From 2871a834702089171223947f796c720f30019841 Mon Sep 17 00:00:00 2001 From: Patryk Date: Tue, 10 Jun 2025 23:39:58 +0200 Subject: [PATCH] init notice edit --- .../app/(tabs)/dashboard/notice/edit/[id].jsx | 391 ++++++++++++++++ .../app/(tabs)/dashboard/userNotices.jsx | 48 +- ArtisanConnect/app/notice/[id].jsx | 434 +++++++++--------- 3 files changed, 641 insertions(+), 232 deletions(-) create mode 100644 ArtisanConnect/app/(tabs)/dashboard/notice/edit/[id].jsx diff --git a/ArtisanConnect/app/(tabs)/dashboard/notice/edit/[id].jsx b/ArtisanConnect/app/(tabs)/dashboard/notice/edit/[id].jsx new file mode 100644 index 0000000..5cc59dd --- /dev/null +++ b/ArtisanConnect/app/(tabs)/dashboard/notice/edit/[id].jsx @@ -0,0 +1,391 @@ +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, +} 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 { attributes } from "@/data/attributesData"; // Assuming you have a separate file for attributes data} +import { useLocalSearchParams } from "expo-router"; + +export default function EditNotice() { + const { id } = useLocalSearchParams(); + const router = useRouter(); + const { editNotice, fetchNotices, notices } = useNoticesStore(); + const [title, setTitle] = useState(""); + const [description, setDescription] = useState(""); + const [price, setPrice] = useState(""); + const [category, setCategory] = useState(""); + const [image, setImage] = useState([]); + const [images, setImages] = useState([]); + const [isImageLoading, setIsImageLoading] = useState(true); + const [selectItems, setSelectItems] = useState([]); + const [isLoading, setIsLoading] = useState(false); + const [selectedAttributes, setSelectedAttributes] = useState({}); + const { getNoticeById, getAllImagesByNoticeId } = useNoticesStore(); + + 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); + } + }; + + fetchSelectItems(); + + return () => { + isMounted = false; + }; + }, []); + + useEffect(() => { + const notice = notices.find((notice) => notice.noticeId == id); + if (notice) { + setTitle(notice.title || ""); + setDescription(notice.description || ""); + setPrice(notice.price?.toString() || ""); + setCategory(notice.category || ""); + + if (notice.attributes && Array.isArray(notice.attributes)) { + const attributesObj = {}; + notice.attributes.forEach((attr) => { + attributesObj[attr.name] = attr.value; + }); + setSelectedAttributes(attributesObj); + // console.log("Attributes loaded:", attributesObj); + } + } + + const fetchImage = async () => { + setIsImageLoading(true); + try { + const fetchedImages = await getAllImagesByNoticeId(notice.noticeId); + console.log("Fetched images:", fetchedImages); + + if (fetchedImages && fetchedImages.length > 0) { + const imageUris = fetchedImages.map((img) => img.uri); + setImages(fetchedImages); + setImage(imageUris); + console.log("Image URIs set:", imageUris); + } else { + setImages([]); + setImage([]); + } + } catch (err) { + console.error("Error while loading images:", err); + setImages([]); + setImage([]); + } finally { + setIsImageLoading(false); + } + }; + + if (notice) { + fetchImage(); + } + }, [notices]); + + 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 handleEditNotice = async () => { + setError({ + title: !title, + description: !description, + price: !price, + category: !category, + }); + + if (!title || !description || !price || !category) { + console.log("Error in form"); + return; + } + const formattedAttributes = Object.entries(selectedAttributes).map( + ([name, value]) => ({ + name: name, + value: value, + }) + ); + // console.log("Selected attributes:", formattedAttributes); + setIsLoading(true); + try { + const result = await editNotice({ + 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} + + + ))} + + + + + + + ); +} diff --git a/ArtisanConnect/app/(tabs)/dashboard/userNotices.jsx b/ArtisanConnect/app/(tabs)/dashboard/userNotices.jsx index 5bdb786..7da0398 100644 --- a/ArtisanConnect/app/(tabs)/dashboard/userNotices.jsx +++ b/ArtisanConnect/app/(tabs)/dashboard/userNotices.jsx @@ -11,7 +11,7 @@ import { createOrder, createPayment, getOrder } from "@/api/order"; import { Ionicons } from "@expo/vector-icons"; import { useToast, Toast, ToastTitle } from "@/components/ui/toast"; import { useAuthStore } from "@/store/authStore"; -import * as WebBrowser from 'expo-web-browser'; +import * as WebBrowser from "expo-web-browser"; import { useRouter } from "expo-router"; export default function UserNotices() { @@ -71,17 +71,16 @@ export default function UserNotices() { if (paymentResult) { setIsRedirecting(true); - await WebBrowser.openAuthSessionAsync(paymentResult); - setTimeout(async () => { setIsRedirecting(false); try { const lastOrder = await getOrder(result); const lastPayments = lastOrder.payments; - const paymentStatus = lastPayments.length > 0 + const paymentStatus = + lastPayments.length > 0 ? lastPayments[lastPayments.length - 1].status : null; @@ -97,7 +96,6 @@ export default function UserNotices() { showNewToast("Nie udało się sprawdzić statusu płatności."); } }, 300); - } else { console.log(`Nie udało się aktywować ogłoszenia ${noticeId}.`); } @@ -149,17 +147,35 @@ export default function UserNotices() { - - + + + {item.status === "INACTIVE" && ( + + )} + {item.status === "ACTIVE" ? ( - - - ) : ( - Błąd podczas ładowania danych użytkownika - )} - - - - {isMessageFormVisible && ( - - - - - Wyślij wiadomość do {user?.firstName} - + + + ) : ( + Błąd podczas ładowania danych użytkownika + )} + + + + {isMessageFormVisible && ( + + + + + Wyślij wiadomość do {user?.firstName} + - Do: - - {user?.email || "Brak adresu e-mail"} - - Temat: - - Zapytanie o ogłoszenie '{notice.title || "Brak nazwy ogłoszenia"}' - + Do: + + {user?.email || "Brak adresu e-mail"} + + Temat: + + Zapytanie o ogłoszenie ' + {notice.title || "Brak nazwy ogłoszenia"}' + - + - - setIsMessageFormVisible(false)} - className="bg-gray-300 py-2 px-4 rounded-md" - > - Anuluj - - - - {isSending ? ( - - ) : ( - Wyślij - )} - - - - - - )} - - + + setIsMessageFormVisible(false)} + className="bg-gray-300 py-2 px-4 rounded-md" + > + Anuluj + + + {isSending ? ( + + ) : ( + Wyślij + )} + + + + + + )} + + ); }