diff --git a/ArtisanConnect/api/notices.jsx b/ArtisanConnect/api/notices.jsx index bbdf05e..d4aba30 100644 --- a/ArtisanConnect/api/notices.jsx +++ b/ArtisanConnect/api/notices.jsx @@ -1,6 +1,8 @@ import axios from "axios"; +import FormData from 'form-data' -const API_URL = "https://testowe.zikor.pl/api/v1"; +// const API_URL = "https://testowe.zikor.pl/api/v1"; +const API_URL = "http://172.20.10.2:8080/api/v1"; export async function listNotices() { const response = await fetch(`${API_URL}/notices/get/all`); @@ -21,6 +23,26 @@ export async function getNoticeById(noticeId) { return data; } +export async function createNotice(notice) { + try { + const response = await axios.post(`${API_URL}/notices/add`, notice, { + headers: { + "Content-Type": "application/json", + }, + }); + // console.log("Response", response.data, "status code: ", response.status); + // console.log("New notice id: ", response.data.noticeId); + // console.log("Image url: ", notice.image) + + if (response.data.noticeId !== null) { + uploadImage(response.data.noticeId, notice.image); + } + + } catch (error) { + console.log("Error", error.response.data, error.response.status); + } +} + export async function getImageByNoticeId(noticeId) { let imageUrl; try { @@ -37,4 +59,43 @@ export async function getImageByNoticeId(noticeId) { imageUrl = "https://http.cat/404.jpg"; return imageUrl; } +} + +export const uploadImage = async (noticeId, imageUri) => { + console.log("Started upload image"); + + // Utwórz obiekt FormData + const formData = new FormData(); + + // Zdobądź nazwę pliku z URI + const filename = imageUri.split('/').pop(); + + // Określ typ MIME (możesz dostosować lub wykrywać dynamicznie) + const match = /\.(\w+)$/.exec(filename); + const type = match ? `image/${match[1]}` : 'image/jpeg'; + + // Dodaj plik do FormData w formacie akceptowanym przez serwer + formData.append('file', { + uri: imageUri, + name: filename, + type: type, + }); + + try { + const response = await axios.post( + `${API_URL}/images/upload/${noticeId}`, + formData, + { + headers: { + 'Content-Type': 'multipart/form-data', + }, + } + ); + console.info('Upload successful:', response.data); + return response.data; + } catch (error) { + console.log("imageURI:", imageUri); + console.error('Error uploading image:', error.response.data, error.response.status); + throw error; + } } \ No newline at end of file diff --git a/ArtisanConnect/app.json b/ArtisanConnect/app.json index 4e10839..49414e7 100644 --- a/ArtisanConnect/app.json +++ b/ArtisanConnect/app.json @@ -26,7 +26,13 @@ "favicon": "./assets/favicon.png" }, "plugins": [ - "expo-router" + "expo-router", + [ + "expo-image-picker", + { + "photosPermission": "The app accesses your photos to let you share them with your friends." + } + ] ] } } diff --git a/ArtisanConnect/app/(tabs)/notice/create.jsx b/ArtisanConnect/app/(tabs)/notice/create.jsx index 9eddf21..337f3d6 100644 --- a/ArtisanConnect/app/(tabs)/notice/create.jsx +++ b/ArtisanConnect/app/(tabs)/notice/create.jsx @@ -1,4 +1,184 @@ +import { useState } from "react"; +import { Image, StyleSheet } 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 * as ImagePicker from 'expo-image-picker'; +import { + Select, + SelectTrigger, + SelectInput, + SelectIcon, + SelectPortal, + SelectBackdrop, + SelectContent, + SelectDragIndicator, + SelectDragIndicatorWrapper, + SelectItem, +} from "@/components/ui/select"; + +import { ChevronDownIcon } from "@/components/ui/icon"; +import { useMutation } from "@tanstack/react-query"; +import {createNotice, uploadImage} from "@/api/notices"; + export default function CreateNotice() { - return Tworzenie ogłoszenia; + const [title, setTitle] = useState(""); + const [description, setDescription] = useState(""); + const [price, setPrice] = useState(""); + const [category, setCategory] = useState(""); + const [image, setImage] = useState(null); + + 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 noticeMutation = useMutation({ + mutationFn: () => + createNotice({ + title: title, + clientId: 1, + description: description, + price: parseFloat(price), + category: category, + status: "ACTIVE", + image: image, + }), + onSuccess: () => { + console.log("Notice created successfully"); + }, + onError: (error) => { + console.error("Error creating notice"); + }, + }); + + const addNotice = () => { + setError({ + title: !title, + description: !description, + price: !price, + category: !category, + }); + + if (!title || !description || !price || !category) { + console.log("Error in form"); + return; + } + noticeMutation.mutate(); + }; + + const pickImage = async () => { + // No permissions request is necessary for launching the image library + let result = await ImagePicker.launchImageLibraryAsync({ + mediaTypes: ['images', 'videos'], + allowsEditing: true, + aspect: [4, 3], + quality: 1, + }); + + if (!result.canceled) { + // await uploadImage(1, result.assets[0].uri); + setImage(result.assets[0].uri); + } + }; + + return ( + + + + Zdjęcie + + {image && } + + + + Tytuł + + setTitle(value)} + /> + + + + + Opis + + + + + Cena + + setPrice(value)} + /> + + + + Kategoria + + + + + + ); } diff --git a/ArtisanConnect/components/ui/form-control/index.tsx b/ArtisanConnect/components/ui/form-control/index.tsx new file mode 100644 index 0000000..f1cfcdf --- /dev/null +++ b/ArtisanConnect/components/ui/form-control/index.tsx @@ -0,0 +1,468 @@ +'use client'; +import { Text, View } from 'react-native'; +import React from 'react'; +import { createFormControl } from '@gluestack-ui/form-control'; +import { tva } from '@gluestack-ui/nativewind-utils/tva'; +import { + withStyleContext, + useStyleContext, +} from '@gluestack-ui/nativewind-utils/withStyleContext'; +import { cssInterop } from 'nativewind'; +import type { VariantProps } from '@gluestack-ui/nativewind-utils'; +import { PrimitiveIcon, UIIcon } from '@gluestack-ui/icon'; + +const SCOPE = 'FORM_CONTROL'; + +const formControlStyle = tva({ + base: 'flex flex-col', + variants: { + size: { + sm: '', + md: '', + lg: '', + }, + }, +}); + +const formControlErrorIconStyle = tva({ + base: 'text-error-700 fill-none', + variants: { + size: { + '2xs': 'h-3 w-3', + 'xs': 'h-3.5 w-3.5', + 'sm': 'h-4 w-4', + 'md': 'h-[18px] w-[18px]', + 'lg': 'h-5 w-5', + 'xl': 'h-6 w-6', + }, + }, +}); + +const formControlErrorStyle = tva({ + base: 'flex flex-row justify-start items-center mt-1 gap-1', +}); + +const formControlErrorTextStyle = tva({ + base: 'text-error-700', + variants: { + isTruncated: { + true: 'web:truncate', + }, + bold: { + true: 'font-bold', + }, + underline: { + true: 'underline', + }, + strikeThrough: { + true: 'line-through', + }, + size: { + '2xs': 'text-2xs', + 'xs': 'text-xs', + 'sm': 'text-sm', + 'md': 'text-base', + 'lg': 'text-lg', + 'xl': 'text-xl', + '2xl': 'text-2xl', + '3xl': 'text-3xl', + '4xl': 'text-4xl', + '5xl': 'text-5xl', + '6xl': 'text-6xl', + }, + sub: { + true: 'text-xs', + }, + italic: { + true: 'italic', + }, + highlight: { + true: 'bg-yellow-500', + }, + }, +}); + +const formControlHelperStyle = tva({ + base: 'flex flex-row justify-start items-center mt-1', +}); + +const formControlHelperTextStyle = tva({ + base: 'text-typography-500', + variants: { + isTruncated: { + true: 'web:truncate', + }, + bold: { + true: 'font-bold', + }, + underline: { + true: 'underline', + }, + strikeThrough: { + true: 'line-through', + }, + size: { + '2xs': 'text-2xs', + 'xs': 'text-xs', + 'sm': 'text-xs', + 'md': 'text-sm', + 'lg': 'text-base', + 'xl': 'text-xl', + '2xl': 'text-2xl', + '3xl': 'text-3xl', + '4xl': 'text-4xl', + '5xl': 'text-5xl', + '6xl': 'text-6xl', + }, + sub: { + true: 'text-xs', + }, + italic: { + true: 'italic', + }, + highlight: { + true: 'bg-yellow-500', + }, + }, +}); + +const formControlLabelStyle = tva({ + base: 'flex flex-row justify-start items-center mb-1', +}); + +const formControlLabelTextStyle = tva({ + base: 'font-medium text-typography-900', + variants: { + isTruncated: { + true: 'web:truncate', + }, + bold: { + true: 'font-bold', + }, + underline: { + true: 'underline', + }, + strikeThrough: { + true: 'line-through', + }, + size: { + '2xs': 'text-2xs', + 'xs': 'text-xs', + 'sm': 'text-sm', + 'md': 'text-base', + 'lg': 'text-lg', + 'xl': 'text-xl', + '2xl': 'text-2xl', + '3xl': 'text-3xl', + '4xl': 'text-4xl', + '5xl': 'text-5xl', + '6xl': 'text-6xl', + }, + sub: { + true: 'text-xs', + }, + italic: { + true: 'italic', + }, + highlight: { + true: 'bg-yellow-500', + }, + }, +}); + +const formControlLabelAstrickStyle = tva({ + base: 'font-medium text-typography-900', + variants: { + isTruncated: { + true: 'web:truncate', + }, + bold: { + true: 'font-bold', + }, + underline: { + true: 'underline', + }, + strikeThrough: { + true: 'line-through', + }, + size: { + '2xs': 'text-2xs', + 'xs': 'text-xs', + 'sm': 'text-sm', + 'md': 'text-base', + 'lg': 'text-lg', + 'xl': 'text-xl', + '2xl': 'text-2xl', + '3xl': 'text-3xl', + '4xl': 'text-4xl', + '5xl': 'text-5xl', + '6xl': 'text-6xl', + }, + sub: { + true: 'text-xs', + }, + italic: { + true: 'italic', + }, + highlight: { + true: 'bg-yellow-500', + }, + }, +}); + +type IFormControlLabelAstrickProps = React.ComponentPropsWithoutRef< + typeof Text +> & + VariantProps; + +const FormControlLabelAstrick = React.forwardRef< + React.ComponentRef, + IFormControlLabelAstrickProps +>(function FormControlLabelAstrick({ className, ...props }, ref) { + const { size: parentSize } = useStyleContext(SCOPE); + + return ( + + ); +}); + +export const UIFormControl = createFormControl({ + Root: withStyleContext(View, SCOPE), + Error: View, + ErrorText: Text, + ErrorIcon: UIIcon, + Label: View, + LabelText: Text, + LabelAstrick: FormControlLabelAstrick, + Helper: View, + HelperText: Text, +}); + +cssInterop(PrimitiveIcon, { + className: { + target: 'style', + nativeStyleToProp: { + height: true, + width: true, + fill: true, + color: true, + stroke: true, + }, + }, +}); + +type IFormControlProps = React.ComponentProps & + VariantProps; + +const FormControl = React.forwardRef< + React.ComponentRef, + IFormControlProps +>(function FormControl({ className, size = 'md', ...props }, ref) { + return ( + + ); +}); + +type IFormControlErrorProps = React.ComponentProps & + VariantProps; + +const FormControlError = React.forwardRef< + React.ComponentRef, + IFormControlErrorProps +>(function FormControlError({ className, ...props }, ref) { + return ( + + ); +}); + +type IFormControlErrorTextProps = React.ComponentProps< + typeof UIFormControl.Error.Text +> & + VariantProps; + +const FormControlErrorText = React.forwardRef< + React.ComponentRef, + IFormControlErrorTextProps +>(function FormControlErrorText({ className, size, ...props }, ref) { + const { size: parentSize } = useStyleContext(SCOPE); + return ( + + ); +}); + +type IFormControlErrorIconProps = React.ComponentProps< + typeof UIFormControl.Error.Icon +> & + VariantProps & { + height?: number; + width?: number; + }; + +const FormControlErrorIcon = React.forwardRef< + React.ComponentRef, + IFormControlErrorIconProps +>(function FormControlErrorIcon({ className, size, ...props }, ref) { + const { size: parentSize } = useStyleContext(SCOPE); + + if (typeof size === 'number') { + return ( + + ); + } else if ( + (props.height !== undefined || props.width !== undefined) && + size === undefined + ) { + return ( + + ); + } + return ( + + ); +}); + +type IFormControlLabelProps = React.ComponentProps & + VariantProps; + +const FormControlLabel = React.forwardRef< + React.ComponentRef, + IFormControlLabelProps +>(function FormControlLabel({ className, ...props }, ref) { + return ( + + ); +}); + +type IFormControlLabelTextProps = React.ComponentProps< + typeof UIFormControl.Label.Text +> & + VariantProps; + +const FormControlLabelText = React.forwardRef< + React.ComponentRef, + IFormControlLabelTextProps +>(function FormControlLabelText({ className, size, ...props }, ref) { + const { size: parentSize } = useStyleContext(SCOPE); + + return ( + + ); +}); + +type IFormControlHelperProps = React.ComponentProps< + typeof UIFormControl.Helper +> & + VariantProps; + +const FormControlHelper = React.forwardRef< + React.ComponentRef, + IFormControlHelperProps +>(function FormControlHelper({ className, ...props }, ref) { + return ( + + ); +}); + +type IFormControlHelperTextProps = React.ComponentProps< + typeof UIFormControl.Helper.Text +> & + VariantProps; + +const FormControlHelperText = React.forwardRef< + React.ComponentRef, + IFormControlHelperTextProps +>(function FormControlHelperText({ className, size, ...props }, ref) { + const { size: parentSize } = useStyleContext(SCOPE); + + return ( + + ); +}); + +FormControl.displayName = 'FormControl'; +FormControlError.displayName = 'FormControlError'; +FormControlErrorText.displayName = 'FormControlErrorText'; +FormControlErrorIcon.displayName = 'FormControlErrorIcon'; +FormControlLabel.displayName = 'FormControlLabel'; +FormControlLabelText.displayName = 'FormControlLabelText'; +FormControlLabelAstrick.displayName = 'FormControlLabelAstrick'; +FormControlHelper.displayName = 'FormControlHelper'; +FormControlHelperText.displayName = 'FormControlHelperText'; + +export { + FormControl, + FormControlError, + FormControlErrorText, + FormControlErrorIcon, + FormControlLabel, + FormControlLabelText, + FormControlLabelAstrick, + FormControlHelper, + FormControlHelperText, +}; diff --git a/ArtisanConnect/package-lock.json b/ArtisanConnect/package-lock.json index 94c3117..766434d 100644 --- a/ArtisanConnect/package-lock.json +++ b/ArtisanConnect/package-lock.json @@ -10,20 +10,29 @@ "dependencies": { "@expo/html-elements": "^0.4.2", "@expo/vector-icons": "^14.1.0", + "@gluestack-ui/actionsheet": "^0.2.53", "@gluestack-ui/button": "^1.0.14", + "@gluestack-ui/form-control": "^0.1.19", "@gluestack-ui/icon": "^0.1.27", "@gluestack-ui/image": "^0.1.17", + "@gluestack-ui/input": "^0.1.38", "@gluestack-ui/nativewind-utils": "^1.0.26", "@gluestack-ui/overlay": "^0.1.22", + "@gluestack-ui/select": "^0.1.31", + "@gluestack-ui/textarea": "^0.1.25", "@gluestack-ui/toast": "^1.0.9", + "@legendapp/motion": "^2.4.0", "@tanstack/react-query": "^5.74.4", "axios": "^1.9.0", "babel-plugin-module-resolver": "^5.0.2", "expo": "~52.0.46", "expo-constants": "~17.0.8", + "expo-image-picker": "~16.0.6", "expo-linking": "~7.0.5", "expo-router": "~4.0.20", "expo-status-bar": "~2.0.1", + "form-data": "^4.0.2", + "fs": "^0.0.1-security", "nativewind": "^4.1.23", "react": "18.3.1", "react-dom": "18.3.1", @@ -1718,6 +1727,21 @@ "expo-internal": "build/bin/cli" } }, + "node_modules/@expo/cli/node_modules/form-data": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.3.tgz", + "integrity": "sha512-q5YBMeWy6E2Un0nMGWMgI65MAKtaylxfNJGJxpGh45YDciZB4epbWpaAfImil6CPAPTYB4sh0URQNDRIZG5F2w==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "mime-types": "^2.1.35" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/@expo/cli/node_modules/semver": { "version": "7.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", @@ -2335,6 +2359,24 @@ "tslib": "^2.8.0" } }, + "node_modules/@gluestack-ui/actionsheet": { + "version": "0.2.53", + "resolved": "https://registry.npmjs.org/@gluestack-ui/actionsheet/-/actionsheet-0.2.53.tgz", + "integrity": "sha512-93qHvq6BHezJ7wt2lce4OQ38wXCGsDtglj5nlmwo2T41vj4ubOtDVoSUhXT+hfH0EmRr0TxFNeFqIgesO46qVw==", + "dependencies": { + "@gluestack-ui/hooks": "0.1.13", + "@gluestack-ui/overlay": "^0.1.22", + "@gluestack-ui/transitions": "^0.1.11", + "@gluestack-ui/utils": "^0.1.15", + "@react-native-aria/dialog": "^0.0.5", + "@react-native-aria/focus": "^0.2.9", + "@react-native-aria/interactions": "0.2.16" + }, + "peerDependencies": { + "react": ">=16", + "react-dom": ">=16" + } + }, "node_modules/@gluestack-ui/button": { "version": "1.0.14", "resolved": "https://registry.npmjs.org/@gluestack-ui/button/-/button-1.0.14.tgz", @@ -2349,6 +2391,19 @@ "react-dom": ">=16" } }, + "node_modules/@gluestack-ui/form-control": { + "version": "0.1.19", + "resolved": "https://registry.npmjs.org/@gluestack-ui/form-control/-/form-control-0.1.19.tgz", + "integrity": "sha512-6YbPbi/RZrXc5DyVPbxPV17FYaBoEl1yAdSwut8iE6n+yQekjluINrh2q5ZPWF2SGmyo7VSNcL85yeU5I97xHg==", + "dependencies": { + "@gluestack-ui/utils": "^0.1.14", + "@react-native-aria/focus": "^0.2.9" + }, + "peerDependencies": { + "react": ">=16", + "react-dom": ">=16" + } + }, "node_modules/@gluestack-ui/hooks": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/@gluestack-ui/hooks/-/hooks-0.1.13.tgz", @@ -2386,6 +2441,21 @@ "react-dom": ">=16" } }, + "node_modules/@gluestack-ui/input": { + "version": "0.1.38", + "resolved": "https://registry.npmjs.org/@gluestack-ui/input/-/input-0.1.38.tgz", + "integrity": "sha512-NzwDOXkkMYzBQ0h7UnhKA2h54/qlxDxMFGXykkmYOl7mc7QJc1aJaveo4yMHtpYvcQG17xLyD+Z+5CQYA76nvw==", + "dependencies": { + "@gluestack-ui/form-control": "^0.1.19", + "@gluestack-ui/utils": "^0.1.15", + "@react-native-aria/focus": "^0.2.9", + "@react-native-aria/interactions": "0.2.16" + }, + "peerDependencies": { + "react": ">=16", + "react-dom": ">=16" + } + }, "node_modules/@gluestack-ui/nativewind-utils": { "version": "1.0.26", "resolved": "https://registry.npmjs.org/@gluestack-ui/nativewind-utils/-/nativewind-utils-1.0.26.tgz", @@ -2440,6 +2510,36 @@ "react-dom": ">=16" } }, + "node_modules/@gluestack-ui/select": { + "version": "0.1.31", + "resolved": "https://registry.npmjs.org/@gluestack-ui/select/-/select-0.1.31.tgz", + "integrity": "sha512-d8vfdCK4VFBYEDYMCTRYcZCWvYaf7UWMJGg2uMnutHA8Y4sDXjKR5P821xKdh75QVkmZRZm1MdzSWFvXUzAlgg==", + "dependencies": { + "@gluestack-ui/form-control": "^0.1.19", + "@gluestack-ui/hooks": "0.1.13", + "@gluestack-ui/utils": "^0.1.14", + "@react-native-aria/focus": "^0.2.9" + }, + "peerDependencies": { + "react": ">=16", + "react-dom": ">=16" + } + }, + "node_modules/@gluestack-ui/textarea": { + "version": "0.1.25", + "resolved": "https://registry.npmjs.org/@gluestack-ui/textarea/-/textarea-0.1.25.tgz", + "integrity": "sha512-hXJx9LYSfrx7/Lrh2D2cTjr7PqvdkxJXBv2VydcR01X4WEN34DZkik+at/qk5FBw+p4t0vE+BTAK3IoMJwWvGg==", + "dependencies": { + "@gluestack-ui/form-control": "^0.1.19", + "@gluestack-ui/utils": "^0.1.14", + "@react-native-aria/focus": "^0.2.9", + "@react-native-aria/interactions": "^0.2.16" + }, + "peerDependencies": { + "react": ">=16", + "react-dom": ">=16" + } + }, "node_modules/@gluestack-ui/toast": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@gluestack-ui/toast/-/toast-1.0.9.tgz", @@ -2828,6 +2928,34 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@legendapp/motion": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@legendapp/motion/-/motion-2.4.0.tgz", + "integrity": "sha512-AAYpRLGvxGD5hIGl9sVHyoUufr66zoH82PuxYcKiPSMdCBI3jwZFWh6CuHjV1leRKVIRk2py1rSvIVabG8eqcw==", + "license": "MIT", + "dependencies": { + "@legendapp/tools": "2.0.1" + }, + "peerDependencies": { + "nativewind": "*", + "react": ">=16", + "react-native": "*" + } + }, + "node_modules/@legendapp/tools": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@legendapp/tools/-/tools-2.0.1.tgz", + "integrity": "sha512-Kxt0HWvWElRK6oybHRzcYxdgaKGwuaiRNreS7usW7QuHXRIHaH4yMcW2YNRG4DHE5fpefv+Bno/BohQcCE4FaA==", + "license": "MIT", + "peerDependencies": { + "react": ">=16" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + } + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -2922,6 +3050,24 @@ "react": "^16.8 || ^17.0 || ^18.0" } }, + "node_modules/@react-aria/dialog": { + "version": "3.5.24", + "resolved": "https://registry.npmjs.org/@react-aria/dialog/-/dialog-3.5.24.tgz", + "integrity": "sha512-tw0WH89gVpHMI5KUQhuzRE+IYCc9clRfDvCppuXNueKDrZmrQKbeoU6d0b5WYRsBur2+d7ErtvpLzHVqE1HzfA==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/interactions": "^3.25.0", + "@react-aria/overlays": "^3.27.0", + "@react-aria/utils": "^3.28.2", + "@react-types/dialog": "^3.5.17", + "@react-types/shared": "^3.29.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, "node_modules/@react-aria/focus": { "version": "3.20.2", "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.20.2.tgz", @@ -3048,6 +3194,22 @@ "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, + "node_modules/@react-native-aria/dialog": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/@react-native-aria/dialog/-/dialog-0.0.5.tgz", + "integrity": "sha512-ZThiWyymf3WiA2EdjStV32pTL3RjAb7H/CL0Zsd1wKNuw1lU9HX6h4UIUpt0MZhcFCUnZjCovNtU9IRwbbdj/Q==", + "license": "MIT", + "dependencies": { + "@react-aria/dialog": "*", + "@react-native-aria/utils": "0.2.12", + "@react-types/dialog": "*", + "@react-types/shared": "*" + }, + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, "node_modules/@react-native-aria/focus": { "version": "0.2.9", "resolved": "https://registry.npmjs.org/@react-native-aria/focus/-/focus-0.2.9.tgz", @@ -3753,6 +3915,19 @@ "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, + "node_modules/@react-types/dialog": { + "version": "3.5.17", + "resolved": "https://registry.npmjs.org/@react-types/dialog/-/dialog-3.5.17.tgz", + "integrity": "sha512-rKe2WrT272xuCH13euegBGjJAORYXJpHsX2hlu/f02TmMG4nSLss9vKBnY2N7k7nci65k5wDTW6lcsvQ4Co5zQ==", + "license": "Apache-2.0", + "dependencies": { + "@react-types/overlays": "^3.8.14", + "@react-types/shared": "^3.29.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, "node_modules/@react-types/overlays": { "version": "3.8.14", "resolved": "https://registry.npmjs.org/@react-types/overlays/-/overlays-3.8.14.tgz", @@ -4294,21 +4469,6 @@ "proxy-from-env": "^1.1.0" } }, - "node_modules/axios/node_modules/form-data": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", - "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==", - "license": "MIT", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "es-set-tostringtag": "^2.1.0", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/babel-core": { "version": "7.0.0-bridge.0", "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz", @@ -6212,6 +6372,27 @@ "react": "*" } }, + "node_modules/expo-image-loader": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/expo-image-loader/-/expo-image-loader-5.0.0.tgz", + "integrity": "sha512-Eg+5FHtyzv3Jjw9dHwu2pWy4xjf8fu3V0Asyy42kO+t/FbvW/vjUixpTjPtgKQLQh+2/9Nk4JjFDV6FwCnF2ZA==", + "license": "MIT", + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-image-picker": { + "version": "16.0.6", + "resolved": "https://registry.npmjs.org/expo-image-picker/-/expo-image-picker-16.0.6.tgz", + "integrity": "sha512-HN4xZirFjsFDIsWFb12AZh19fRzuvZjj2ll17cGr19VNRP06S/VPQU3Tdccn5vwUzQhOBlLu704CnNm278boiQ==", + "license": "MIT", + "dependencies": { + "expo-image-loader": "~5.0.0" + }, + "peerDependencies": { + "expo": "*" + } + }, "node_modules/expo-keep-awake": { "version": "14.0.3", "resolved": "https://registry.npmjs.org/expo-keep-awake/-/expo-keep-awake-14.0.3.tgz", @@ -6633,15 +6814,15 @@ } }, "node_modules/form-data": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.3.tgz", - "integrity": "sha512-q5YBMeWy6E2Un0nMGWMgI65MAKtaylxfNJGJxpGh45YDciZB4epbWpaAfImil6CPAPTYB4sh0URQNDRIZG5F2w==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", + "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==", "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", - "mime-types": "^2.1.35" + "mime-types": "^2.1.12" }, "engines": { "node": ">= 6" @@ -6665,6 +6846,12 @@ "node": ">= 0.6" } }, + "node_modules/fs": { + "version": "0.0.1-security", + "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz", + "integrity": "sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w==", + "license": "ISC" + }, "node_modules/fs-extra": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", diff --git a/ArtisanConnect/package.json b/ArtisanConnect/package.json index 17babd5..bcab898 100644 --- a/ArtisanConnect/package.json +++ b/ArtisanConnect/package.json @@ -11,20 +11,29 @@ "dependencies": { "@expo/html-elements": "^0.4.2", "@expo/vector-icons": "^14.1.0", + "@gluestack-ui/actionsheet": "^0.2.53", "@gluestack-ui/button": "^1.0.14", + "@gluestack-ui/form-control": "^0.1.19", "@gluestack-ui/icon": "^0.1.27", "@gluestack-ui/image": "^0.1.17", + "@gluestack-ui/input": "^0.1.38", "@gluestack-ui/nativewind-utils": "^1.0.26", "@gluestack-ui/overlay": "^0.1.22", + "@gluestack-ui/select": "^0.1.31", + "@gluestack-ui/textarea": "^0.1.25", "@gluestack-ui/toast": "^1.0.9", + "@legendapp/motion": "^2.4.0", "@tanstack/react-query": "^5.74.4", "axios": "^1.9.0", "babel-plugin-module-resolver": "^5.0.2", "expo": "~52.0.46", "expo-constants": "~17.0.8", + "expo-image-picker": "~16.0.6", "expo-linking": "~7.0.5", "expo-router": "~4.0.20", "expo-status-bar": "~2.0.1", + "form-data": "^4.0.2", + "fs": "^0.0.1-security", "nativewind": "^4.1.23", "react": "18.3.1", "react-dom": "18.3.1",