From 413c9ac5ee445aa7c73ea24db1e5d63dcc44e1de Mon Sep 17 00:00:00 2001 From: Patryk Date: Tue, 10 Jun 2025 20:39:29 +0200 Subject: [PATCH 1/2] add attributes --- ArtisanConnect/app/(tabs)/notice/create.jsx | 608 +++++++++++--------- 1 file changed, 344 insertions(+), 264 deletions(-) diff --git a/ArtisanConnect/app/(tabs)/notice/create.jsx b/ArtisanConnect/app/(tabs)/notice/create.jsx index 89d9dad..a2e7011 100644 --- a/ArtisanConnect/app/(tabs)/notice/create.jsx +++ b/ArtisanConnect/app/(tabs)/notice/create.jsx @@ -1,280 +1,360 @@ -import {useState, useEffect} from "react"; -import {Image, StyleSheet, KeyboardAvoidingView, Platform, ActivityIndicator} from "react-native"; -import {Button, ButtonText} from "@/components/ui/button"; -import {FormControl} from "@/components/ui/form-control"; -import {Input, InputField} from "@/components/ui/input"; -import {Text} from "@/components/ui/text"; -import {VStack} from "@/components/ui/vstack"; -import {Textarea, TextareaInput} from "@/components/ui/textarea"; -import {ScrollView} from "@gluestack-ui/themed"; -import {Box} from "@/components/ui/box"; +import { useState, useEffect } from "react"; +import { + Image, + StyleSheet, + KeyboardAvoidingView, + Platform, + ActivityIndicator, +} from "react-native"; +import { Button, ButtonText } from "@/components/ui/button"; +import { FormControl } from "@/components/ui/form-control"; +import { Input, InputField } from "@/components/ui/input"; +import { Text } from "@/components/ui/text"; +import { VStack } from "@/components/ui/vstack"; +import { Textarea, TextareaInput } from "@/components/ui/textarea"; +import { ScrollView } from "@gluestack-ui/themed"; +import { Box } from "@/components/ui/box"; import * as ImagePicker from "expo-image-picker"; import { - Select, - SelectTrigger, - SelectInput, - SelectIcon, - SelectPortal, - SelectBackdrop, - SelectContent, - SelectItem, - SelectScrollView, + Select, + SelectTrigger, + SelectInput, + SelectIcon, + SelectPortal, + SelectBackdrop, + SelectContent, + SelectItem, + SelectScrollView, } from "@/components/ui/select"; -import {ChevronDownIcon} from "@/components/ui/icon"; -import {useNoticesStore} from "@/store/noticesStore"; -import {listCategories} from "@/api/categories"; -import {useRouter} from "expo-router"; +import { ChevronDownIcon } from "@/components/ui/icon"; +import { useNoticesStore } from "@/store/noticesStore"; +import { listCategories } from "@/api/categories"; +import { useRouter } from "expo-router"; export default function CreateNotice() { - const router = useRouter(); - const {addNotice, fetchNotices} = useNoticesStore(); - const [title, setTitle] = useState(""); - const [description, setDescription] = useState(""); - const [price, setPrice] = useState(""); - const [category, setCategory] = useState(""); - const [image, setImage] = useState([]); - const [selectItems, setSelectItems] = useState([]); - const [isLoading, setIsLoading] = useState(false); + const router = useRouter(); + const { addNotice, fetchNotices } = useNoticesStore(); + const [title, setTitle] = useState(""); + const [description, setDescription] = useState(""); + const [price, setPrice] = useState(""); + const [category, setCategory] = useState(""); + const [image, setImage] = useState([]); + const [selectItems, setSelectItems] = useState([]); + const [isLoading, setIsLoading] = useState(false); + const [selectedAttributes, setSelectedAttributes] = useState({}); - useEffect(() => { - let isMounted = true; + useEffect(() => { + let isMounted = true; - const fetchSelectItems = async () => { - try { - let data = await listCategories(); - if (isMounted && Array.isArray(data)) { - setSelectItems(data); - } - } catch (error) { - console.error("Error fetching select items:", error); - } - }; + const fetchSelectItems = async () => { + try { + let data = await listCategories(); + if (isMounted && Array.isArray(data)) { + setSelectItems(data); + } + } catch (error) { + console.error("Error fetching select items:", error); + } + }; - fetchSelectItems(); + fetchSelectItems(); - return () => { - isMounted = false; - }; - }, []); + return () => { + isMounted = false; + }; + }, []); - const [error, setError] = useState({ - title: false, - description: false, - price: false, - category: false, + const [error, setError] = useState({ + title: false, + description: false, + price: false, + category: false, + }); + + const styles = StyleSheet.create({ + container: { + flex: 1, + alignItems: "center", + justifyContent: "center", + }, + image: { + width: 100, + height: 100, + }, + }); + + const attributes = { + Kolor: [ + "Zielony", + "Czerwony", + "Niebieski", + "Żółty", + "Biały", + "Czarny", + "Różowy", + "Szary", + "Fioletowy", + "Pomarańczowy", + "Inny", + ], + Materiał: [ + "Bawełna", + "Wełna", + "Syntetyk", + "Skóra", + "Len", + "Jedwab", + "Poliester", + "Akryl", + "Wiskoza", + "Nylon", + "Inny", + ], + }; + + const handleAddNotice = async () => { + setError({ + title: !title, + description: !description, + price: !price, + category: !category, }); - const styles = StyleSheet.create({ - container: { - flex: 1, - alignItems: "center", - justifyContent: "center", - }, - image: { - width: 100, - height: 100, - }, - }); - - const handleAddNotice = async () => { - setError({ - title: !title, - description: !description, - price: !price, - category: !category, - }); - - if (!title || !description || !price || !category) { - console.log("Error in form"); - return; - } - - setIsLoading(true); - try { - const result = await addNotice({ - title: title, - description: description, - price: price, - category: category, - status: "INACTIVE", - image: image, - }); - - if (result) { - console.log("Notice created successfully with ID: ", result.noticeId); - await fetchNotices(); - clearForm(); - - router.push("/(tabs)/dashboard/userNotices"); - } - } catch (error) { - console.error("Error creating notice. Error message: ", error.message); - } finally { - setIsLoading(false); - } - }; - - const takePicture = async () => { - const {status} = await ImagePicker.requestCameraPermissionsAsync(); - if (status !== "granted") { - return; - } - const result = await ImagePicker.launchCameraAsync({ - allowsEditing: false, - }); - - if (!result.canceled && result.assets) { - setImage(result.assets.map((asset) => asset.uri)); - } - }; - - const pickImage = async () => { - let result = await ImagePicker.launchImageLibraryAsync({ - mediaTypes: "images", - selectionLimit: 8, - allowsEditing: false, - allowsMultipleSelection: true, - aspect: [4, 3], - quality: 0.5, - }); - - if (!result.canceled) { - setImage(result.assets.map((asset) => asset.uri)); - } - }; - - const clearForm = () => { - setTitle(""); - setDescription(""); - setPrice(""); - setCategory(""); - setImage([]); - setError({ - title: false, - description: false, - price: false, - category: false, - }); - }; - - if (isLoading) { - return ( - - - - Dodajemy ogłoszenie... - - - ); + if (!title || !description || !price || !category) { + console.log("Error in form"); + return; } - - return ( - - - - - - Zdjęcia - - - - Pierwsze zdjęcie będzie zdjęciem głównym - - {image && image.length > 0 && ( - - {image.map((img, index) => ( - - ))} - - )} - - - - Tytuł - - setTitle(value)} - /> - - - - - Opis - - - - - Cena - - setPrice(value)} - /> - - - - Kategoria - - - - - - - + const formattedAttributes = Object.entries(selectedAttributes).map( + ([name, value]) => ({ + name: name, + value: value, + }) ); + // console.log("Selected attributes:", formattedAttributes); + setIsLoading(true); + try { + const result = await addNotice({ + title: title, + description: description, + price: price, + category: category, + status: "INACTIVE", + image: image, + attributes: formattedAttributes, + }); + + if (result) { + console.log("Notice created successfully with ID: ", result.noticeId); + await fetchNotices(); + clearForm(); + + router.push("/(tabs)/dashboard/userNotices"); + } + } catch (error) { + console.error("Error creating notice. Error message: ", error.message); + } finally { + setIsLoading(false); + } + }; + + const takePicture = async () => { + const { status } = await ImagePicker.requestCameraPermissionsAsync(); + if (status !== "granted") { + return; + } + const result = await ImagePicker.launchCameraAsync({ + allowsEditing: false, + }); + + if (!result.canceled && result.assets) { + setImage(result.assets.map((asset) => asset.uri)); + } + }; + + const pickImage = async () => { + let result = await ImagePicker.launchImageLibraryAsync({ + mediaTypes: "images", + selectionLimit: 8, + allowsEditing: false, + allowsMultipleSelection: true, + aspect: [4, 3], + quality: 0.5, + }); + + if (!result.canceled) { + setImage(result.assets.map((asset) => asset.uri)); + } + }; + + const clearForm = () => { + setTitle(""); + setDescription(""); + setPrice(""); + setCategory(""); + setImage([]); + setSelectedAttributes({}); + setError({ + title: false, + description: false, + price: false, + category: false, + }); + }; + + if (isLoading) { + return ( + + + + Dodajemy ogłoszenie... + + + ); + } + + return ( + + + + + + Zdjęcia + + + + Pierwsze zdjęcie będzie zdjęciem głównym + + {image && image.length > 0 && ( + + {image.map((img, index) => ( + + ))} + + )} + + + + Tytuł + + setTitle(value)} + /> + + + + + Opis + + + + + Cena + + setPrice(value)} + /> + + + + Kategoria + + + + {Object.entries(attributes).map(([label, options]) => ( + + {label} + + + ))} + + + + + + + ); } From 83f105eff16cf6463d9bdcff193edcb008fe0d55 Mon Sep 17 00:00:00 2001 From: Patryk Date: Tue, 10 Jun 2025 20:42:13 +0200 Subject: [PATCH 2/2] add required label --- ArtisanConnect/app/(tabs)/notice/create.jsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ArtisanConnect/app/(tabs)/notice/create.jsx b/ArtisanConnect/app/(tabs)/notice/create.jsx index a2e7011..06b7af4 100644 --- a/ArtisanConnect/app/(tabs)/notice/create.jsx +++ b/ArtisanConnect/app/(tabs)/notice/create.jsx @@ -248,7 +248,7 @@ export default function CreateNotice() { - Tytuł + Tytuł* - Opis + Opis*