diff --git a/.vscode/settings.json b/.vscode/settings.json index 66243f6..ca831ba 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -5,8 +5,8 @@ "**/.hg": true, "**/CVS": true, "**/.DS_Store": true, - "node_modules": true, - ".next": true + "node_modules": false, + ".next": false }, "eslint.lintTask.enable": true, "typescript.tsdk": "node_modules/typescript/lib", diff --git a/app/activity/[id]/components/activity-header.tsx b/app/activity/[id]/components/activity-header.tsx index 81b1219..938bfa4 100644 --- a/app/activity/[id]/components/activity-header.tsx +++ b/app/activity/[id]/components/activity-header.tsx @@ -1,12 +1,15 @@ 'use client' import { Heading, Box, Flex, Spacer, Text, IconButton } from '@chakra-ui/react' +import { useRouter } from 'next/navigation' import { FiClock, FiMapPin, FiLink2, FiEdit3, FiTrash2 } from 'react-icons/fi' +import { useActivityDelete } from '@/activity/hooks/useActivityDelete' import { Link } from '@/components/link' import { formatToDateTime } from '@/libs/utils' import { customColors } from '@/theme/color' type ActivityHeaderProps = { + id: string title: string time_from: string | null time_to?: string | null @@ -15,12 +18,16 @@ type ActivityHeaderProps = { } export const ActivityHeader = ({ + id, title, time_from, time_to, address, url }: ActivityHeaderProps) => { + const router = useRouter() + const { deleteActivity, isActivityDeleting } = useActivityDelete() + return ( <> @@ -31,7 +38,7 @@ export const ActivityHeader = ({ {}} + onClick={() => router.push(`/activity/${id}/edit`)} p={{ base: '6px', md: '10px' }} > @@ -40,6 +47,8 @@ export const ActivityHeader = ({ aria-label="Delete this trip" variant="roundIcon" p={{ base: '6px', md: '10px' }} + onClick={() => deleteActivity(id)} + isLoading={isActivityDeleting} > diff --git a/app/activity/[id]/edit/page.tsx b/app/activity/[id]/edit/page.tsx new file mode 100644 index 0000000..87dbd5c --- /dev/null +++ b/app/activity/[id]/edit/page.tsx @@ -0,0 +1,77 @@ +'use client' + +import { NetworkStatus } from '@apollo/client' +import { Box, Container, Heading, useColorModeValue } from '@chakra-ui/react' +import { ActivityForm } from '@/activity/components/activity-form' +import { Loading } from '@/components/loading' +import { useActivityCollectionQuery } from '@generated/api' + +export default function ActivityEditPage({ + params +}: { + params: { id: string } +}) { + const bg = useColorModeValue('white', 'gray.800') + const color = useColorModeValue('black', 'gray.300') + + // Activity Details + const { + data: activityData, + loading: activityLoading, + refetch: activityRefetch, + networkStatus: activityNetWorkStatus + } = useActivityCollectionQuery({ + variables: { + id: params.id + }, + notifyOnNetworkStatusChange: true + }) + + const activityDataCollection = + activityData?.activityCollection?.edges[0]?.node + const activityDetailsRefetch = () => { + activityRefetch() + } + const activityDetailsRefetchLoading = + activityNetWorkStatus === NetworkStatus.refetch + + if (!activityData && !activityLoading) + throw new Error('No activity data found') + + return ( + + + + Edit Activity + + {!activityDataCollection || activityLoading ? ( + + ) : ( + edge?.node?.file_url + ), + refetch: activityDetailsRefetch, + refetchLoading: activityDetailsRefetchLoading + }} + /> + )} + + + ) +} diff --git a/app/activity/[id]/page.tsx b/app/activity/[id]/page.tsx index 6621dfb..c0ef88e 100644 --- a/app/activity/[id]/page.tsx +++ b/app/activity/[id]/page.tsx @@ -21,15 +21,14 @@ export default function ActivityDetails({ } }) - const dummyUrls: string[] = [ - 'https://images.unsplash.com/photo-1612852098516-55d01c75769a?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1yZWxhdGVkfDR8fHxlbnwwfHx8fA%3D%3D&auto=format&fit=crop&w=900&q=60', - 'https://images.unsplash.com/photo-1627875764093-315831ac12f7?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1yZWxhdGVkfDJ8fHxlbnwwfHx8fA%3D%3D&auto=format&fit=crop&w=900&q=60', - 'https://images.unsplash.com/photo-1571432248690-7fd6980a1ae2?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1yZWxhdGVkfDl8fHxlbnwwfHx8fA%3D%3D&auto=format&fit=crop&w=900&q=60' - ] - if (!loading && !data) throw new Error('No activity data found') const activityData = data?.activityCollection?.edges[0]?.node + const uploadedImageUrls = activityData?.activity_uploaded_filesCollection + ? activityData?.activity_uploaded_filesCollection?.edges.map( + (edge) => edge?.node?.file_url + ) + : [] return ( @@ -44,18 +43,20 @@ export default function ActivityDetails({ pb={{ base: '40px', md: '80px' }} > - {/* TODO: Fetch images from the database once available. */} - + {uploadedImageUrls.length > 0 && ( + + )} - + Got back to Trip Details diff --git a/app/activity/components/activity-form.tsx b/app/activity/components/activity-form.tsx new file mode 100644 index 0000000..21f2761 --- /dev/null +++ b/app/activity/components/activity-form.tsx @@ -0,0 +1,301 @@ +import React, { useState } from 'react' +import { Controller, useForm, useWatch } from 'react-hook-form' +import { + Box, + FormControl, + FormLabel, + FormErrorMessage, + Button, + Image, + SimpleGrid, + Text, + Flex, + VStack, + Input +} from '@chakra-ui/react' +import { PrimaryButton } from '@/components/button' +import { CustomDateTimePicker } from '@/components/date' +import { InputForm, TextareaForm } from '@/components/input' +import { getDateObj } from '@/libs/utils' +import { useActivityCreate, useActivityUpdate } from '../hooks' +import { ActivitySchema, activityResolver } from '../schema' + +export type ActivityDetails = { + id: string + title: string + timeFrom?: string | null + timeTo?: string | null | undefined + address?: string | null + url?: string | null + memo?: string | null + cost?: string | null + costUnit?: string | null + uploadedFileUrls?: string[] | null + refetch: () => void + refetchLoading: boolean +} + +type ActivityFormProps = { + tripId: string + activityDetails?: ActivityDetails +} + +export const ActivityForm = ({ + tripId, + activityDetails +}: ActivityFormProps) => { + const [selectedImages, setSelectedImages] = useState([]) + const removeImage = (index: number) => { + setSelectedImages((prevImages) => { + const newImages = [...prevImages] + newImages.splice(index, 1) + return newImages + }) + } + + const { + register, + control, + handleSubmit, + formState: { errors } + } = useForm({ + defaultValues: { + title: activityDetails?.title, + timeFrom: activityDetails?.timeFrom + ? getDateObj(activityDetails?.timeFrom) + : undefined, + timeTo: activityDetails?.timeTo + ? getDateObj(activityDetails?.timeTo) + : null, + address: activityDetails?.address || undefined, + url: activityDetails?.url || undefined, + memo: activityDetails?.memo || undefined, + cost: activityDetails?.cost || undefined, + costUnit: activityDetails?.costUnit || undefined, + uploadedFileUrls: activityDetails?.uploadedFileUrls || undefined, + newFiles: [] + }, + resolver: activityResolver + }) + const newFiles = useWatch({ control, name: 'newFiles' }) + + const { createActivity, isActivityCreating } = useActivityCreate(tripId) + const { updateActivity, isActivityUpdating } = useActivityUpdate(tripId) + const mutateFun = activityDetails + ? (data: ActivitySchema) => updateActivity(activityDetails.id, data) + : createActivity + const isMutating = isActivityCreating || isActivityUpdating + + return ( + + + Title + + {errors.title && ( + {errors.title.message} + )} + + + + Time From + ( + + )} + /> + {errors.timeFrom && ( + {errors.timeFrom.message} + )} + + + + Time To + ( + + )} + /> + {errors.timeTo && ( + {errors.timeTo.message} + )} + + + + Address + + {errors.address && ( + {errors.address.message} + )} + + + + URL + + {errors.url && ( + {errors.url.message} + )} + + + + Image + + + {activityDetails?.uploadedFileUrls?.map((url, index) => ( + {`Uploaded + ))} + {selectedImages.map((image, index) => ( + {`Selected removeImage(index)} + /> + ))} + + + 0 || + selectedImages.length !== 0 + ? '40px' + : '0' + }} + > + ( + + Add Image + { + const files = event.target.files + if (files && newFiles) { + const newFileList = Array.from(files) + setSelectedImages((prevImages) => [ + ...prevImages, + ...newFileList + ]) + newFiles.push(...newFileList) + onChange(newFiles) + } + }} + /> + + )} + /> + + + + Memo + + {errors.memo && ( + {errors.memo.message} + )} + + + + + Cost + + {errors?.cost?.message} + + + + Unit + + {errors?.costUnit?.message} + + + + + + + + ) +} diff --git a/app/activity/components/index.ts b/app/activity/components/index.ts new file mode 100644 index 0000000..7213fb2 --- /dev/null +++ b/app/activity/components/index.ts @@ -0,0 +1 @@ +export { ActivityForm } from './activity-form' diff --git a/app/activity/create/components/form.tsx b/app/activity/create/components/form.tsx deleted file mode 100644 index 8d8e7e9..0000000 --- a/app/activity/create/components/form.tsx +++ /dev/null @@ -1,165 +0,0 @@ -import React, { useCallback, useState } from 'react' -import { useDropzone } from 'react-dropzone' -import { useForm } from 'react-hook-form' -import { - Box, - FormControl, - FormLabel, - FormErrorMessage, - Button, - Image, - SimpleGrid, - Text, - Flex -} from '@chakra-ui/react' -import { PrimaryButton } from '@/components/button' -import { CustomDateTimePicker } from '@/components/customDateTimePicker' -import { InputForm, TextareaForm } from '@/components/input' -import { createActivitySchema, createActivityResolver } from '../schema' - -type ValuePiece = Date | null -type Value = ValuePiece | [ValuePiece, ValuePiece] - -export const FormActivity = () => { - const [dateTo, setDateTo] = useState(null) - const [dateFrom, setDateFrom] = useState(null) - const [selectedImages, setSelectedImages] = useState([]) - const onDrop = useCallback((acceptedFiles: File[]) => { - setSelectedImages((prevImages) => [...prevImages, ...acceptedFiles]) - }, []) - const { getRootProps, getInputProps } = useDropzone({ onDrop }) - function removeImage(index: number) { - setSelectedImages((prevImages) => { - const newImages = [...prevImages] - newImages.splice(index, 1) - return newImages - }) - } - - const { - register, - handleSubmit, - formState: { errors } - } = useForm({ - resolver: createActivityResolver - }) - - const createHandler = handleSubmit(async (data: createActivitySchema) => { - console.log(data) - // TODO append 'images', 'date from', 'date to' to formData and send to backend - }) - - console.log('date to', dateTo, 'date from', dateFrom) - - return ( - - - Title - - {errors.title && ( - {errors.title.message} - )} - - - - Time From - - - - - Time To - - - - - Address - - {errors.address && ( - {errors.address.message} - )} - - - - URL - - {errors.url && ( - {errors.url.message} - )} - - - - Image - - - {selectedImages.map((image, index) => ( - {`Selected removeImage(index)} - /> - ))} - - - - - - Add Image - - - - - Memo - - {errors.memo && ( - {errors.memo.message} - )} - - - - Cost - - {errors.cost && ( - {errors.cost.message} - )} - - - - - - - ) -} diff --git a/app/activity/create/components/index.ts b/app/activity/create/components/index.ts deleted file mode 100644 index 424fdad..0000000 --- a/app/activity/create/components/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { FormActivity } from './form' diff --git a/app/activity/create/graphql/mutation/createActivity.graphql b/app/activity/create/graphql/mutation/createActivity.graphql deleted file mode 100644 index d77e189..0000000 --- a/app/activity/create/graphql/mutation/createActivity.graphql +++ /dev/null @@ -1,35 +0,0 @@ -mutation createActivity( - $trip_id: UUID! - $title: String! - $time_from: Datetime - $time_to: Datetime - $address: String - $url: String - $memo: String - $cost: BigFloat - $cost_unit: String - $image_url: String -) { - insertIntoactivityCollection( - objects: [ - { - trip_id: $trip_id - title: $title - time_from: $time_from - time_to: $time_to - address: $address - url: $url - memo: $memo - cost: $cost - cost_unit: $cost_unit - image_url: $image_url - } - ] - ) { - records { - __typename - id - title - } - } -} diff --git a/app/activity/create/page.tsx b/app/activity/create/page.tsx index 335dbb3..679eea1 100644 --- a/app/activity/create/page.tsx +++ b/app/activity/create/page.tsx @@ -1,11 +1,13 @@ 'use client' import { Box, Container, Heading, useColorModeValue } from '@chakra-ui/react' -import { FormActivity } from './components' +import { useSearchParams } from 'next/navigation' +import { ActivityForm } from '../components' export default function CreateActivityPage() { const bg = useColorModeValue('white', 'gray.800') const color = useColorModeValue('black', 'gray.300') + const tripId = useSearchParams().get('tripId') || '' return ( @@ -16,7 +18,7 @@ export default function CreateActivityPage() { Create Activity - + ) diff --git a/app/activity/graphql/mutation/createActivity.graphql b/app/activity/graphql/mutation/createActivity.graphql new file mode 100644 index 0000000..5164526 --- /dev/null +++ b/app/activity/graphql/mutation/createActivity.graphql @@ -0,0 +1,9 @@ +mutation createActivity($object: activityInsertInput!) { + insertIntoactivityCollection(objects: [$object]) { + records { + __typename + id + title + } + } +} diff --git a/app/activity/graphql/mutation/createActivityUploadedFiles.graphql b/app/activity/graphql/mutation/createActivityUploadedFiles.graphql new file mode 100644 index 0000000..87ad0af --- /dev/null +++ b/app/activity/graphql/mutation/createActivityUploadedFiles.graphql @@ -0,0 +1,13 @@ +mutation createActivityUploadedFiles( + $objects: [activity_uploaded_filesInsertInput!]! +) { + insertIntoactivity_uploaded_filesCollection(objects: $objects) { + records { + __typename + id + activity_id + file_name + file_url + } + } +} diff --git a/app/activity/graphql/mutation/deleteActivity.graphql b/app/activity/graphql/mutation/deleteActivity.graphql new file mode 100644 index 0000000..a53e92e --- /dev/null +++ b/app/activity/graphql/mutation/deleteActivity.graphql @@ -0,0 +1,10 @@ +mutation DeleteActivity($id: UUID!) { + deleteFromactivityCollection(filter: { id: { eq: $id } }) { + records { + __typename + id + trip_id + title + } + } +} diff --git a/app/activity/graphql/mutation/updateActivity.graphql b/app/activity/graphql/mutation/updateActivity.graphql new file mode 100644 index 0000000..2b94a5c --- /dev/null +++ b/app/activity/graphql/mutation/updateActivity.graphql @@ -0,0 +1,8 @@ +mutation updateActivity($id: UUID!, $set: activityUpdateInput!) { + updateactivityCollection(set: $set, filter: { id: { eq: $id } }) { + records { + id + title + } + } +} diff --git a/app/activity/[id]/graphql/query/activityCollection.graphql b/app/activity/graphql/query/activityCollection.graphql similarity index 60% rename from app/activity/[id]/graphql/query/activityCollection.graphql rename to app/activity/graphql/query/activityCollection.graphql index 1f9984e..c6b9ce9 100644 --- a/app/activity/[id]/graphql/query/activityCollection.graphql +++ b/app/activity/graphql/query/activityCollection.graphql @@ -12,7 +12,15 @@ query activityCollection($id: UUID!) { memo cost cost_unit - image_url + activity_uploaded_filesCollection { + edges { + node { + id + file_name + file_url + } + } + } } } } diff --git a/app/activity/hooks/index.ts b/app/activity/hooks/index.ts new file mode 100644 index 0000000..6529f95 --- /dev/null +++ b/app/activity/hooks/index.ts @@ -0,0 +1,3 @@ +export { useActivityCreate } from './useActivityCreate' +export { useActivityUpdate } from './useActivityUpdate' +export { useUploadFiles } from './useUploadFiles' diff --git a/app/activity/hooks/useActivityCreate.ts b/app/activity/hooks/useActivityCreate.ts new file mode 100644 index 0000000..756ed41 --- /dev/null +++ b/app/activity/hooks/useActivityCreate.ts @@ -0,0 +1,79 @@ +import { useToast } from '@chakra-ui/react' +import { useRouter } from 'next/navigation' +import { formatToISODate } from '@/libs/utils' +import { ActivitySchema } from '../schema' +import { useRefetchTrips } from './useRefetchTrips' +import { useUploadFiles } from './useUploadFiles' +import { useCreateActivityMutation } from '@generated/api' + +export const useActivityCreate = (tripId: string) => { + const toast = useToast() + const router = useRouter() + const [createActivityMutation, { loading: isActivityCreating }] = + useCreateActivityMutation() + const { uploadFiles } = useUploadFiles() + const { refetchTrips } = useRefetchTrips() + + const createActivity = async (activityData: ActivitySchema) => { + try { + const { data, errors } = await createActivityMutation({ + variables: { + object: { + trip_id: tripId, + title: activityData.title, + time_from: formatToISODate(activityData.timeFrom), + time_to: activityData.timeTo + ? formatToISODate(activityData.timeTo) + : null, + address: activityData.address, + url: activityData.url, + memo: activityData.memo, + cost: activityData.cost || null, + cost_unit: activityData.costUnit + } + }, + refetchQueries: ['activityCollection'] + }) + + if (errors) throw new Error(errors[0].message) + + const createdActivityId = + data?.insertIntoactivityCollection?.records[0]?.id + + if (!createdActivityId) throw new Error('Failed to create an activity') + + if ( + createdActivityId && + activityData.newFiles && + activityData.newFiles.length > 0 + ) { + await uploadFiles(activityData.newFiles, { + id: createdActivityId, + tripId + }) + } + + refetchTrips(tripId) + router.push(`/activity/${createdActivityId}`) + toast({ + title: 'Successfully created!', + status: 'success', + duration: 2000, + isClosable: true, + position: 'top' + }) + } catch (error) { + toast({ + title: 'Failed to create an activity', + status: 'error', + duration: 3000, + isClosable: true + }) + } + } + + return { + createActivity, + isActivityCreating + } +} diff --git a/app/activity/hooks/useActivityDelete.ts b/app/activity/hooks/useActivityDelete.ts new file mode 100644 index 0000000..bae3ed5 --- /dev/null +++ b/app/activity/hooks/useActivityDelete.ts @@ -0,0 +1,47 @@ +import { useToast } from '@chakra-ui/react' +import { useRouter } from 'next/navigation' +import { useRefetchTrips } from './useRefetchTrips' +import { useDeleteActivityMutation } from '@generated/api' + +export const useActivityDelete = () => { + const toast = useToast() + const router = useRouter() + const [deleteActivityMutation, { loading: isActivityDeleting }] = + useDeleteActivityMutation() + const { refetchTrips } = useRefetchTrips() + + const deleteActivity = async (activityId: string) => { + try { + const { data, errors } = await deleteActivityMutation({ + variables: { + id: activityId + }, + refetchQueries: ['activityCollection'] + }) + + if (errors) throw new Error(errors[0].message) + if (!data) throw new Error('Failed to delete an activity') + + const tripId = data.deleteFromactivityCollection.records[0].trip_id + + refetchTrips(tripId) + router.push(`/trip/${tripId}`) + toast({ + title: 'Successfully deleted!', + status: 'success', + duration: 2000, + isClosable: true, + position: 'top' + }) + } catch (error) { + toast({ + title: 'Failed to delete an activity', + status: 'error', + duration: 3000, + isClosable: true + }) + } + } + + return { deleteActivity, isActivityDeleting } +} diff --git a/app/activity/hooks/useActivityUpdate.ts b/app/activity/hooks/useActivityUpdate.ts new file mode 100644 index 0000000..967ac04 --- /dev/null +++ b/app/activity/hooks/useActivityUpdate.ts @@ -0,0 +1,78 @@ +import { useToast } from '@chakra-ui/react' +import { useRouter } from 'next/navigation' +import { formatToISODate } from '@/libs/utils' +import { ActivitySchema } from '../schema' +import { useRefetchTrips } from './useRefetchTrips' +import { useUploadFiles } from './useUploadFiles' +import { useUpdateActivityMutation } from '@generated/api' + +export const useActivityUpdate = (tripId: string) => { + const toast = useToast() + const router = useRouter() + const [updateActivityMutation, { loading: isActivityUpdating }] = + useUpdateActivityMutation() + const { uploadFiles } = useUploadFiles() + const { refetchTrips } = useRefetchTrips() + + const updateActivity = async ( + activityId: string, + activityData: ActivitySchema + ) => { + try { + const { data, errors } = await updateActivityMutation({ + variables: { + id: activityId, + set: { + title: activityData.title, + time_from: formatToISODate(activityData.timeFrom), + time_to: activityData.timeTo + ? formatToISODate(activityData.timeTo) + : null, + address: activityData.address, + url: activityData.url, + memo: activityData.memo, + cost: activityData.cost || null, + cost_unit: activityData.costUnit + } + }, + refetchQueries: ['activityCollection'] + }) + + if (errors) throw new Error(errors[0].message) + + const updatedActivityId = data?.updateactivityCollection?.records[0]?.id + + if (!updatedActivityId) throw new Error('Failed to create an activity') + + if ( + updatedActivityId && + activityData.newFiles && + activityData.newFiles.length > 0 + ) { + await uploadFiles(activityData.newFiles, { id: activityId, tripId }) + } + + refetchTrips(tripId) + router.push(`/activity/${activityId}`) + toast({ + title: 'Successfully updated!', + status: 'success', + duration: 2000, + isClosable: true, + position: 'top' + }) + } catch (error) { + toast({ + title: 'Failed to create an activity', + status: 'error', + duration: 3000, + isClosable: true + }) + } + } + + return { + updateActivity, + isActivityUpdating + } +} diff --git a/app/activity/hooks/useRefetchTrips.ts b/app/activity/hooks/useRefetchTrips.ts new file mode 100644 index 0000000..a0fde7e --- /dev/null +++ b/app/activity/hooks/useRefetchTrips.ts @@ -0,0 +1,19 @@ +import { useTripsCollectionQuery } from '@generated/api' + +// This hook is used to refetch trips after an activity is created, updated, or deleted. +export const useRefetchTrips = () => { + const { refetch } = useTripsCollectionQuery({}) + + const refetchTrips = (tripId: string) => { + refetch({ + filter: { + id: { eq: tripId } + }, + first: 12, + // NOTE: This refetch hook function is designed to re-fetch only the single trip associated with an activity, so pagination considerations are unnecessary. + after: null + }) + } + + return { refetchTrips } +} diff --git a/app/activity/hooks/useUploadFiles.ts b/app/activity/hooks/useUploadFiles.ts new file mode 100644 index 0000000..48e7406 --- /dev/null +++ b/app/activity/hooks/useUploadFiles.ts @@ -0,0 +1,64 @@ +import { createClient } from '@supabase/supabase-js' +import { useCreateActivityUploadedFilesMutation } from '@generated/api' + +export const useUploadFiles = () => { + const [createActivityUploadedFilesMutation] = + useCreateActivityUploadedFilesMutation() + + const uploadFiles = async ( + files: File[], + activityDetails: { id: string; tripId: string } + ) => { + const supabase = createClient( + process.env.NEXT_PUBLIC_SUPABASE_URL!, + process.env.NEXT_PUBLIC_API_KEY! + ) + + const uploadPromises = files.map(async (file) => { + const { data, error } = await supabase.storage + .from(process.env.NEXT_PUBLIC_BUCKET_NAME!) + .upload( + `trips/${activityDetails.tripId}/activity/${activityDetails.id}/${file.name}`, + file, + { upsert: true } + ) + + return { data, fileName: file.name, error } + }) + + const uploadResults = await Promise.all(uploadPromises) + const uploadErrors = uploadResults.filter((result) => result.error) + + if (uploadErrors.length > 0) { + throw new Error(uploadErrors[0].error!.message) + } + + // get the public URL of the uploaded files + const results = uploadResults.map((result) => result) + const dataWithPublicUrls = await Promise.all( + results.map((result) => { + const { + data: { publicUrl } + } = supabase.storage + .from(process.env.NEXT_PUBLIC_BUCKET_NAME!) + .getPublicUrl(result.data!.path!) + + return { publicUrl, fileName: result.fileName } + }) + ) + + // create a record in the uploaded_files table + await createActivityUploadedFilesMutation({ + variables: { + objects: dataWithPublicUrls.map((data) => ({ + activity_id: activityDetails.id, + file_name: data.fileName, + file_url: data.publicUrl + })) + }, + refetchQueries: ['activityCollection'] + }) + } + + return { uploadFiles } +} diff --git a/app/activity/schema.ts b/app/activity/schema.ts new file mode 100644 index 0000000..8cbbf97 --- /dev/null +++ b/app/activity/schema.ts @@ -0,0 +1,34 @@ +import { zodResolver } from '@hookform/resolvers/zod' +import * as z from 'zod' + +const activitySchema = z + .object({ + title: z.string().min(1, { message: 'Please enter a title' }), + timeFrom: z.date({ + required_error: 'Please select a date from', + invalid_type_error: "That's not a date" + }), + timeTo: z.date().nullable().optional(), + address: z.string().min(0).max(50).nullable(), + url: z.union([z.string().url().nullish(), z.literal('')]), + memo: z.string().min(0).max(300).nullable(), + cost: z.string().nullable(), + costUnit: z.string().nullable(), + uploadedFileUrls: z.array(z.string()).optional(), + newFiles: z.array(z.instanceof(File)).optional() + }) + .refine( + (args) => { + if (args.timeTo === null || args.timeTo === undefined) return true + + const { timeFrom, timeTo } = args + return timeFrom < timeTo + }, + { + message: 'Time to must be later than time from', + path: ['timeTo'] + } + ) + +export type ActivitySchema = z.infer +export const activityResolver = zodResolver(activitySchema) diff --git a/app/components/customDateTimePicker/dateTimePickerWrapper.tsx b/app/components/customDateTimePicker/dateTimePickerWrapper.tsx deleted file mode 100644 index 1e87eaa..0000000 --- a/app/components/customDateTimePicker/dateTimePickerWrapper.tsx +++ /dev/null @@ -1,117 +0,0 @@ -import { DateTimePicker as ReactDateTimePicker } from 'react-datetime-picker' -import { useColorMode } from '@chakra-ui/react' -import { MdCalendarToday, MdClose } from 'react-icons/md' -import 'react-clock/dist/Clock.css' -import 'react-datetime-picker/dist/DateTimePicker.css' -import 'react-calendar/dist/Calendar.css' - -type ValuePiece = Date | null -type Value = ValuePiece | [ValuePiece, ValuePiece] - -// TODO Delete this and use react date picker for time as well -export const CustomDateTimePicker = ({ - onChange, - value -}: { - onChange: (value: Value) => void - value: Value -}) => { - const { colorMode } = useColorMode() - - return ( - <> - - -
- } - clearIcon={} - format={'y-MM-dd h:mm a'} - /> -
- - ) -} diff --git a/app/components/customDateTimePicker/index.ts b/app/components/customDateTimePicker/index.ts deleted file mode 100644 index 7137b21..0000000 --- a/app/components/customDateTimePicker/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { CustomDateTimePicker } from './dateTimePickerWrapper' diff --git a/app/components/customDateTimePicker/stories/dateTimePicker.stories.tsx b/app/components/customDateTimePicker/stories/dateTimePicker.stories.tsx deleted file mode 100644 index a75c5d8..0000000 --- a/app/components/customDateTimePicker/stories/dateTimePicker.stories.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { StoryObj, Meta } from '@storybook/react' -import { CustomDateTimePicker } from '../index' // Adjust the import path accordingly - -const meta: Meta = { - title: 'CustomDateTimePicker', - component: CustomDateTimePicker -} - -export default meta - -type Story = StoryObj - -export const Default: Story = { - args: { - onChange: (value) => console.log(value), - value: new Date() - } -} diff --git a/app/components/date/custom-date-picker.tsx b/app/components/date/custom-date-picker.tsx index 8cbde6d..ef44e4d 100644 --- a/app/components/date/custom-date-picker.tsx +++ b/app/components/date/custom-date-picker.tsx @@ -104,3 +104,132 @@ export const CustomDatePicker = ({
) } + +export const CustomDateTimePicker = ({ + selectedDate, + onChange, + placeholderText, + dateFormat +}: DatePickerProps) => { + const { colorMode } = useColorMode() + + const dateTimePickerStyles = { + '.react-datepicker-wrapper': { + width: '100%' + }, + '.react-datepicker-popper': { + right: { base: 0, md: 'unset' } + }, + '.react-datepicker ': { + width: '100%', + border: 'none', + boxShadow: '0px 2px 16px 0px rgba(0,0,0,.25);', + fontSize: 'sm', + backgroundColor: colorMode === 'dark' ? 'gray.700' : 'white' + }, + '.react-datepicker__month-container': { + backgroundColor: colorMode === 'dark' ? 'gray.700' : 'white', + width: { base: '80%', md: '400px' }, // In order to display month and time side by side, width is set to 80% and 20% respectively + height: { base: '360px', md: '386px' } // Due to .react-datepicker__time-list height is set to static px value by inline style, this is to prevent the time list from overflowing. + }, + '.react-datepicker__time-container': { + backgroundColor: colorMode === 'dark' ? 'gray.700' : 'white', + width: { base: '20%', md: '85px' } // In order to display month and time side by side, width is set to 20% and 80% respectively + }, + '.react-datepicker__triangle': { + display: 'none' + }, + '.react-datepicker__header': { + backgroundColor: colorMode === 'dark' ? 'gray.700' : 'white', + borderBottomColor: colorMode === 'dark' ? 'gray.500' : 'gray.300' + }, + '.react-datepicker__header--time': { + backgroundColor: colorMode === 'dark' ? 'gray.700' : 'white', + borderBottomColor: colorMode === 'dark' ? 'gray.500' : 'gray.300' + }, + '.react-datepicker__current-month': { + color: colorMode === 'dark' ? 'primary.700' : 'primary.800', + paddingY: '8px', + fontSize: 'lg' + }, + '.react-datepicker__navigation': { + top: '11px' + }, + '.react-datepicker__navigation--previous': { + left: { base: '16px', md: '32px' } + }, + '.react-datepicker__navigation--next--with-time:not(.react-datepicker__navigation--next--with-today-button)': + { + right: '24%' + }, + '.react-datepicker__navigation-icon': { + '&::before': { + borderColor: colorMode === 'dark' ? 'gray.500' : 'gray.400' + } + }, + '.react-datepicker__month': { + margin: '1rem' + }, + '.react-datepicker__day-names': { + paddingY: '4px' + }, + '.react-datepicker__day-name': { + width: { base: '2rem', md: '2.8rem' }, + lineHeight: { base: '2.4rem', md: '2.8rem' }, + color: colorMode === 'dark' ? 'gray.300' : 'black' + }, + '.react-datepicker__day': { + width: { base: '2rem', md: '2.8rem' }, + lineHeight: { base: '2.2rem', md: '2.4rem' }, + ':hover': { + backgroundColor: colorMode === 'dark' ? 'gray.600' : 'gray.100' + }, + color: colorMode === 'dark' ? 'gray.300' : 'black' + }, + '.react-datepicker__day--selected': { + fontWeight: 'bold', + color: 'white', + backgroundColor: colorMode === 'dark' ? 'primary.700' : 'primary.500' + }, + '.react-datepicker__day--keyboard-selected': { + background: 'none' + }, + '.react-datepicker-time__header': { + backgroundColor: colorMode === 'dark' ? 'gray.700' : 'white', + borderBottomColor: colorMode === 'dark' ? 'gray.500' : 'gray.300', + color: colorMode === 'dark' ? 'gray.300' : 'black' + }, + + '.react-datepicker__time-box': { + backgroundColor: colorMode === 'dark' ? 'gray.700' : 'white', + color: colorMode === 'dark' ? 'gray.300' : 'black' + }, + + '.react-datepicker__time-container .react-datepicker__time .react-datepicker__time-box': + { + width: { base: '100%', md: '85px' } + }, + '.react-datepicker__time-container .react-datepicker__time .react-datepicker__time-box ul.react-datepicker__time-list li.react-datepicker__time-list-item--selected': + { + color: 'white', + backgroundColor: colorMode === 'dark' ? 'primary.700' : 'primary.500' + } + } + + return ( + + } + /> + + ) +} diff --git a/app/components/date/index.ts b/app/components/date/index.ts index 6ec423b..60a3b33 100644 --- a/app/components/date/index.ts +++ b/app/components/date/index.ts @@ -1 +1 @@ -export { CustomDatePicker } from './custom-date-picker' +export { CustomDatePicker, CustomDateTimePicker } from './custom-date-picker' diff --git a/app/components/date/stories/custom-date-picker.stories.tsx b/app/components/date/stories/custom-date-picker.stories.tsx index b5c1ebb..e23650a 100644 --- a/app/components/date/stories/custom-date-picker.stories.tsx +++ b/app/components/date/stories/custom-date-picker.stories.tsx @@ -1,6 +1,6 @@ import { useState } from 'react' -import { Meta } from '@storybook/react' -import { CustomDatePicker } from '@/components/date' +import { Meta, StoryFn } from '@storybook/react' +import { CustomDatePicker, CustomDateTimePicker } from '@/components/date' const meta: Meta = { title: 'CustomDatePicker', @@ -18,3 +18,15 @@ export const Default = () => { /> ) } + +export const DateTimePicker: StoryFn = () => { + const [selectedDate, setSelectedDate] = useState(new Date()) + return ( + setSelectedDate(date)} + placeholderText="Select Date" + dateFormat="yyyy/MM/dd HH:mm" + /> + ) +} diff --git a/app/providers/session-provider.tsx b/app/providers/session-provider.tsx index ccc26d2..17a93d0 100644 --- a/app/providers/session-provider.tsx +++ b/app/providers/session-provider.tsx @@ -21,7 +21,6 @@ export function SessionProvider({ userId: string }) { const pathname = usePathname() - console.log(pathname) const AUTH_PATH_NAMES = ['/signin', '/signup'] return AUTH_PATH_NAMES.includes(pathname) ? ( {children} diff --git a/app/trip/[id]/action/update-image-metadata.ts b/app/trip/[id]/action/update-image-metadata.ts deleted file mode 100644 index 924d636..0000000 --- a/app/trip/[id]/action/update-image-metadata.ts +++ /dev/null @@ -1,53 +0,0 @@ -'use server' -import { createServerActionClient } from '@supabase/auth-helpers-nextjs' -import { cookies } from 'next/headers' - -export const updateImageMetadataAction = async ( - id: string, - filePath: string -): Promise< - | { status: 'success'; data: { publicUrl: string } } - | { status: 'error'; data: { publicUrl: string }; error: { message: string } } -> => { - try { - const cookieStore = cookies() - // NOTE: Use createServerActionClient instead of createClient in with-cookie.ts - // https://supabase.com/docs/guides/auth/auth-helpers/nextjs?language=ts#server-actions - const supabase = createServerActionClient({ cookies: () => cookieStore }) - - // Supabase Storage API is not available in the server action. - // const { data: uploadData, error: uploadError } = await supabase.storage - // .from('tabi-memo-uploads') - // .upload(`trips/${id}/${file.name}`, file, { upsert: true }) - - // if (uploadError) throw uploadError - - const { - data: { publicUrl } - } = await supabase.storage - .from(process.env.NEXT_PUBLIC_BUCKET_NAME!) - .getPublicUrl(filePath) - - const updateResponse = await supabase - .from('trips') - .update({ image_url: publicUrl }) - .match({ id }) - - if (updateResponse.error) { - return { - status: 'error', - data: { publicUrl }, - error: { message: updateResponse.error.message } - } - } - - return { status: 'success', data: { publicUrl } } - } catch (error) { - console.error({ error }) - return { - status: 'error', - data: { publicUrl: '' }, - error: { message: 'Failed to upload image' } - } - } -} diff --git a/app/trip/[id]/components/activity-card.tsx b/app/trip/[id]/components/activity-card.tsx index 5061025..d1e68c7 100644 --- a/app/trip/[id]/components/activity-card.tsx +++ b/app/trip/[id]/components/activity-card.tsx @@ -12,6 +12,7 @@ import { } from '@chakra-ui/react' import { useRouter } from 'next/navigation' import { FiTrash2, FiMapPin, FiMoreHorizontal, FiEdit3 } from 'react-icons/fi' +import { useActivityDelete } from '@/activity/hooks/useActivityDelete' import { Link } from '@/components/link' import { ConfirmModal } from '@/components/modal' import { @@ -39,6 +40,8 @@ export const ActivityCard = ({ activity, selectedDate }: ActivityCardProps) => { onClose: onDeleteModalClose } = useDisclosure() + const { deleteActivity } = useActivityDelete() + const differentDate = (displayPlace: 'timeFrom' | 'timeTo') => { if (!activity.timeTo) return null @@ -166,7 +169,6 @@ export const ActivityCard = ({ activity, selectedDate }: ActivityCardProps) => { - {/* TODO Delete activity */} { Are you sure you want to delete this activity? } - onClick={() => {}} + onClick={async () => { + await deleteActivity(activity.id) + onDeleteModalClose() + }} submitLabel="Delete" /> diff --git a/app/trip/[id]/components/trip-details-header.tsx b/app/trip/[id]/components/trip-details-header.tsx index ecff77f..ce104a4 100644 --- a/app/trip/[id]/components/trip-details-header.tsx +++ b/app/trip/[id]/components/trip-details-header.tsx @@ -175,9 +175,8 @@ export const TripDetailsHeader = ({ ))}
)} - {/* TODO Change URL */} { + const borderColor = useColorModeValue('gray.300', 'gray.600') + + const labelMap = { + [Permission_Level_Enum.Editable]: 'Can Edit', + [Permission_Level_Enum.ViewOnly]: 'View Only' + } + + const userId = useUserId() + + const { updatePermissionLevel, isInvitationUpdating } = + useUpdateInvitation(tripId) + + const { deleteInvitation, isInvitationDeleting } = useDeleteInvitation(tripId) + + const currentUserIsOwner = userId === ownerId + + return ( + + + + + + {name} + + {email} + + + + + + + {Object.entries(Permission_Level_Enum).map(([key, value]) => ( + updatePermissionLevel(id, value)} + > + {labelMap[value]} + + ))} + + + + {currentUserIsOwner && ( + deleteInvitation(id)} + > + + + )} + + + ) +} diff --git a/app/trip/[id]/manage-group/components/owner-card.tsx b/app/trip/[id]/manage-group/components/owner-card.tsx new file mode 100644 index 0000000..9c36121 --- /dev/null +++ b/app/trip/[id]/manage-group/components/owner-card.tsx @@ -0,0 +1,46 @@ +import { + Box, + useColorModeValue, + Heading, + Avatar, + Flex, + Text +} from '@chakra-ui/react' + +type OwnerCardProps = { + image: string | null | undefined + name: string + email: string +} + +export const OwnerCard = ({ image, name, email }: OwnerCardProps) => { + const borderColor = useColorModeValue('gray.300', 'gray.600') + + return ( + + + + + + {name} + + {email} + + + + + Owner + + + ) +} diff --git a/app/trip/[id]/manage-group/graphql/mutation/delete-invitation.graphql b/app/trip/[id]/manage-group/graphql/mutation/delete-invitation.graphql new file mode 100644 index 0000000..62fcfc5 --- /dev/null +++ b/app/trip/[id]/manage-group/graphql/mutation/delete-invitation.graphql @@ -0,0 +1,10 @@ +mutation deleteInvitation($id: UUID!) { + deleteFrominvitationsCollection(filter: { id: { eq: $id } }) { + records { + __typename + id + email + permission_level + } + } +} diff --git a/app/trip/[id]/manage-group/graphql/mutation/update-invitation.graphql b/app/trip/[id]/manage-group/graphql/mutation/update-invitation.graphql new file mode 100644 index 0000000..db8a3c1 --- /dev/null +++ b/app/trip/[id]/manage-group/graphql/mutation/update-invitation.graphql @@ -0,0 +1,9 @@ +mutation updateInvitation($id: UUID!, $set: invitationsUpdateInput!) { + updateinvitationsCollection(set: $set, filter: { id: { eq: $id } }) { + records { + id + email + permission_level + } + } +} diff --git a/app/trip/[id]/manage-group/graphql/query/trip-shared-users.graphql b/app/trip/[id]/manage-group/graphql/query/trip-shared-users.graphql new file mode 100644 index 0000000..e072c7b --- /dev/null +++ b/app/trip/[id]/manage-group/graphql/query/trip-shared-users.graphql @@ -0,0 +1,30 @@ +query tripSharedUsers($tripId: UUID!) { + tripsCollection(filter: { id: { eq: $tripId } }) { + edges { + node { + id + title + users { + id + name + profile_picture_url + email + } + invitationsCollection { + edges { + node { + id + permission_level + users { + id + name + email + profile_picture_url + } + } + } + } + } + } + } +} diff --git a/app/trip/[id]/manage-group/hooks/index.ts b/app/trip/[id]/manage-group/hooks/index.ts new file mode 100644 index 0000000..10d6006 --- /dev/null +++ b/app/trip/[id]/manage-group/hooks/index.ts @@ -0,0 +1,3 @@ +export { useDeleteInvitation } from './use-delete-invitation' +export { useGetTripSharedUsers } from './use-get-trip-shared-users' +export { useUpdateInvitation } from './use-update-invitation' diff --git a/app/trip/[id]/manage-group/hooks/use-delete-invitation.ts b/app/trip/[id]/manage-group/hooks/use-delete-invitation.ts new file mode 100644 index 0000000..5262e22 --- /dev/null +++ b/app/trip/[id]/manage-group/hooks/use-delete-invitation.ts @@ -0,0 +1,37 @@ +import { useToast } from '@chakra-ui/react' +import { useGetTripSharedUsers } from '../hooks' +import { useDeleteInvitationMutation } from '@generated/api' + +export const useDeleteInvitation = (tripId: string) => { + const toast = useToast() + + const [deleteInvitationMutation, { loading: isInvitationDeleting }] = + useDeleteInvitationMutation() + + const { refetch } = useGetTripSharedUsers(tripId) + + const deleteInvitation = async (id: string) => { + try { + await deleteInvitationMutation({ + variables: { + id + } + }) + refetch() + } catch (error) { + toast({ + title: "We're sorry, but you failed to delete the shared user", + description: + error instanceof Error ? error.message : 'Please try again later.', + status: 'error', + duration: 5000, + isClosable: true, + position: 'top' + }) + } + } + return { + deleteInvitation, + isInvitationDeleting + } +} diff --git a/app/trip/[id]/manage-group/hooks/use-get-trip-shared-users.ts b/app/trip/[id]/manage-group/hooks/use-get-trip-shared-users.ts new file mode 100644 index 0000000..0538ee9 --- /dev/null +++ b/app/trip/[id]/manage-group/hooks/use-get-trip-shared-users.ts @@ -0,0 +1,15 @@ +import { useTripSharedUsersQuery } from '@generated/api' + +export const useGetTripSharedUsers = (tripId: string) => { + const { data, loading, refetch } = useTripSharedUsersQuery({ + variables: { + tripId + } + }) + + return { + tripSharedUsers: data?.tripsCollection?.edges[0].node, + loading, + refetch + } +} diff --git a/app/trip/[id]/manage-group/hooks/use-update-invitation.ts b/app/trip/[id]/manage-group/hooks/use-update-invitation.ts new file mode 100644 index 0000000..40ee458 --- /dev/null +++ b/app/trip/[id]/manage-group/hooks/use-update-invitation.ts @@ -0,0 +1,47 @@ +import { useToast } from '@chakra-ui/react' +import { useGetTripSharedUsers } from '../hooks' +import { + useUpdateInvitationMutation, + Permission_Level_Enum +} from '@generated/api' + +export const useUpdateInvitation = (tripId: string) => { + const toast = useToast() + + const [updateInvitationMutation, { loading: isInvitationUpdating }] = + useUpdateInvitationMutation() + + const { refetch } = useGetTripSharedUsers(tripId) + + const updatePermissionLevel = async ( + id: string, + permissionLevel: Permission_Level_Enum + ) => { + try { + await updateInvitationMutation({ + variables: { + id, + set: { + permission_level: permissionLevel + } + } + }) + refetch() + } catch (error) { + toast({ + title: "We're sorry, but you failed to update the option", + description: + error instanceof Error ? error.message : 'Please try again later.', + status: 'error', + duration: 5000, + isClosable: true, + position: 'top' + }) + } + } + + return { + updatePermissionLevel, + isInvitationUpdating + } +} diff --git a/app/trip/[id]/manage-group/page.tsx b/app/trip/[id]/manage-group/page.tsx new file mode 100644 index 0000000..c77b4bc --- /dev/null +++ b/app/trip/[id]/manage-group/page.tsx @@ -0,0 +1,72 @@ +'use client' + +import { + Box, + Container, + useColorModeValue, + Heading, + VStack +} from '@chakra-ui/react' +import { Loading } from '@/components/loading' +import { OwnerCard, InvitedUserCard } from './components' +import { useGetTripSharedUsers } from './hooks' + +export default function ManageGroup({ params }: { params: { id: string } }) { + const bg = useColorModeValue('white', 'gray.800') + const color = useColorModeValue('black', 'gray.300') + + const { tripSharedUsers, loading } = useGetTripSharedUsers(params.id) + + return ( + + + + Manage Group + + + {!tripSharedUsers || loading ? ( + + ) : ( + + + + {tripSharedUsers.invitationsCollection?.edges.map( + (invitedUser) => { + return ( + + ) + } + )} + + )} + + + + ) +} diff --git a/app/trip/[id]/page.tsx b/app/trip/[id]/page.tsx index 9bc0edb..1b596ff 100644 --- a/app/trip/[id]/page.tsx +++ b/app/trip/[id]/page.tsx @@ -1,13 +1,10 @@ 'use client' -import { useState } from 'react' -import { Box, Container, useColorModeValue, Input } from '@chakra-ui/react' -import { createClient } from '@supabase/supabase-js' +import { Box, Container, useColorModeValue } from '@chakra-ui/react' import { useRouter } from 'next/navigation' import { PrimaryButton } from '@/components/button' import { Loading } from '@/components/loading' import { useTripDetailsGet } from '../hooks' -import { updateImageMetadataAction } from './action/update-image-metadata' import { TripDetailsHeader, TripDetailsTabs } from './components' export default function TripDetailsPage({ @@ -19,40 +16,24 @@ export default function TripDetailsPage({ const color = useColorModeValue('black', 'gray.300') const router = useRouter() - const { tripDetailsData, tripDetailsLoading, tripDetailsRefetch } = - useTripDetailsGet(params.id) + const { tripDetailsData, tripDetailsLoading } = useTripDetailsGet(params.id) if (!tripDetailsData && !tripDetailsLoading) throw new Error('No trip data found') const tripData = tripDetailsData?.tripsCollection - const [selectedImage, setSelectedImage] = useState(null) - const uploadImage = async (id: string, file: File) => { - try { - const supabase = createClient( - process.env.NEXT_PUBLIC_SUPABASE_URL!, - process.env.NEXT_PUBLIC_API_KEY! - ) - - // TODO: Authenticated user can upload images with policy - const { data: uploadData, error: uploadError } = await supabase.storage - .from('tabi-memo-uploads') - .upload(`trips/${id}/${file.name}`, file, { upsert: true }) - - if (uploadError) throw new Error(uploadError.message) - - // NOTE: Server action doen't return result in Client Component. I don't know why. - await updateImageMetadataAction(id, uploadData.path) - - setSelectedImage(file) - await tripDetailsRefetch() - } catch (error) { - console.error({ error }) - throw error - } + const owner = { + id: tripData?.edges[0].node.users.id, + image: tripData?.edges[0].node.users.profile_picture_url } + const sharedUsers = + tripData?.edges[0].node.invitationsCollection?.edges.map((invitation) => ({ + id: invitation.node.users?.id, + image: invitation.node.users?.profile_picture_url + })) || [] + return ( ({ - id: invitation.node.users?.id, - image: invitation.node.users?.profile_picture_url - }) - ) || [] - } + users={[owner, ...sharedUsers]} tags={ tripData.edges[0].node.trip_tagsCollection?.edges.map( (tag) => ({ @@ -110,16 +80,12 @@ export default function TripDetailsPage({ router.push('/activity/create')} + onClick={() => + router.push(`/activity/create?tripId=${params.id}`) + } > Add Activity - uploadImage(params.id, e.target.files![0])} - /> )} diff --git a/app/trip/components/trip-card.tsx b/app/trip/components/trip-card.tsx index df16931..8f1b9a7 100644 --- a/app/trip/components/trip-card.tsx +++ b/app/trip/components/trip-card.tsx @@ -83,29 +83,47 @@ export const TripCard = ({ data }: TripCardProps) => { > {data.node.title} - {data.node.invitationsCollection?.edges && - data.node.invitationsCollection.edges.length > 0 && ( - - {data.node.invitationsCollection?.edges.map((invitation) => ( - - {invitation.node.users?.profile_picture_url ? ( - - ) : ( - - )} - - ))} - - )} + + + {data.node.users.profile_picture_url ? ( + + ) : ( + + )} + + + {data.node.invitationsCollection?.edges && + data.node.invitationsCollection.edges.length > 0 && ( + <> + {data.node.invitationsCollection?.edges.map((invitation) => ( + + {invitation.node.users?.profile_picture_url ? ( + + ) : ( + + )} + + ))} + + )} + {formatDateToSlash(data.node.date_from, 'dayMonthYear')} -{' '} {formatDateToSlash(data.node.date_to, 'dayMonthYear')} diff --git a/app/trip/components/trip-form.tsx b/app/trip/components/trip-form.tsx index 09be2ee..413dd6a 100644 --- a/app/trip/components/trip-form.tsx +++ b/app/trip/components/trip-form.tsx @@ -1,3 +1,4 @@ +import { useState } from 'react' import { useForm, Controller } from 'react-hook-form' import { FormControl, @@ -11,7 +12,8 @@ import { Flex, Checkbox, Box, - useDisclosure + useDisclosure, + Input } from '@chakra-ui/react' import { PrimaryButton, SecondaryButton } from '@/components/button' import { CustomDatePicker } from '@/components/date' @@ -57,6 +59,7 @@ export const TripForm = ({ tripDetails, tags, tripTags }: TripFormProps) => { '/images/no_image_light.jpg', '/images/no_image_dark.jpg' ) + const [selectedImage, setSelectedImage] = useState(null) const { isOpen, onOpen, onClose } = useDisclosure() const { createTrip, isTripCreating } = useTripCreate() @@ -81,6 +84,7 @@ export const TripForm = ({ tripDetails, tags, tripTags }: TripFormProps) => { : undefined, date_to: tripDetails?.dateTo ? getDateObj(tripDetails.dateTo) : null, image_url: tripDetails?.image || null, + uploaded_image_file: null, selectedTags: tripTags ? tripTags.data.map((tag) => tag.tag_id) : [], cost: tripDetails?.cost ? tripDetails.cost.toString() : null, cost_unit: tripDetails?.costUnit @@ -143,14 +147,49 @@ export const TripForm = ({ tripDetails, tags, tripTags }: TripFormProps) => { {errors?.date_to?.message} - {/* TODO Image Upload to storage & Send the URL string to DB */} - + Image - - Select Image + {selectedImage ? ( + Selected Image + ) : ( + Default Image + )} + ( + + Select Image + { + const file = event.target.files?.[0] + if (file) { + setSelectedImage(file) + onChange(file) + } + }} + hidden + /> + + )} + /> - {errors?.image_url?.message} + + {errors?.uploaded_image_file?.message} + diff --git a/app/trip/graphql/query/tripDetails.graphql b/app/trip/graphql/query/tripDetails.graphql index 1c7d132..6c3c575 100644 --- a/app/trip/graphql/query/tripDetails.graphql +++ b/app/trip/graphql/query/tripDetails.graphql @@ -9,6 +9,10 @@ query tripDetails($id: UUID) { image_url cost cost_unit + users { + id + profile_picture_url + } invitationsCollection { edges { node { diff --git a/app/trip/graphql/query/tripsCollection.graphql b/app/trip/graphql/query/tripsCollection.graphql index b446d46..00718ef 100644 --- a/app/trip/graphql/query/tripsCollection.graphql +++ b/app/trip/graphql/query/tripsCollection.graphql @@ -19,6 +19,11 @@ query tripsCollection( date_to image_url created_at + users { + id + name + profile_picture_url + } invitationsCollection { edges { node { diff --git a/app/trip/hooks/useTripCreate.ts b/app/trip/hooks/useTripCreate.ts index 1efd38e..033eea1 100644 --- a/app/trip/hooks/useTripCreate.ts +++ b/app/trip/hooks/useTripCreate.ts @@ -3,6 +3,7 @@ import { useRouter } from 'next/navigation' import { formatToISODate } from '@/libs/utils' import { useUserId } from '@/providers/session-provider' import { TripSchema } from '../schema' +import { useUploadFile } from './useUploadFile' import { useTripsGet } from '.' import { useCreateTripMutation, useCreateTripTagMutation } from '@generated/api' @@ -17,6 +18,7 @@ export const useTripCreate = () => { useCreateTripTagMutation() const { tripsRefetch } = useTripsGet() + const { uploadFile } = useUploadFile() const createTrip = async (data: TripSchema) => { try { @@ -27,7 +29,7 @@ export const useTripCreate = () => { date_from: formatToISODate(data.date_from), date_to: data.date_to ? formatToISODate(data.date_to) : null, image_url: data.image_url, - cost: data.cost, + cost: data.cost || null, cost_unit: data.cost_unit, user_id: userId } @@ -50,6 +52,10 @@ export const useTripCreate = () => { await Promise.all([...createPromises]) + if (data.uploaded_image_file && createdTripId) { + await uploadFile(data.uploaded_image_file, createdTripId) + } + tripsRefetch() router.push('/') diff --git a/app/trip/hooks/useTripUpdate.ts b/app/trip/hooks/useTripUpdate.ts index ca53209..81d0d90 100644 --- a/app/trip/hooks/useTripUpdate.ts +++ b/app/trip/hooks/useTripUpdate.ts @@ -3,6 +3,7 @@ import { useRouter } from 'next/navigation' import { formatToISODate } from '@/libs/utils' import { TripDetailsArgs, TripTagsArgs } from '../components/trip-form' import { TripSchema } from '../schema' +import { useUploadFile } from './useUploadFile' import { useTripsGet } from '.' import { useUpdateTripMutation, @@ -25,13 +26,14 @@ export const useTripUpdate = ( useDeleteTripTagMutation() const { tripsRefetch } = useTripsGet() + const { uploadFile, isMetadataUpdating } = useUploadFile() const updateTrip = async (data: TripSchema) => { if (!tripDetails) throw new Error('Trip details is not found') try { // Trip Update - await updateTripMutation({ + const res = await updateTripMutation({ variables: { id: tripDetails.id, set: { @@ -39,12 +41,16 @@ export const useTripUpdate = ( date_from: formatToISODate(data.date_from), date_to: data.date_to ? formatToISODate(data.date_to) : null, image_url: data.image_url, - cost: data.cost, + cost: data.cost || null, cost_unit: data.cost_unit } } }) + const updatedTripId = res.data?.updatetripsCollection?.records[0]?.id + + if (!updatedTripId) throw new Error('Failed to update a trip') + // TripTags Update const selectedTags = data.selectedTags const tripTagsArray = tripTags?.data || [] @@ -71,10 +77,14 @@ export const useTripUpdate = ( await Promise.all([...deletePromises, ...createPromises]) + if (data.uploaded_image_file && updatedTripId) { + await uploadFile(data.uploaded_image_file, updatedTripId) + } + tripDetails.refetch() tripTags?.refetch() tripsRefetch() - router.push(`/trip/${tripDetails.id}`) + router.push(`/trip/${updatedTripId}`) toast({ title: 'Successfully updated!', @@ -104,6 +114,7 @@ export const useTripUpdate = ( return { updateTrip, isTripUpdating, - isTripTagsUpdating: isTripTagCreating || isTripTagDeleting + isTripTagsUpdating: + isTripTagCreating || isTripTagDeleting || isMetadataUpdating } } diff --git a/app/trip/hooks/useTripsGet.ts b/app/trip/hooks/useTripsGet.ts index 13203a3..1a767d1 100644 --- a/app/trip/hooks/useTripsGet.ts +++ b/app/trip/hooks/useTripsGet.ts @@ -5,6 +5,7 @@ import { useTripsCollectionQuery, TripsOrderBy } from '@generated/api' export const useTripsGet = (searchWord?: string) => { const userId = useUserId() + // TODO - need to change as currently just showing all trips user created. We also need to show invited trips const { data, loading, error, fetchMore, refetch, networkStatus } = useTripsCollectionQuery({ variables: { diff --git a/app/trip/hooks/useUploadFile.ts b/app/trip/hooks/useUploadFile.ts new file mode 100644 index 0000000..c81ac81 --- /dev/null +++ b/app/trip/hooks/useUploadFile.ts @@ -0,0 +1,40 @@ +import { createClient } from '@supabase/supabase-js' +import { useUpdateTripMutation } from '@generated/api' + +export const useUploadFile = () => { + const [updateTripMutation, { loading: isMetadataUpdating }] = + useUpdateTripMutation() + + // Upload image to Supabase Storage & Update image_url by server action + const uploadFile = async (file: File, tripId: string) => { + const supabase = createClient( + process.env.NEXT_PUBLIC_SUPABASE_URL!, + process.env.NEXT_PUBLIC_API_KEY! + ) + + // TODO: Authenticated user can upload images with policy + const { data: uploadData, error: uploadError } = await supabase.storage + .from('tabi-memo-uploads') + .upload(`trips/${tripId}/${file.name}`, file, { upsert: true }) + + if (uploadError) throw new Error(uploadError.message) + + const { + data: { publicUrl } + } = supabase.storage + .from(process.env.NEXT_PUBLIC_BUCKET_NAME!) + .getPublicUrl(uploadData.path) + + // Update image_url by mutation + await updateTripMutation({ + variables: { + id: tripId, + set: { + image_url: publicUrl + } + } + }) + } + + return { uploadFile, isMetadataUpdating } +} diff --git a/app/trip/schema.ts b/app/trip/schema.ts index 6b73ee7..d4de9e7 100644 --- a/app/trip/schema.ts +++ b/app/trip/schema.ts @@ -9,6 +9,15 @@ const tripSchema = z.object({ }), date_to: z.date().nullable(), image_url: z.string().nullable(), + uploaded_image_file: z + .instanceof(File) + .nullable() + .refine((file) => file === null || file.size <= 10_000_000, { + message: 'File size must be less than 10MB' + }) + .refine((file) => file === null || file.type.startsWith('image/'), { + message: 'Only image files are allowed' + }), selectedTags: z.array(z.string()), cost: z.string().nullable(), cost_unit: z.string().nullable() diff --git a/graphql-codegen/generated/api.ts b/graphql-codegen/generated/api.ts index 8fb224a..6f60cd8 100644 --- a/graphql-codegen/generated/api.ts +++ b/graphql-codegen/generated/api.ts @@ -138,8 +138,6 @@ export type Mutation = { deleteFrominvitationsCollection: InvitationsDeleteResponse /** Deletes zero or more records from the `tags` collection */ deleteFromtagsCollection: TagsDeleteResponse - /** Deletes zero or more records from the `test_tenant` collection */ - deleteFromtest_tenantCollection: Test_TenantDeleteResponse /** Deletes zero or more records from the `trip_tags` collection */ deleteFromtrip_tagsCollection: Trip_TagsDeleteResponse /** Deletes zero or more records from the `trips` collection */ @@ -154,8 +152,6 @@ export type Mutation = { insertIntoinvitationsCollection?: Maybe /** Adds one or more `tags` records to the collection */ insertIntotagsCollection?: Maybe - /** Adds one or more `test_tenant` records to the collection */ - insertIntotest_tenantCollection?: Maybe /** Adds one or more `trip_tags` records to the collection */ insertIntotrip_tagsCollection?: Maybe /** Adds one or more `trips` records to the collection */ @@ -170,8 +166,6 @@ export type Mutation = { updateinvitationsCollection: InvitationsUpdateResponse /** Updates zero or more records in the `tags` collection */ updatetagsCollection: TagsUpdateResponse - /** Updates zero or more records in the `test_tenant` collection */ - updatetest_tenantCollection: Test_TenantUpdateResponse /** Updates zero or more records in the `trip_tags` collection */ updatetrip_tagsCollection: Trip_TagsUpdateResponse /** Updates zero or more records in the `trips` collection */ @@ -204,12 +198,6 @@ export type MutationDeleteFromtagsCollectionArgs = { filter?: InputMaybe } -/** The root type for creating and mutating data */ -export type MutationDeleteFromtest_TenantCollectionArgs = { - atMost?: Scalars['Int']['input'] - filter?: InputMaybe -} - /** The root type for creating and mutating data */ export type MutationDeleteFromtrip_TagsCollectionArgs = { atMost?: Scalars['Int']['input'] @@ -248,11 +236,6 @@ export type MutationInsertIntotagsCollectionArgs = { objects: Array } -/** The root type for creating and mutating data */ -export type MutationInsertIntotest_TenantCollectionArgs = { - objects: Array -} - /** The root type for creating and mutating data */ export type MutationInsertIntotrip_TagsCollectionArgs = { objects: Array @@ -296,13 +279,6 @@ export type MutationUpdatetagsCollectionArgs = { set: TagsUpdateInput } -/** The root type for creating and mutating data */ -export type MutationUpdatetest_TenantCollectionArgs = { - atMost?: Scalars['Int']['input'] - filter?: InputMaybe - set: Test_TenantUpdateInput -} - /** The root type for creating and mutating data */ export type MutationUpdatetrip_TagsCollectionArgs = { atMost?: Scalars['Int']['input'] @@ -368,8 +344,6 @@ export type Query = { node?: Maybe /** A pagable collection of type `tags` */ tagsCollection?: Maybe - /** A pagable collection of type `test_tenant` */ - test_tenantCollection?: Maybe /** A pagable collection of type `trip_tags` */ trip_tagsCollection?: Maybe /** A pagable collection of type `trips` */ @@ -423,16 +397,6 @@ export type QueryTagsCollectionArgs = { orderBy?: InputMaybe> } -/** The root type for querying data */ -export type QueryTest_TenantCollectionArgs = { - after?: InputMaybe - before?: InputMaybe - filter?: InputMaybe - first?: InputMaybe - last?: InputMaybe - orderBy?: InputMaybe> -} - /** The root type for querying data */ export type QueryTrip_TagsCollectionArgs = { after?: InputMaybe @@ -515,8 +479,8 @@ export type Activity = Node & { time_from: Scalars['Datetime']['output'] time_to?: Maybe title: Scalars['String']['output'] - trip_id?: Maybe - trips?: Maybe + trip_id: Scalars['UUID']['output'] + trips: Trips url?: Maybe } @@ -551,6 +515,8 @@ export type ActivityEdge = { export type ActivityFilter = { address?: InputMaybe + /** Returns true only if all its inner filters are true, otherwise returns false */ + and?: InputMaybe> cost?: InputMaybe cost_unit?: InputMaybe created_at?: InputMaybe @@ -558,6 +524,10 @@ export type ActivityFilter = { image_url?: InputMaybe memo?: InputMaybe nodeId?: InputMaybe + /** Negates a filter */ + not?: InputMaybe + /** Returns true if at least one of its inner filters is true, otherwise returns false */ + or?: InputMaybe> time_from?: InputMaybe time_to?: InputMaybe title?: InputMaybe @@ -628,9 +598,9 @@ export type ActivityUpdateResponse = { export type Activity_Uploaded_Files = Node & { __typename?: 'activity_uploaded_files' - activity?: Maybe - activity_id?: Maybe - content_type: Scalars['String']['output'] + activity: Activity + activity_id: Scalars['UUID']['output'] + content_type?: Maybe created_at: Scalars['Datetime']['output'] file_data?: Maybe file_name: Scalars['String']['output'] @@ -662,12 +632,18 @@ export type Activity_Uploaded_FilesEdge = { export type Activity_Uploaded_FilesFilter = { activity_id?: InputMaybe + /** Returns true only if all its inner filters are true, otherwise returns false */ + and?: InputMaybe> content_type?: InputMaybe created_at?: InputMaybe file_name?: InputMaybe file_url?: InputMaybe id?: InputMaybe nodeId?: InputMaybe + /** Negates a filter */ + not?: InputMaybe + /** Returns true if at least one of its inner filters is true, otherwise returns false */ + or?: InputMaybe> } export type Activity_Uploaded_FilesInsertInput = { @@ -751,12 +727,18 @@ export type InvitationsEdge = { } export type InvitationsFilter = { + /** Returns true only if all its inner filters are true, otherwise returns false */ + and?: InputMaybe> email?: InputMaybe id?: InputMaybe invitation_url?: InputMaybe invited_by_user_id?: InputMaybe invitee_user_id?: InputMaybe nodeId?: InputMaybe + /** Negates a filter */ + not?: InputMaybe + /** Returns true if at least one of its inner filters is true, otherwise returns false */ + or?: InputMaybe> permission_level?: InputMaybe trip_id?: InputMaybe } @@ -862,10 +844,16 @@ export type TagsEdge = { } export type TagsFilter = { + /** Returns true only if all its inner filters are true, otherwise returns false */ + and?: InputMaybe> created_at?: InputMaybe id?: InputMaybe name?: InputMaybe nodeId?: InputMaybe + /** Negates a filter */ + not?: InputMaybe + /** Returns true if at least one of its inner filters is true, otherwise returns false */ + or?: InputMaybe> user_id?: InputMaybe } @@ -906,78 +894,15 @@ export type TagsUpdateResponse = { records: Array } -export type Test_Tenant = Node & { - __typename?: 'test_tenant' - details?: Maybe - id: Scalars['Int']['output'] - /** Globally Unique Record Identifier */ - nodeId: Scalars['ID']['output'] -} - -export type Test_TenantConnection = { - __typename?: 'test_tenantConnection' - edges: Array - pageInfo: PageInfo -} - -export type Test_TenantDeleteResponse = { - __typename?: 'test_tenantDeleteResponse' - /** Count of the records impacted by the mutation */ - affectedCount: Scalars['Int']['output'] - /** Array of records impacted by the mutation */ - records: Array -} - -export type Test_TenantEdge = { - __typename?: 'test_tenantEdge' - cursor: Scalars['String']['output'] - node: Test_Tenant -} - -export type Test_TenantFilter = { - details?: InputMaybe - id?: InputMaybe - nodeId?: InputMaybe -} - -export type Test_TenantInsertInput = { - details?: InputMaybe -} - -export type Test_TenantInsertResponse = { - __typename?: 'test_tenantInsertResponse' - /** Count of the records impacted by the mutation */ - affectedCount: Scalars['Int']['output'] - /** Array of records impacted by the mutation */ - records: Array -} - -export type Test_TenantOrderBy = { - details?: InputMaybe - id?: InputMaybe -} - -export type Test_TenantUpdateInput = { - details?: InputMaybe -} - -export type Test_TenantUpdateResponse = { - __typename?: 'test_tenantUpdateResponse' - /** Count of the records impacted by the mutation */ - affectedCount: Scalars['Int']['output'] - /** Array of records impacted by the mutation */ - records: Array -} - export type Trip_Tags = Node & { __typename?: 'trip_tags' id: Scalars['UUID']['output'] /** Globally Unique Record Identifier */ nodeId: Scalars['ID']['output'] - tag_id?: Maybe - tags?: Maybe - trip_id?: Maybe - trips?: Maybe + tag_id: Scalars['UUID']['output'] + tags: Tags + trip_id: Scalars['UUID']['output'] + trips: Trips } export type Trip_TagsConnection = { @@ -1001,8 +926,14 @@ export type Trip_TagsEdge = { } export type Trip_TagsFilter = { + /** Returns true only if all its inner filters are true, otherwise returns false */ + and?: InputMaybe> id?: InputMaybe nodeId?: InputMaybe + /** Negates a filter */ + not?: InputMaybe + /** Returns true if at least one of its inner filters is true, otherwise returns false */ + or?: InputMaybe> tag_id?: InputMaybe trip_id?: InputMaybe } @@ -1057,8 +988,8 @@ export type Trips = Node & { nodeId: Scalars['ID']['output'] title: Scalars['String']['output'] trip_tagsCollection?: Maybe - user_id?: Maybe - users?: Maybe + user_id: Scalars['UUID']['output'] + users: Users } export type TripsActivityCollectionArgs = { @@ -1109,6 +1040,8 @@ export type TripsEdge = { } export type TripsFilter = { + /** Returns true only if all its inner filters are true, otherwise returns false */ + and?: InputMaybe> cost?: InputMaybe cost_unit?: InputMaybe created_at?: InputMaybe @@ -1118,6 +1051,10 @@ export type TripsFilter = { id?: InputMaybe image_url?: InputMaybe nodeId?: InputMaybe + /** Negates a filter */ + not?: InputMaybe + /** Returns true if at least one of its inner filters is true, otherwise returns false */ + or?: InputMaybe> title?: InputMaybe user_id?: InputMaybe } @@ -1238,10 +1175,16 @@ export type UsersEdge = { } export type UsersFilter = { + /** Returns true only if all its inner filters are true, otherwise returns false */ + and?: InputMaybe> email?: InputMaybe id?: InputMaybe name?: InputMaybe nodeId?: InputMaybe + /** Negates a filter */ + not?: InputMaybe + /** Returns true if at least one of its inner filters is true, otherwise returns false */ + or?: InputMaybe> profile_picture_url?: InputMaybe } @@ -1303,6 +1246,68 @@ export type GetUserQuery = { } | null } +export type CreateActivityMutationVariables = Exact<{ + object: ActivityInsertInput +}> + +export type CreateActivityMutation = { + __typename: 'Mutation' + insertIntoactivityCollection?: { + __typename: 'activityInsertResponse' + records: Array<{ __typename: 'activity'; id: string; title: string }> + } | null +} + +export type CreateActivityUploadedFilesMutationVariables = Exact<{ + objects: + | Array + | Activity_Uploaded_FilesInsertInput +}> + +export type CreateActivityUploadedFilesMutation = { + __typename: 'Mutation' + insertIntoactivity_uploaded_filesCollection?: { + __typename: 'activity_uploaded_filesInsertResponse' + records: Array<{ + __typename: 'activity_uploaded_files' + id: string + activity_id: string + file_name: string + file_url: string + }> + } | null +} + +export type DeleteActivityMutationVariables = Exact<{ + id: Scalars['UUID']['input'] +}> + +export type DeleteActivityMutation = { + __typename: 'Mutation' + deleteFromactivityCollection: { + __typename: 'activityDeleteResponse' + records: Array<{ + __typename: 'activity' + id: string + trip_id: string + title: string + }> + } +} + +export type UpdateActivityMutationVariables = Exact<{ + id: Scalars['UUID']['input'] + set: ActivityUpdateInput +}> + +export type UpdateActivityMutation = { + __typename: 'Mutation' + updateactivityCollection: { + __typename: 'activityUpdateResponse' + records: Array<{ __typename: 'activity'; id: string; title: string }> + } +} + export type ActivityCollectionQueryVariables = Exact<{ id: Scalars['UUID']['input'] }> @@ -1316,7 +1321,7 @@ export type ActivityCollectionQuery = { node: { __typename: 'activity' id: string - trip_id?: string | null + trip_id: string title: string time_from: string time_to?: string | null @@ -1325,30 +1330,99 @@ export type ActivityCollectionQuery = { memo?: string | null cost?: string | null cost_unit?: string | null - image_url?: string | null + activity_uploaded_filesCollection?: { + __typename: 'activity_uploaded_filesConnection' + edges: Array<{ + __typename: 'activity_uploaded_filesEdge' + node: { + __typename: 'activity_uploaded_files' + id: string + file_name: string + file_url: string + } + }> + } | null } }> } | null } -export type CreateActivityMutationVariables = Exact<{ - trip_id: Scalars['UUID']['input'] - title: Scalars['String']['input'] - time_from?: InputMaybe - time_to?: InputMaybe - address?: InputMaybe - url?: InputMaybe - memo?: InputMaybe - cost?: InputMaybe - cost_unit?: InputMaybe - image_url?: InputMaybe +export type DeleteInvitationMutationVariables = Exact<{ + id: Scalars['UUID']['input'] }> -export type CreateActivityMutation = { +export type DeleteInvitationMutation = { __typename: 'Mutation' - insertIntoactivityCollection?: { - __typename: 'activityInsertResponse' - records: Array<{ __typename: 'activity'; id: string; title: string }> + deleteFrominvitationsCollection: { + __typename: 'invitationsDeleteResponse' + records: Array<{ + __typename: 'invitations' + id: string + email: string + permission_level: Permission_Level_Enum + }> + } +} + +export type UpdateInvitationMutationVariables = Exact<{ + id: Scalars['UUID']['input'] + set: InvitationsUpdateInput +}> + +export type UpdateInvitationMutation = { + __typename: 'Mutation' + updateinvitationsCollection: { + __typename: 'invitationsUpdateResponse' + records: Array<{ + __typename: 'invitations' + id: string + email: string + permission_level: Permission_Level_Enum + }> + } +} + +export type TripSharedUsersQueryVariables = Exact<{ + tripId: Scalars['UUID']['input'] +}> + +export type TripSharedUsersQuery = { + __typename: 'Query' + tripsCollection?: { + __typename: 'tripsConnection' + edges: Array<{ + __typename: 'tripsEdge' + node: { + __typename: 'trips' + id: string + title: string + users: { + __typename: 'users' + id: string + name: string + profile_picture_url?: string | null + email: string + } + invitationsCollection?: { + __typename: 'invitationsConnection' + edges: Array<{ + __typename: 'invitationsEdge' + node: { + __typename: 'invitations' + id: string + permission_level: Permission_Level_Enum + users?: { + __typename: 'users' + id: string + name: string + email: string + profile_picture_url?: string | null + } | null + } + }> + } | null + } + }> } | null } @@ -1389,8 +1463,8 @@ export type CreateTripTagMutation = { records: Array<{ __typename: 'trip_tags' id: string - tag_id?: string | null - trip_id?: string | null + tag_id: string + trip_id: string }> } | null } @@ -1479,6 +1553,11 @@ export type TripDetailsQuery = { image_url?: string | null cost?: string | null cost_unit?: string | null + users: { + __typename: 'users' + id: string + profile_picture_url?: string | null + } invitationsCollection?: { __typename: 'invitationsConnection' edges: Array<{ @@ -1513,7 +1592,7 @@ export type TripDetailsQuery = { __typename: 'trip_tagsEdge' node: { __typename: 'trip_tags' - tags?: { __typename: 'tags'; id: string; name: string } | null + tags: { __typename: 'tags'; id: string; name: string } } }> } | null @@ -1535,8 +1614,8 @@ export type TripTagsCollectionQuery = { node: { __typename: 'trip_tags' id: string - trip_id?: string | null - tag_id?: string | null + trip_id: string + tag_id: string } }> } | null @@ -1563,6 +1642,12 @@ export type TripsCollectionQuery = { date_to?: string | null image_url?: string | null created_at: string + users: { + __typename: 'users' + id: string + name: string + profile_picture_url?: string | null + } invitationsCollection?: { __typename: 'invitationsConnection' edges: Array<{ @@ -1673,6 +1758,237 @@ export type GetUserQueryResult = Apollo.QueryResult< export function refetchGetUserQuery(variables: GetUserQueryVariables) { return { query: GetUserDocument, variables: variables } } +export const CreateActivityDocument = gql` + mutation createActivity($object: activityInsertInput!) { + __typename + insertIntoactivityCollection(objects: [$object]) { + __typename + records { + __typename + id + title + } + } + } +` +export type CreateActivityMutationFn = Apollo.MutationFunction< + CreateActivityMutation, + CreateActivityMutationVariables +> + +/** + * __useCreateActivityMutation__ + * + * To run a mutation, you first call `useCreateActivityMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useCreateActivityMutation` returns a tuple that includes: + * - A mutate function that you can call at any time to execute the mutation + * - An object with fields that represent the current status of the mutation's execution + * + * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; + * + * @example + * const [createActivityMutation, { data, loading, error }] = useCreateActivityMutation({ + * variables: { + * object: // value for 'object' + * }, + * }); + */ +export function useCreateActivityMutation( + baseOptions?: Apollo.MutationHookOptions< + CreateActivityMutation, + CreateActivityMutationVariables + > +) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation< + CreateActivityMutation, + CreateActivityMutationVariables + >(CreateActivityDocument, options) +} +export type CreateActivityMutationHookResult = ReturnType< + typeof useCreateActivityMutation +> +export type CreateActivityMutationResult = + Apollo.MutationResult +export type CreateActivityMutationOptions = Apollo.BaseMutationOptions< + CreateActivityMutation, + CreateActivityMutationVariables +> +export const CreateActivityUploadedFilesDocument = gql` + mutation createActivityUploadedFiles( + $objects: [activity_uploaded_filesInsertInput!]! + ) { + __typename + insertIntoactivity_uploaded_filesCollection(objects: $objects) { + __typename + records { + __typename + id + activity_id + file_name + file_url + } + } + } +` +export type CreateActivityUploadedFilesMutationFn = Apollo.MutationFunction< + CreateActivityUploadedFilesMutation, + CreateActivityUploadedFilesMutationVariables +> + +/** + * __useCreateActivityUploadedFilesMutation__ + * + * To run a mutation, you first call `useCreateActivityUploadedFilesMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useCreateActivityUploadedFilesMutation` returns a tuple that includes: + * - A mutate function that you can call at any time to execute the mutation + * - An object with fields that represent the current status of the mutation's execution + * + * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; + * + * @example + * const [createActivityUploadedFilesMutation, { data, loading, error }] = useCreateActivityUploadedFilesMutation({ + * variables: { + * objects: // value for 'objects' + * }, + * }); + */ +export function useCreateActivityUploadedFilesMutation( + baseOptions?: Apollo.MutationHookOptions< + CreateActivityUploadedFilesMutation, + CreateActivityUploadedFilesMutationVariables + > +) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation< + CreateActivityUploadedFilesMutation, + CreateActivityUploadedFilesMutationVariables + >(CreateActivityUploadedFilesDocument, options) +} +export type CreateActivityUploadedFilesMutationHookResult = ReturnType< + typeof useCreateActivityUploadedFilesMutation +> +export type CreateActivityUploadedFilesMutationResult = + Apollo.MutationResult +export type CreateActivityUploadedFilesMutationOptions = + Apollo.BaseMutationOptions< + CreateActivityUploadedFilesMutation, + CreateActivityUploadedFilesMutationVariables + > +export const DeleteActivityDocument = gql` + mutation DeleteActivity($id: UUID!) { + __typename + deleteFromactivityCollection(filter: { id: { eq: $id } }) { + __typename + records { + __typename + id + trip_id + title + } + } + } +` +export type DeleteActivityMutationFn = Apollo.MutationFunction< + DeleteActivityMutation, + DeleteActivityMutationVariables +> + +/** + * __useDeleteActivityMutation__ + * + * To run a mutation, you first call `useDeleteActivityMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useDeleteActivityMutation` returns a tuple that includes: + * - A mutate function that you can call at any time to execute the mutation + * - An object with fields that represent the current status of the mutation's execution + * + * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; + * + * @example + * const [deleteActivityMutation, { data, loading, error }] = useDeleteActivityMutation({ + * variables: { + * id: // value for 'id' + * }, + * }); + */ +export function useDeleteActivityMutation( + baseOptions?: Apollo.MutationHookOptions< + DeleteActivityMutation, + DeleteActivityMutationVariables + > +) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation< + DeleteActivityMutation, + DeleteActivityMutationVariables + >(DeleteActivityDocument, options) +} +export type DeleteActivityMutationHookResult = ReturnType< + typeof useDeleteActivityMutation +> +export type DeleteActivityMutationResult = + Apollo.MutationResult +export type DeleteActivityMutationOptions = Apollo.BaseMutationOptions< + DeleteActivityMutation, + DeleteActivityMutationVariables +> +export const UpdateActivityDocument = gql` + mutation updateActivity($id: UUID!, $set: activityUpdateInput!) { + __typename + updateactivityCollection(set: $set, filter: { id: { eq: $id } }) { + __typename + records { + __typename + id + title + } + } + } +` +export type UpdateActivityMutationFn = Apollo.MutationFunction< + UpdateActivityMutation, + UpdateActivityMutationVariables +> + +/** + * __useUpdateActivityMutation__ + * + * To run a mutation, you first call `useUpdateActivityMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useUpdateActivityMutation` returns a tuple that includes: + * - A mutate function that you can call at any time to execute the mutation + * - An object with fields that represent the current status of the mutation's execution + * + * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; + * + * @example + * const [updateActivityMutation, { data, loading, error }] = useUpdateActivityMutation({ + * variables: { + * id: // value for 'id' + * set: // value for 'set' + * }, + * }); + */ +export function useUpdateActivityMutation( + baseOptions?: Apollo.MutationHookOptions< + UpdateActivityMutation, + UpdateActivityMutationVariables + > +) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation< + UpdateActivityMutation, + UpdateActivityMutationVariables + >(UpdateActivityDocument, options) +} +export type UpdateActivityMutationHookResult = ReturnType< + typeof useUpdateActivityMutation +> +export type UpdateActivityMutationResult = + Apollo.MutationResult +export type UpdateActivityMutationOptions = Apollo.BaseMutationOptions< + UpdateActivityMutation, + UpdateActivityMutationVariables +> export const ActivityCollectionDocument = gql` query activityCollection($id: UUID!) { __typename @@ -1692,7 +2008,18 @@ export const ActivityCollectionDocument = gql` memo cost cost_unit - image_url + activity_uploaded_filesCollection { + __typename + edges { + __typename + node { + __typename + id + file_name + file_url + } + } + } } } } @@ -1769,97 +2096,233 @@ export function refetchActivityCollectionQuery( ) { return { query: ActivityCollectionDocument, variables: variables } } -export const CreateActivityDocument = gql` - mutation createActivity( - $trip_id: UUID! - $title: String! - $time_from: Datetime - $time_to: Datetime - $address: String - $url: String - $memo: String - $cost: BigFloat - $cost_unit: String - $image_url: String - ) { +export const DeleteInvitationDocument = gql` + mutation deleteInvitation($id: UUID!) { __typename - insertIntoactivityCollection( - objects: [ - { - trip_id: $trip_id - title: $title - time_from: $time_from - time_to: $time_to - address: $address - url: $url - memo: $memo - cost: $cost - cost_unit: $cost_unit - image_url: $image_url - } - ] - ) { + deleteFrominvitationsCollection(filter: { id: { eq: $id } }) { __typename records { __typename id - title + email + permission_level } } } ` -export type CreateActivityMutationFn = Apollo.MutationFunction< - CreateActivityMutation, - CreateActivityMutationVariables +export type DeleteInvitationMutationFn = Apollo.MutationFunction< + DeleteInvitationMutation, + DeleteInvitationMutationVariables > /** - * __useCreateActivityMutation__ + * __useDeleteInvitationMutation__ * - * To run a mutation, you first call `useCreateActivityMutation` within a React component and pass it any options that fit your needs. - * When your component renders, `useCreateActivityMutation` returns a tuple that includes: + * To run a mutation, you first call `useDeleteInvitationMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useDeleteInvitationMutation` returns a tuple that includes: * - A mutate function that you can call at any time to execute the mutation * - An object with fields that represent the current status of the mutation's execution * * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; * * @example - * const [createActivityMutation, { data, loading, error }] = useCreateActivityMutation({ + * const [deleteInvitationMutation, { data, loading, error }] = useDeleteInvitationMutation({ * variables: { - * trip_id: // value for 'trip_id' - * title: // value for 'title' - * time_from: // value for 'time_from' - * time_to: // value for 'time_to' - * address: // value for 'address' - * url: // value for 'url' - * memo: // value for 'memo' - * cost: // value for 'cost' - * cost_unit: // value for 'cost_unit' - * image_url: // value for 'image_url' + * id: // value for 'id' * }, * }); */ -export function useCreateActivityMutation( +export function useDeleteInvitationMutation( baseOptions?: Apollo.MutationHookOptions< - CreateActivityMutation, - CreateActivityMutationVariables + DeleteInvitationMutation, + DeleteInvitationMutationVariables > ) { const options = { ...defaultOptions, ...baseOptions } return Apollo.useMutation< - CreateActivityMutation, - CreateActivityMutationVariables - >(CreateActivityDocument, options) + DeleteInvitationMutation, + DeleteInvitationMutationVariables + >(DeleteInvitationDocument, options) } -export type CreateActivityMutationHookResult = ReturnType< - typeof useCreateActivityMutation +export type DeleteInvitationMutationHookResult = ReturnType< + typeof useDeleteInvitationMutation > -export type CreateActivityMutationResult = - Apollo.MutationResult -export type CreateActivityMutationOptions = Apollo.BaseMutationOptions< - CreateActivityMutation, - CreateActivityMutationVariables +export type DeleteInvitationMutationResult = + Apollo.MutationResult +export type DeleteInvitationMutationOptions = Apollo.BaseMutationOptions< + DeleteInvitationMutation, + DeleteInvitationMutationVariables +> +export const UpdateInvitationDocument = gql` + mutation updateInvitation($id: UUID!, $set: invitationsUpdateInput!) { + __typename + updateinvitationsCollection(set: $set, filter: { id: { eq: $id } }) { + __typename + records { + __typename + id + email + permission_level + } + } + } +` +export type UpdateInvitationMutationFn = Apollo.MutationFunction< + UpdateInvitationMutation, + UpdateInvitationMutationVariables +> + +/** + * __useUpdateInvitationMutation__ + * + * To run a mutation, you first call `useUpdateInvitationMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useUpdateInvitationMutation` returns a tuple that includes: + * - A mutate function that you can call at any time to execute the mutation + * - An object with fields that represent the current status of the mutation's execution + * + * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; + * + * @example + * const [updateInvitationMutation, { data, loading, error }] = useUpdateInvitationMutation({ + * variables: { + * id: // value for 'id' + * set: // value for 'set' + * }, + * }); + */ +export function useUpdateInvitationMutation( + baseOptions?: Apollo.MutationHookOptions< + UpdateInvitationMutation, + UpdateInvitationMutationVariables + > +) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation< + UpdateInvitationMutation, + UpdateInvitationMutationVariables + >(UpdateInvitationDocument, options) +} +export type UpdateInvitationMutationHookResult = ReturnType< + typeof useUpdateInvitationMutation +> +export type UpdateInvitationMutationResult = + Apollo.MutationResult +export type UpdateInvitationMutationOptions = Apollo.BaseMutationOptions< + UpdateInvitationMutation, + UpdateInvitationMutationVariables +> +export const TripSharedUsersDocument = gql` + query tripSharedUsers($tripId: UUID!) { + __typename + tripsCollection(filter: { id: { eq: $tripId } }) { + __typename + edges { + __typename + node { + __typename + id + title + users { + __typename + id + name + profile_picture_url + email + } + invitationsCollection { + __typename + edges { + __typename + node { + __typename + id + permission_level + users { + __typename + id + name + email + profile_picture_url + } + } + } + } + } + } + } + } +` + +/** + * __useTripSharedUsersQuery__ + * + * To run a query within a React component, call `useTripSharedUsersQuery` and pass it any options that fit your needs. + * When your component renders, `useTripSharedUsersQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useTripSharedUsersQuery({ + * variables: { + * tripId: // value for 'tripId' + * }, + * }); + */ +export function useTripSharedUsersQuery( + baseOptions: Apollo.QueryHookOptions< + TripSharedUsersQuery, + TripSharedUsersQueryVariables + > +) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useQuery( + TripSharedUsersDocument, + options + ) +} +export function useTripSharedUsersLazyQuery( + baseOptions?: Apollo.LazyQueryHookOptions< + TripSharedUsersQuery, + TripSharedUsersQueryVariables + > +) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useLazyQuery< + TripSharedUsersQuery, + TripSharedUsersQueryVariables + >(TripSharedUsersDocument, options) +} +export function useTripSharedUsersSuspenseQuery( + baseOptions?: Apollo.SuspenseQueryHookOptions< + TripSharedUsersQuery, + TripSharedUsersQueryVariables + > +) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useSuspenseQuery< + TripSharedUsersQuery, + TripSharedUsersQueryVariables + >(TripSharedUsersDocument, options) +} +export type TripSharedUsersQueryHookResult = ReturnType< + typeof useTripSharedUsersQuery +> +export type TripSharedUsersLazyQueryHookResult = ReturnType< + typeof useTripSharedUsersLazyQuery +> +export type TripSharedUsersSuspenseQueryHookResult = ReturnType< + typeof useTripSharedUsersSuspenseQuery > +export type TripSharedUsersQueryResult = Apollo.QueryResult< + TripSharedUsersQuery, + TripSharedUsersQueryVariables +> +export function refetchTripSharedUsersQuery( + variables: TripSharedUsersQueryVariables +) { + return { query: TripSharedUsersDocument, variables: variables } +} export const CreateTagDocument = gql` mutation createTag($name: String!, $userId: UUID!) { __typename @@ -2361,6 +2824,11 @@ export const TripDetailsDocument = gql` image_url cost cost_unit + users { + __typename + id + profile_picture_url + } invitationsCollection { __typename edges { @@ -2589,6 +3057,12 @@ export const TripsCollectionDocument = gql` date_to image_url created_at + users { + __typename + id + name + profile_picture_url + } invitationsCollection { __typename edges { diff --git a/graphql-codegen/generated/gql.ts b/graphql-codegen/generated/gql.ts index 5136b13..0d1b02e 100644 --- a/graphql-codegen/generated/gql.ts +++ b/graphql-codegen/generated/gql.ts @@ -15,10 +15,22 @@ import type { TypedDocumentNode as DocumentNode } from '@graphql-typed-document- const documents = { 'query getUser($id: UUID!) {\n usersCollection(filter: {id: {eq: $id}}) {\n edges {\n node {\n id\n email\n name\n profile_picture_url\n }\n }\n }\n}': types.GetUserDocument, - 'query activityCollection($id: UUID!) {\n activityCollection(filter: {id: {eq: $id}}) {\n edges {\n node {\n id\n trip_id\n title\n time_from\n time_to\n address\n url\n memo\n cost\n cost_unit\n image_url\n }\n }\n }\n}': - types.ActivityCollectionDocument, - 'mutation createActivity($trip_id: UUID!, $title: String!, $time_from: Datetime, $time_to: Datetime, $address: String, $url: String, $memo: String, $cost: BigFloat, $cost_unit: String, $image_url: String) {\n insertIntoactivityCollection(\n objects: [{trip_id: $trip_id, title: $title, time_from: $time_from, time_to: $time_to, address: $address, url: $url, memo: $memo, cost: $cost, cost_unit: $cost_unit, image_url: $image_url}]\n ) {\n records {\n __typename\n id\n title\n }\n }\n}': + 'mutation createActivity($object: activityInsertInput!) {\n insertIntoactivityCollection(objects: [$object]) {\n records {\n __typename\n id\n title\n }\n }\n}': types.CreateActivityDocument, + 'mutation createActivityUploadedFiles($objects: [activity_uploaded_filesInsertInput!]!) {\n insertIntoactivity_uploaded_filesCollection(objects: $objects) {\n records {\n __typename\n id\n activity_id\n file_name\n file_url\n }\n }\n}': + types.CreateActivityUploadedFilesDocument, + 'mutation DeleteActivity($id: UUID!) {\n deleteFromactivityCollection(filter: {id: {eq: $id}}) {\n records {\n __typename\n id\n trip_id\n title\n }\n }\n}': + types.DeleteActivityDocument, + 'mutation updateActivity($id: UUID!, $set: activityUpdateInput!) {\n updateactivityCollection(set: $set, filter: {id: {eq: $id}}) {\n records {\n id\n title\n }\n }\n}': + types.UpdateActivityDocument, + 'query activityCollection($id: UUID!) {\n activityCollection(filter: {id: {eq: $id}}) {\n edges {\n node {\n id\n trip_id\n title\n time_from\n time_to\n address\n url\n memo\n cost\n cost_unit\n activity_uploaded_filesCollection {\n edges {\n node {\n id\n file_name\n file_url\n }\n }\n }\n }\n }\n }\n}': + types.ActivityCollectionDocument, + 'mutation deleteInvitation($id: UUID!) {\n deleteFrominvitationsCollection(filter: {id: {eq: $id}}) {\n records {\n __typename\n id\n email\n permission_level\n }\n }\n}': + types.DeleteInvitationDocument, + 'mutation updateInvitation($id: UUID!, $set: invitationsUpdateInput!) {\n updateinvitationsCollection(set: $set, filter: {id: {eq: $id}}) {\n records {\n id\n email\n permission_level\n }\n }\n}': + types.UpdateInvitationDocument, + 'query tripSharedUsers($tripId: UUID!) {\n tripsCollection(filter: {id: {eq: $tripId}}) {\n edges {\n node {\n id\n title\n users {\n id\n name\n profile_picture_url\n email\n }\n invitationsCollection {\n edges {\n node {\n id\n permission_level\n users {\n id\n name\n email\n profile_picture_url\n }\n }\n }\n }\n }\n }\n }\n}': + types.TripSharedUsersDocument, 'mutation createTag($name: String!, $userId: UUID!) {\n insertIntotagsCollection(objects: [{name: $name, user_id: $userId}]) {\n records {\n __typename\n id\n name\n }\n }\n}': types.CreateTagDocument, 'mutation createTrip($object: tripsInsertInput!) {\n insertIntotripsCollection(objects: [$object]) {\n records {\n __typename\n id\n title\n }\n }\n}': @@ -35,11 +47,11 @@ const documents = { types.UpdateTripDocument, 'query tagsCollection($userId: UUID!) {\n tagsCollection(\n filter: {user_id: {eq: $userId}}\n orderBy: {created_at: AscNullsLast}\n ) {\n edges {\n node {\n id\n name\n }\n }\n }\n}': types.TagsCollectionDocument, - 'query tripDetails($id: UUID) {\n tripsCollection(filter: {id: {eq: $id}}) {\n edges {\n node {\n id\n title\n date_from\n date_to\n image_url\n cost\n cost_unit\n invitationsCollection {\n edges {\n node {\n users {\n id\n profile_picture_url\n }\n }\n }\n }\n activityCollection {\n edges {\n node {\n id\n title\n time_from\n time_to\n address\n }\n }\n }\n trip_tagsCollection {\n edges {\n node {\n tags {\n id\n name\n }\n }\n }\n }\n }\n }\n }\n}': + 'query tripDetails($id: UUID) {\n tripsCollection(filter: {id: {eq: $id}}) {\n edges {\n node {\n id\n title\n date_from\n date_to\n image_url\n cost\n cost_unit\n users {\n id\n profile_picture_url\n }\n invitationsCollection {\n edges {\n node {\n users {\n id\n profile_picture_url\n }\n }\n }\n }\n activityCollection {\n edges {\n node {\n id\n title\n time_from\n time_to\n address\n }\n }\n }\n trip_tagsCollection {\n edges {\n node {\n tags {\n id\n name\n }\n }\n }\n }\n }\n }\n }\n}': types.TripDetailsDocument, 'query tripTagsCollection($filter: trip_tagsFilter) {\n trip_tagsCollection(filter: $filter) {\n edges {\n node {\n id\n trip_id\n tag_id\n }\n }\n }\n}': types.TripTagsCollectionDocument, - 'query tripsCollection($filter: tripsFilter, $orderBy: [tripsOrderBy!], $first: Int!, $after: Cursor) {\n tripsCollection(\n filter: $filter\n first: $first\n after: $after\n orderBy: $orderBy\n ) {\n edges {\n node {\n id\n id\n title\n date_from\n date_to\n image_url\n created_at\n invitationsCollection {\n edges {\n node {\n users {\n id\n profile_picture_url\n }\n }\n }\n }\n activityCollection {\n edges {\n node {\n id\n }\n }\n }\n }\n }\n pageInfo {\n startCursor\n endCursor\n hasPreviousPage\n hasNextPage\n }\n }\n}': + 'query tripsCollection($filter: tripsFilter, $orderBy: [tripsOrderBy!], $first: Int!, $after: Cursor) {\n tripsCollection(\n filter: $filter\n first: $first\n after: $after\n orderBy: $orderBy\n ) {\n edges {\n node {\n id\n id\n title\n date_from\n date_to\n image_url\n created_at\n users {\n id\n name\n profile_picture_url\n }\n invitationsCollection {\n edges {\n node {\n users {\n id\n profile_picture_url\n }\n }\n }\n }\n activityCollection {\n edges {\n node {\n id\n }\n }\n }\n }\n }\n pageInfo {\n startCursor\n endCursor\n hasPreviousPage\n hasNextPage\n }\n }\n}': types.TripsCollectionDocument } @@ -67,14 +79,50 @@ export function graphql( * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ export function graphql( - source: 'query activityCollection($id: UUID!) {\n activityCollection(filter: {id: {eq: $id}}) {\n edges {\n node {\n id\n trip_id\n title\n time_from\n time_to\n address\n url\n memo\n cost\n cost_unit\n image_url\n }\n }\n }\n}' -): (typeof documents)['query activityCollection($id: UUID!) {\n activityCollection(filter: {id: {eq: $id}}) {\n edges {\n node {\n id\n trip_id\n title\n time_from\n time_to\n address\n url\n memo\n cost\n cost_unit\n image_url\n }\n }\n }\n}'] + source: 'mutation createActivity($object: activityInsertInput!) {\n insertIntoactivityCollection(objects: [$object]) {\n records {\n __typename\n id\n title\n }\n }\n}' +): (typeof documents)['mutation createActivity($object: activityInsertInput!) {\n insertIntoactivityCollection(objects: [$object]) {\n records {\n __typename\n id\n title\n }\n }\n}'] +/** + * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. + */ +export function graphql( + source: 'mutation createActivityUploadedFiles($objects: [activity_uploaded_filesInsertInput!]!) {\n insertIntoactivity_uploaded_filesCollection(objects: $objects) {\n records {\n __typename\n id\n activity_id\n file_name\n file_url\n }\n }\n}' +): (typeof documents)['mutation createActivityUploadedFiles($objects: [activity_uploaded_filesInsertInput!]!) {\n insertIntoactivity_uploaded_filesCollection(objects: $objects) {\n records {\n __typename\n id\n activity_id\n file_name\n file_url\n }\n }\n}'] +/** + * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. + */ +export function graphql( + source: 'mutation DeleteActivity($id: UUID!) {\n deleteFromactivityCollection(filter: {id: {eq: $id}}) {\n records {\n __typename\n id\n trip_id\n title\n }\n }\n}' +): (typeof documents)['mutation DeleteActivity($id: UUID!) {\n deleteFromactivityCollection(filter: {id: {eq: $id}}) {\n records {\n __typename\n id\n trip_id\n title\n }\n }\n}'] +/** + * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. + */ +export function graphql( + source: 'mutation updateActivity($id: UUID!, $set: activityUpdateInput!) {\n updateactivityCollection(set: $set, filter: {id: {eq: $id}}) {\n records {\n id\n title\n }\n }\n}' +): (typeof documents)['mutation updateActivity($id: UUID!, $set: activityUpdateInput!) {\n updateactivityCollection(set: $set, filter: {id: {eq: $id}}) {\n records {\n id\n title\n }\n }\n}'] +/** + * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. + */ +export function graphql( + source: 'query activityCollection($id: UUID!) {\n activityCollection(filter: {id: {eq: $id}}) {\n edges {\n node {\n id\n trip_id\n title\n time_from\n time_to\n address\n url\n memo\n cost\n cost_unit\n activity_uploaded_filesCollection {\n edges {\n node {\n id\n file_name\n file_url\n }\n }\n }\n }\n }\n }\n}' +): (typeof documents)['query activityCollection($id: UUID!) {\n activityCollection(filter: {id: {eq: $id}}) {\n edges {\n node {\n id\n trip_id\n title\n time_from\n time_to\n address\n url\n memo\n cost\n cost_unit\n activity_uploaded_filesCollection {\n edges {\n node {\n id\n file_name\n file_url\n }\n }\n }\n }\n }\n }\n}'] +/** + * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. + */ +export function graphql( + source: 'mutation deleteInvitation($id: UUID!) {\n deleteFrominvitationsCollection(filter: {id: {eq: $id}}) {\n records {\n __typename\n id\n email\n permission_level\n }\n }\n}' +): (typeof documents)['mutation deleteInvitation($id: UUID!) {\n deleteFrominvitationsCollection(filter: {id: {eq: $id}}) {\n records {\n __typename\n id\n email\n permission_level\n }\n }\n}'] +/** + * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. + */ +export function graphql( + source: 'mutation updateInvitation($id: UUID!, $set: invitationsUpdateInput!) {\n updateinvitationsCollection(set: $set, filter: {id: {eq: $id}}) {\n records {\n id\n email\n permission_level\n }\n }\n}' +): (typeof documents)['mutation updateInvitation($id: UUID!, $set: invitationsUpdateInput!) {\n updateinvitationsCollection(set: $set, filter: {id: {eq: $id}}) {\n records {\n id\n email\n permission_level\n }\n }\n}'] /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ export function graphql( - source: 'mutation createActivity($trip_id: UUID!, $title: String!, $time_from: Datetime, $time_to: Datetime, $address: String, $url: String, $memo: String, $cost: BigFloat, $cost_unit: String, $image_url: String) {\n insertIntoactivityCollection(\n objects: [{trip_id: $trip_id, title: $title, time_from: $time_from, time_to: $time_to, address: $address, url: $url, memo: $memo, cost: $cost, cost_unit: $cost_unit, image_url: $image_url}]\n ) {\n records {\n __typename\n id\n title\n }\n }\n}' -): (typeof documents)['mutation createActivity($trip_id: UUID!, $title: String!, $time_from: Datetime, $time_to: Datetime, $address: String, $url: String, $memo: String, $cost: BigFloat, $cost_unit: String, $image_url: String) {\n insertIntoactivityCollection(\n objects: [{trip_id: $trip_id, title: $title, time_from: $time_from, time_to: $time_to, address: $address, url: $url, memo: $memo, cost: $cost, cost_unit: $cost_unit, image_url: $image_url}]\n ) {\n records {\n __typename\n id\n title\n }\n }\n}'] + source: 'query tripSharedUsers($tripId: UUID!) {\n tripsCollection(filter: {id: {eq: $tripId}}) {\n edges {\n node {\n id\n title\n users {\n id\n name\n profile_picture_url\n email\n }\n invitationsCollection {\n edges {\n node {\n id\n permission_level\n users {\n id\n name\n email\n profile_picture_url\n }\n }\n }\n }\n }\n }\n }\n}' +): (typeof documents)['query tripSharedUsers($tripId: UUID!) {\n tripsCollection(filter: {id: {eq: $tripId}}) {\n edges {\n node {\n id\n title\n users {\n id\n name\n profile_picture_url\n email\n }\n invitationsCollection {\n edges {\n node {\n id\n permission_level\n users {\n id\n name\n email\n profile_picture_url\n }\n }\n }\n }\n }\n }\n }\n}'] /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ @@ -127,8 +175,8 @@ export function graphql( * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ export function graphql( - source: 'query tripDetails($id: UUID) {\n tripsCollection(filter: {id: {eq: $id}}) {\n edges {\n node {\n id\n title\n date_from\n date_to\n image_url\n cost\n cost_unit\n invitationsCollection {\n edges {\n node {\n users {\n id\n profile_picture_url\n }\n }\n }\n }\n activityCollection {\n edges {\n node {\n id\n title\n time_from\n time_to\n address\n }\n }\n }\n trip_tagsCollection {\n edges {\n node {\n tags {\n id\n name\n }\n }\n }\n }\n }\n }\n }\n}' -): (typeof documents)['query tripDetails($id: UUID) {\n tripsCollection(filter: {id: {eq: $id}}) {\n edges {\n node {\n id\n title\n date_from\n date_to\n image_url\n cost\n cost_unit\n invitationsCollection {\n edges {\n node {\n users {\n id\n profile_picture_url\n }\n }\n }\n }\n activityCollection {\n edges {\n node {\n id\n title\n time_from\n time_to\n address\n }\n }\n }\n trip_tagsCollection {\n edges {\n node {\n tags {\n id\n name\n }\n }\n }\n }\n }\n }\n }\n}'] + source: 'query tripDetails($id: UUID) {\n tripsCollection(filter: {id: {eq: $id}}) {\n edges {\n node {\n id\n title\n date_from\n date_to\n image_url\n cost\n cost_unit\n users {\n id\n profile_picture_url\n }\n invitationsCollection {\n edges {\n node {\n users {\n id\n profile_picture_url\n }\n }\n }\n }\n activityCollection {\n edges {\n node {\n id\n title\n time_from\n time_to\n address\n }\n }\n }\n trip_tagsCollection {\n edges {\n node {\n tags {\n id\n name\n }\n }\n }\n }\n }\n }\n }\n}' +): (typeof documents)['query tripDetails($id: UUID) {\n tripsCollection(filter: {id: {eq: $id}}) {\n edges {\n node {\n id\n title\n date_from\n date_to\n image_url\n cost\n cost_unit\n users {\n id\n profile_picture_url\n }\n invitationsCollection {\n edges {\n node {\n users {\n id\n profile_picture_url\n }\n }\n }\n }\n activityCollection {\n edges {\n node {\n id\n title\n time_from\n time_to\n address\n }\n }\n }\n trip_tagsCollection {\n edges {\n node {\n tags {\n id\n name\n }\n }\n }\n }\n }\n }\n }\n}'] /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ @@ -139,8 +187,8 @@ export function graphql( * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ export function graphql( - source: 'query tripsCollection($filter: tripsFilter, $orderBy: [tripsOrderBy!], $first: Int!, $after: Cursor) {\n tripsCollection(\n filter: $filter\n first: $first\n after: $after\n orderBy: $orderBy\n ) {\n edges {\n node {\n id\n id\n title\n date_from\n date_to\n image_url\n created_at\n invitationsCollection {\n edges {\n node {\n users {\n id\n profile_picture_url\n }\n }\n }\n }\n activityCollection {\n edges {\n node {\n id\n }\n }\n }\n }\n }\n pageInfo {\n startCursor\n endCursor\n hasPreviousPage\n hasNextPage\n }\n }\n}' -): (typeof documents)['query tripsCollection($filter: tripsFilter, $orderBy: [tripsOrderBy!], $first: Int!, $after: Cursor) {\n tripsCollection(\n filter: $filter\n first: $first\n after: $after\n orderBy: $orderBy\n ) {\n edges {\n node {\n id\n id\n title\n date_from\n date_to\n image_url\n created_at\n invitationsCollection {\n edges {\n node {\n users {\n id\n profile_picture_url\n }\n }\n }\n }\n activityCollection {\n edges {\n node {\n id\n }\n }\n }\n }\n }\n pageInfo {\n startCursor\n endCursor\n hasPreviousPage\n hasNextPage\n }\n }\n}'] + source: 'query tripsCollection($filter: tripsFilter, $orderBy: [tripsOrderBy!], $first: Int!, $after: Cursor) {\n tripsCollection(\n filter: $filter\n first: $first\n after: $after\n orderBy: $orderBy\n ) {\n edges {\n node {\n id\n id\n title\n date_from\n date_to\n image_url\n created_at\n users {\n id\n name\n profile_picture_url\n }\n invitationsCollection {\n edges {\n node {\n users {\n id\n profile_picture_url\n }\n }\n }\n }\n activityCollection {\n edges {\n node {\n id\n }\n }\n }\n }\n }\n pageInfo {\n startCursor\n endCursor\n hasPreviousPage\n hasNextPage\n }\n }\n}' +): (typeof documents)['query tripsCollection($filter: tripsFilter, $orderBy: [tripsOrderBy!], $first: Int!, $after: Cursor) {\n tripsCollection(\n filter: $filter\n first: $first\n after: $after\n orderBy: $orderBy\n ) {\n edges {\n node {\n id\n id\n title\n date_from\n date_to\n image_url\n created_at\n users {\n id\n name\n profile_picture_url\n }\n invitationsCollection {\n edges {\n node {\n users {\n id\n profile_picture_url\n }\n }\n }\n }\n activityCollection {\n edges {\n node {\n id\n }\n }\n }\n }\n }\n pageInfo {\n startCursor\n endCursor\n hasPreviousPage\n hasNextPage\n }\n }\n}'] export function graphql(source: string) { return (documents as any)[source] ?? {} diff --git a/graphql-codegen/generated/graphql.ts b/graphql-codegen/generated/graphql.ts index 1f9ad04..316dc05 100644 --- a/graphql-codegen/generated/graphql.ts +++ b/graphql-codegen/generated/graphql.ts @@ -146,8 +146,6 @@ export type Mutation = { deleteFrominvitationsCollection: InvitationsDeleteResponse /** Deletes zero or more records from the `tags` collection */ deleteFromtagsCollection: TagsDeleteResponse - /** Deletes zero or more records from the `test_tenant` collection */ - deleteFromtest_tenantCollection: Test_TenantDeleteResponse /** Deletes zero or more records from the `trip_tags` collection */ deleteFromtrip_tagsCollection: Trip_TagsDeleteResponse /** Deletes zero or more records from the `trips` collection */ @@ -162,8 +160,6 @@ export type Mutation = { insertIntoinvitationsCollection?: Maybe /** Adds one or more `tags` records to the collection */ insertIntotagsCollection?: Maybe - /** Adds one or more `test_tenant` records to the collection */ - insertIntotest_tenantCollection?: Maybe /** Adds one or more `trip_tags` records to the collection */ insertIntotrip_tagsCollection?: Maybe /** Adds one or more `trips` records to the collection */ @@ -178,8 +174,6 @@ export type Mutation = { updateinvitationsCollection: InvitationsUpdateResponse /** Updates zero or more records in the `tags` collection */ updatetagsCollection: TagsUpdateResponse - /** Updates zero or more records in the `test_tenant` collection */ - updatetest_tenantCollection: Test_TenantUpdateResponse /** Updates zero or more records in the `trip_tags` collection */ updatetrip_tagsCollection: Trip_TagsUpdateResponse /** Updates zero or more records in the `trips` collection */ @@ -212,12 +206,6 @@ export type MutationDeleteFromtagsCollectionArgs = { filter?: InputMaybe } -/** The root type for creating and mutating data */ -export type MutationDeleteFromtest_TenantCollectionArgs = { - atMost?: Scalars['Int']['input'] - filter?: InputMaybe -} - /** The root type for creating and mutating data */ export type MutationDeleteFromtrip_TagsCollectionArgs = { atMost?: Scalars['Int']['input'] @@ -256,11 +244,6 @@ export type MutationInsertIntotagsCollectionArgs = { objects: Array } -/** The root type for creating and mutating data */ -export type MutationInsertIntotest_TenantCollectionArgs = { - objects: Array -} - /** The root type for creating and mutating data */ export type MutationInsertIntotrip_TagsCollectionArgs = { objects: Array @@ -304,13 +287,6 @@ export type MutationUpdatetagsCollectionArgs = { set: TagsUpdateInput } -/** The root type for creating and mutating data */ -export type MutationUpdatetest_TenantCollectionArgs = { - atMost?: Scalars['Int']['input'] - filter?: InputMaybe - set: Test_TenantUpdateInput -} - /** The root type for creating and mutating data */ export type MutationUpdatetrip_TagsCollectionArgs = { atMost?: Scalars['Int']['input'] @@ -376,8 +352,6 @@ export type Query = { node?: Maybe /** A pagable collection of type `tags` */ tagsCollection?: Maybe - /** A pagable collection of type `test_tenant` */ - test_tenantCollection?: Maybe /** A pagable collection of type `trip_tags` */ trip_tagsCollection?: Maybe /** A pagable collection of type `trips` */ @@ -431,16 +405,6 @@ export type QueryTagsCollectionArgs = { orderBy?: InputMaybe> } -/** The root type for querying data */ -export type QueryTest_TenantCollectionArgs = { - after?: InputMaybe - before?: InputMaybe - filter?: InputMaybe - first?: InputMaybe - last?: InputMaybe - orderBy?: InputMaybe> -} - /** The root type for querying data */ export type QueryTrip_TagsCollectionArgs = { after?: InputMaybe @@ -523,8 +487,8 @@ export type Activity = Node & { time_from: Scalars['Datetime']['output'] time_to?: Maybe title: Scalars['String']['output'] - trip_id?: Maybe - trips?: Maybe + trip_id: Scalars['UUID']['output'] + trips: Trips url?: Maybe } @@ -559,6 +523,8 @@ export type ActivityEdge = { export type ActivityFilter = { address?: InputMaybe + /** Returns true only if all its inner filters are true, otherwise returns false */ + and?: InputMaybe> cost?: InputMaybe cost_unit?: InputMaybe created_at?: InputMaybe @@ -566,6 +532,10 @@ export type ActivityFilter = { image_url?: InputMaybe memo?: InputMaybe nodeId?: InputMaybe + /** Negates a filter */ + not?: InputMaybe + /** Returns true if at least one of its inner filters is true, otherwise returns false */ + or?: InputMaybe> time_from?: InputMaybe time_to?: InputMaybe title?: InputMaybe @@ -636,9 +606,9 @@ export type ActivityUpdateResponse = { export type Activity_Uploaded_Files = Node & { __typename?: 'activity_uploaded_files' - activity?: Maybe - activity_id?: Maybe - content_type: Scalars['String']['output'] + activity: Activity + activity_id: Scalars['UUID']['output'] + content_type?: Maybe created_at: Scalars['Datetime']['output'] file_data?: Maybe file_name: Scalars['String']['output'] @@ -670,12 +640,18 @@ export type Activity_Uploaded_FilesEdge = { export type Activity_Uploaded_FilesFilter = { activity_id?: InputMaybe + /** Returns true only if all its inner filters are true, otherwise returns false */ + and?: InputMaybe> content_type?: InputMaybe created_at?: InputMaybe file_name?: InputMaybe file_url?: InputMaybe id?: InputMaybe nodeId?: InputMaybe + /** Negates a filter */ + not?: InputMaybe + /** Returns true if at least one of its inner filters is true, otherwise returns false */ + or?: InputMaybe> } export type Activity_Uploaded_FilesInsertInput = { @@ -759,12 +735,18 @@ export type InvitationsEdge = { } export type InvitationsFilter = { + /** Returns true only if all its inner filters are true, otherwise returns false */ + and?: InputMaybe> email?: InputMaybe id?: InputMaybe invitation_url?: InputMaybe invited_by_user_id?: InputMaybe invitee_user_id?: InputMaybe nodeId?: InputMaybe + /** Negates a filter */ + not?: InputMaybe + /** Returns true if at least one of its inner filters is true, otherwise returns false */ + or?: InputMaybe> permission_level?: InputMaybe trip_id?: InputMaybe } @@ -870,10 +852,16 @@ export type TagsEdge = { } export type TagsFilter = { + /** Returns true only if all its inner filters are true, otherwise returns false */ + and?: InputMaybe> created_at?: InputMaybe id?: InputMaybe name?: InputMaybe nodeId?: InputMaybe + /** Negates a filter */ + not?: InputMaybe + /** Returns true if at least one of its inner filters is true, otherwise returns false */ + or?: InputMaybe> user_id?: InputMaybe } @@ -914,78 +902,15 @@ export type TagsUpdateResponse = { records: Array } -export type Test_Tenant = Node & { - __typename?: 'test_tenant' - details?: Maybe - id: Scalars['Int']['output'] - /** Globally Unique Record Identifier */ - nodeId: Scalars['ID']['output'] -} - -export type Test_TenantConnection = { - __typename?: 'test_tenantConnection' - edges: Array - pageInfo: PageInfo -} - -export type Test_TenantDeleteResponse = { - __typename?: 'test_tenantDeleteResponse' - /** Count of the records impacted by the mutation */ - affectedCount: Scalars['Int']['output'] - /** Array of records impacted by the mutation */ - records: Array -} - -export type Test_TenantEdge = { - __typename?: 'test_tenantEdge' - cursor: Scalars['String']['output'] - node: Test_Tenant -} - -export type Test_TenantFilter = { - details?: InputMaybe - id?: InputMaybe - nodeId?: InputMaybe -} - -export type Test_TenantInsertInput = { - details?: InputMaybe -} - -export type Test_TenantInsertResponse = { - __typename?: 'test_tenantInsertResponse' - /** Count of the records impacted by the mutation */ - affectedCount: Scalars['Int']['output'] - /** Array of records impacted by the mutation */ - records: Array -} - -export type Test_TenantOrderBy = { - details?: InputMaybe - id?: InputMaybe -} - -export type Test_TenantUpdateInput = { - details?: InputMaybe -} - -export type Test_TenantUpdateResponse = { - __typename?: 'test_tenantUpdateResponse' - /** Count of the records impacted by the mutation */ - affectedCount: Scalars['Int']['output'] - /** Array of records impacted by the mutation */ - records: Array -} - export type Trip_Tags = Node & { __typename?: 'trip_tags' id: Scalars['UUID']['output'] /** Globally Unique Record Identifier */ nodeId: Scalars['ID']['output'] - tag_id?: Maybe - tags?: Maybe - trip_id?: Maybe - trips?: Maybe + tag_id: Scalars['UUID']['output'] + tags: Tags + trip_id: Scalars['UUID']['output'] + trips: Trips } export type Trip_TagsConnection = { @@ -1009,8 +934,14 @@ export type Trip_TagsEdge = { } export type Trip_TagsFilter = { + /** Returns true only if all its inner filters are true, otherwise returns false */ + and?: InputMaybe> id?: InputMaybe nodeId?: InputMaybe + /** Negates a filter */ + not?: InputMaybe + /** Returns true if at least one of its inner filters is true, otherwise returns false */ + or?: InputMaybe> tag_id?: InputMaybe trip_id?: InputMaybe } @@ -1065,8 +996,8 @@ export type Trips = Node & { nodeId: Scalars['ID']['output'] title: Scalars['String']['output'] trip_tagsCollection?: Maybe - user_id?: Maybe - users?: Maybe + user_id: Scalars['UUID']['output'] + users: Users } export type TripsActivityCollectionArgs = { @@ -1117,6 +1048,8 @@ export type TripsEdge = { } export type TripsFilter = { + /** Returns true only if all its inner filters are true, otherwise returns false */ + and?: InputMaybe> cost?: InputMaybe cost_unit?: InputMaybe created_at?: InputMaybe @@ -1126,6 +1059,10 @@ export type TripsFilter = { id?: InputMaybe image_url?: InputMaybe nodeId?: InputMaybe + /** Negates a filter */ + not?: InputMaybe + /** Returns true if at least one of its inner filters is true, otherwise returns false */ + or?: InputMaybe> title?: InputMaybe user_id?: InputMaybe } @@ -1246,10 +1183,16 @@ export type UsersEdge = { } export type UsersFilter = { + /** Returns true only if all its inner filters are true, otherwise returns false */ + and?: InputMaybe> email?: InputMaybe id?: InputMaybe name?: InputMaybe nodeId?: InputMaybe + /** Negates a filter */ + not?: InputMaybe + /** Returns true if at least one of its inner filters is true, otherwise returns false */ + or?: InputMaybe> profile_picture_url?: InputMaybe } @@ -1311,6 +1254,68 @@ export type GetUserQuery = { } | null } +export type CreateActivityMutationVariables = Exact<{ + object: ActivityInsertInput +}> + +export type CreateActivityMutation = { + __typename: 'Mutation' + insertIntoactivityCollection?: { + __typename: 'activityInsertResponse' + records: Array<{ __typename: 'activity'; id: string; title: string }> + } | null +} + +export type CreateActivityUploadedFilesMutationVariables = Exact<{ + objects: + | Array + | Activity_Uploaded_FilesInsertInput +}> + +export type CreateActivityUploadedFilesMutation = { + __typename: 'Mutation' + insertIntoactivity_uploaded_filesCollection?: { + __typename: 'activity_uploaded_filesInsertResponse' + records: Array<{ + __typename: 'activity_uploaded_files' + id: string + activity_id: string + file_name: string + file_url: string + }> + } | null +} + +export type DeleteActivityMutationVariables = Exact<{ + id: Scalars['UUID']['input'] +}> + +export type DeleteActivityMutation = { + __typename: 'Mutation' + deleteFromactivityCollection: { + __typename: 'activityDeleteResponse' + records: Array<{ + __typename: 'activity' + id: string + trip_id: string + title: string + }> + } +} + +export type UpdateActivityMutationVariables = Exact<{ + id: Scalars['UUID']['input'] + set: ActivityUpdateInput +}> + +export type UpdateActivityMutation = { + __typename: 'Mutation' + updateactivityCollection: { + __typename: 'activityUpdateResponse' + records: Array<{ __typename: 'activity'; id: string; title: string }> + } +} + export type ActivityCollectionQueryVariables = Exact<{ id: Scalars['UUID']['input'] }> @@ -1324,7 +1329,7 @@ export type ActivityCollectionQuery = { node: { __typename: 'activity' id: string - trip_id?: string | null + trip_id: string title: string time_from: string time_to?: string | null @@ -1333,30 +1338,99 @@ export type ActivityCollectionQuery = { memo?: string | null cost?: string | null cost_unit?: string | null - image_url?: string | null + activity_uploaded_filesCollection?: { + __typename: 'activity_uploaded_filesConnection' + edges: Array<{ + __typename: 'activity_uploaded_filesEdge' + node: { + __typename: 'activity_uploaded_files' + id: string + file_name: string + file_url: string + } + }> + } | null } }> } | null } -export type CreateActivityMutationVariables = Exact<{ - trip_id: Scalars['UUID']['input'] - title: Scalars['String']['input'] - time_from?: InputMaybe - time_to?: InputMaybe - address?: InputMaybe - url?: InputMaybe - memo?: InputMaybe - cost?: InputMaybe - cost_unit?: InputMaybe - image_url?: InputMaybe +export type DeleteInvitationMutationVariables = Exact<{ + id: Scalars['UUID']['input'] }> -export type CreateActivityMutation = { +export type DeleteInvitationMutation = { __typename: 'Mutation' - insertIntoactivityCollection?: { - __typename: 'activityInsertResponse' - records: Array<{ __typename: 'activity'; id: string; title: string }> + deleteFrominvitationsCollection: { + __typename: 'invitationsDeleteResponse' + records: Array<{ + __typename: 'invitations' + id: string + email: string + permission_level: Permission_Level_Enum + }> + } +} + +export type UpdateInvitationMutationVariables = Exact<{ + id: Scalars['UUID']['input'] + set: InvitationsUpdateInput +}> + +export type UpdateInvitationMutation = { + __typename: 'Mutation' + updateinvitationsCollection: { + __typename: 'invitationsUpdateResponse' + records: Array<{ + __typename: 'invitations' + id: string + email: string + permission_level: Permission_Level_Enum + }> + } +} + +export type TripSharedUsersQueryVariables = Exact<{ + tripId: Scalars['UUID']['input'] +}> + +export type TripSharedUsersQuery = { + __typename: 'Query' + tripsCollection?: { + __typename: 'tripsConnection' + edges: Array<{ + __typename: 'tripsEdge' + node: { + __typename: 'trips' + id: string + title: string + users: { + __typename: 'users' + id: string + name: string + profile_picture_url?: string | null + email: string + } + invitationsCollection?: { + __typename: 'invitationsConnection' + edges: Array<{ + __typename: 'invitationsEdge' + node: { + __typename: 'invitations' + id: string + permission_level: Permission_Level_Enum + users?: { + __typename: 'users' + id: string + name: string + email: string + profile_picture_url?: string | null + } | null + } + }> + } | null + } + }> } | null } @@ -1397,8 +1471,8 @@ export type CreateTripTagMutation = { records: Array<{ __typename: 'trip_tags' id: string - tag_id?: string | null - trip_id?: string | null + tag_id: string + trip_id: string }> } | null } @@ -1487,6 +1561,11 @@ export type TripDetailsQuery = { image_url?: string | null cost?: string | null cost_unit?: string | null + users: { + __typename: 'users' + id: string + profile_picture_url?: string | null + } invitationsCollection?: { __typename: 'invitationsConnection' edges: Array<{ @@ -1521,7 +1600,7 @@ export type TripDetailsQuery = { __typename: 'trip_tagsEdge' node: { __typename: 'trip_tags' - tags?: { __typename: 'tags'; id: string; name: string } | null + tags: { __typename: 'tags'; id: string; name: string } } }> } | null @@ -1543,8 +1622,8 @@ export type TripTagsCollectionQuery = { node: { __typename: 'trip_tags' id: string - trip_id?: string | null - tag_id?: string | null + trip_id: string + tag_id: string } }> } | null @@ -1571,6 +1650,12 @@ export type TripsCollectionQuery = { date_to?: string | null image_url?: string | null created_at: string + users: { + __typename: 'users' + id: string + name: string + profile_picture_url?: string | null + } invitationsCollection?: { __typename: 'invitationsConnection' edges: Array<{ @@ -1714,21 +1799,27 @@ export const GetUserDocument = { } ] } as unknown as DocumentNode -export const ActivityCollectionDocument = { - __meta__: { hash: '5ba311a19d53ac42096cb55d1830aaf08f96fccf' }, +export const CreateActivityDocument = { + __meta__: { hash: '374de4fe4f2de1741f44619ae25c008fee655937' }, kind: 'Document', definitions: [ { kind: 'OperationDefinition', - operation: 'query', - name: { kind: 'Name', value: 'activityCollection' }, + operation: 'mutation', + name: { kind: 'Name', value: 'createActivity' }, variableDefinitions: [ { kind: 'VariableDefinition', - variable: { kind: 'Variable', name: { kind: 'Name', value: 'id' } }, + variable: { + kind: 'Variable', + name: { kind: 'Name', value: 'object' } + }, type: { kind: 'NonNullType', - type: { kind: 'NamedType', name: { kind: 'Name', value: 'UUID' } } + type: { + kind: 'NamedType', + name: { kind: 'Name', value: 'activityInsertInput' } + } } } ], @@ -1738,30 +1829,17 @@ export const ActivityCollectionDocument = { { kind: 'Field', name: { kind: 'Name', value: '__typename' } }, { kind: 'Field', - name: { kind: 'Name', value: 'activityCollection' }, + name: { kind: 'Name', value: 'insertIntoactivityCollection' }, arguments: [ { kind: 'Argument', - name: { kind: 'Name', value: 'filter' }, + name: { kind: 'Name', value: 'objects' }, value: { - kind: 'ObjectValue', - fields: [ + kind: 'ListValue', + values: [ { - kind: 'ObjectField', - name: { kind: 'Name', value: 'id' }, - value: { - kind: 'ObjectValue', - fields: [ - { - kind: 'ObjectField', - name: { kind: 'Name', value: 'eq' }, - value: { - kind: 'Variable', - name: { kind: 'Name', value: 'id' } - } - } - ] - } + kind: 'Variable', + name: { kind: 'Name', value: 'object' } } ] } @@ -1773,7 +1851,7 @@ export const ActivityCollectionDocument = { { kind: 'Field', name: { kind: 'Name', value: '__typename' } }, { kind: 'Field', - name: { kind: 'Name', value: 'edges' }, + name: { kind: 'Name', value: 'records' }, selectionSet: { kind: 'SelectionSet', selections: [ @@ -1781,51 +1859,417 @@ export const ActivityCollectionDocument = { kind: 'Field', name: { kind: 'Name', value: '__typename' } }, - { - kind: 'Field', - name: { kind: 'Name', value: 'node' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: '__typename' } - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'id' } - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'trip_id' } - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'title' } - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'time_from' } - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'time_to' } - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'address' } - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'url' } - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'memo' } - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'cost' } + { kind: 'Field', name: { kind: 'Name', value: 'id' } }, + { kind: 'Field', name: { kind: 'Name', value: 'title' } } + ] + } + } + ] + } + } + ] + } + } + ] +} as unknown as DocumentNode< + CreateActivityMutation, + CreateActivityMutationVariables +> +export const CreateActivityUploadedFilesDocument = { + __meta__: { hash: '9b12c83c4bb7cae7ead1221919c3842b1d446e35' }, + kind: 'Document', + definitions: [ + { + kind: 'OperationDefinition', + operation: 'mutation', + name: { kind: 'Name', value: 'createActivityUploadedFiles' }, + variableDefinitions: [ + { + kind: 'VariableDefinition', + variable: { + kind: 'Variable', + name: { kind: 'Name', value: 'objects' } + }, + type: { + kind: 'NonNullType', + type: { + kind: 'ListType', + type: { + kind: 'NonNullType', + type: { + kind: 'NamedType', + name: { + kind: 'Name', + value: 'activity_uploaded_filesInsertInput' + } + } + } + } + } + } + ], + selectionSet: { + kind: 'SelectionSet', + selections: [ + { kind: 'Field', name: { kind: 'Name', value: '__typename' } }, + { + kind: 'Field', + name: { + kind: 'Name', + value: 'insertIntoactivity_uploaded_filesCollection' + }, + arguments: [ + { + kind: 'Argument', + name: { kind: 'Name', value: 'objects' }, + value: { + kind: 'Variable', + name: { kind: 'Name', value: 'objects' } + } + } + ], + selectionSet: { + kind: 'SelectionSet', + selections: [ + { kind: 'Field', name: { kind: 'Name', value: '__typename' } }, + { + kind: 'Field', + name: { kind: 'Name', value: 'records' }, + selectionSet: { + kind: 'SelectionSet', + selections: [ + { + kind: 'Field', + name: { kind: 'Name', value: '__typename' } + }, + { kind: 'Field', name: { kind: 'Name', value: 'id' } }, + { + kind: 'Field', + name: { kind: 'Name', value: 'activity_id' } + }, + { + kind: 'Field', + name: { kind: 'Name', value: 'file_name' } + }, + { + kind: 'Field', + name: { kind: 'Name', value: 'file_url' } + } + ] + } + } + ] + } + } + ] + } + } + ] +} as unknown as DocumentNode< + CreateActivityUploadedFilesMutation, + CreateActivityUploadedFilesMutationVariables +> +export const DeleteActivityDocument = { + __meta__: { hash: 'f86bef447c736e2937994ec37ca883ee109fa6c5' }, + kind: 'Document', + definitions: [ + { + kind: 'OperationDefinition', + operation: 'mutation', + name: { kind: 'Name', value: 'DeleteActivity' }, + variableDefinitions: [ + { + kind: 'VariableDefinition', + variable: { kind: 'Variable', name: { kind: 'Name', value: 'id' } }, + type: { + kind: 'NonNullType', + type: { kind: 'NamedType', name: { kind: 'Name', value: 'UUID' } } + } + } + ], + selectionSet: { + kind: 'SelectionSet', + selections: [ + { kind: 'Field', name: { kind: 'Name', value: '__typename' } }, + { + kind: 'Field', + name: { kind: 'Name', value: 'deleteFromactivityCollection' }, + arguments: [ + { + kind: 'Argument', + name: { kind: 'Name', value: 'filter' }, + value: { + kind: 'ObjectValue', + fields: [ + { + kind: 'ObjectField', + name: { kind: 'Name', value: 'id' }, + value: { + kind: 'ObjectValue', + fields: [ + { + kind: 'ObjectField', + name: { kind: 'Name', value: 'eq' }, + value: { + kind: 'Variable', + name: { kind: 'Name', value: 'id' } + } + } + ] + } + } + ] + } + } + ], + selectionSet: { + kind: 'SelectionSet', + selections: [ + { kind: 'Field', name: { kind: 'Name', value: '__typename' } }, + { + kind: 'Field', + name: { kind: 'Name', value: 'records' }, + selectionSet: { + kind: 'SelectionSet', + selections: [ + { + kind: 'Field', + name: { kind: 'Name', value: '__typename' } + }, + { kind: 'Field', name: { kind: 'Name', value: 'id' } }, + { + kind: 'Field', + name: { kind: 'Name', value: 'trip_id' } + }, + { kind: 'Field', name: { kind: 'Name', value: 'title' } } + ] + } + } + ] + } + } + ] + } + } + ] +} as unknown as DocumentNode< + DeleteActivityMutation, + DeleteActivityMutationVariables +> +export const UpdateActivityDocument = { + __meta__: { hash: 'd6d6be943e738534556ff6a112b8dea268daf1f6' }, + kind: 'Document', + definitions: [ + { + kind: 'OperationDefinition', + operation: 'mutation', + name: { kind: 'Name', value: 'updateActivity' }, + variableDefinitions: [ + { + kind: 'VariableDefinition', + variable: { kind: 'Variable', name: { kind: 'Name', value: 'id' } }, + type: { + kind: 'NonNullType', + type: { kind: 'NamedType', name: { kind: 'Name', value: 'UUID' } } + } + }, + { + kind: 'VariableDefinition', + variable: { kind: 'Variable', name: { kind: 'Name', value: 'set' } }, + type: { + kind: 'NonNullType', + type: { + kind: 'NamedType', + name: { kind: 'Name', value: 'activityUpdateInput' } + } + } + } + ], + selectionSet: { + kind: 'SelectionSet', + selections: [ + { kind: 'Field', name: { kind: 'Name', value: '__typename' } }, + { + kind: 'Field', + name: { kind: 'Name', value: 'updateactivityCollection' }, + arguments: [ + { + kind: 'Argument', + name: { kind: 'Name', value: 'set' }, + value: { + kind: 'Variable', + name: { kind: 'Name', value: 'set' } + } + }, + { + kind: 'Argument', + name: { kind: 'Name', value: 'filter' }, + value: { + kind: 'ObjectValue', + fields: [ + { + kind: 'ObjectField', + name: { kind: 'Name', value: 'id' }, + value: { + kind: 'ObjectValue', + fields: [ + { + kind: 'ObjectField', + name: { kind: 'Name', value: 'eq' }, + value: { + kind: 'Variable', + name: { kind: 'Name', value: 'id' } + } + } + ] + } + } + ] + } + } + ], + selectionSet: { + kind: 'SelectionSet', + selections: [ + { kind: 'Field', name: { kind: 'Name', value: '__typename' } }, + { + kind: 'Field', + name: { kind: 'Name', value: 'records' }, + selectionSet: { + kind: 'SelectionSet', + selections: [ + { + kind: 'Field', + name: { kind: 'Name', value: '__typename' } + }, + { kind: 'Field', name: { kind: 'Name', value: 'id' } }, + { kind: 'Field', name: { kind: 'Name', value: 'title' } } + ] + } + } + ] + } + } + ] + } + } + ] +} as unknown as DocumentNode< + UpdateActivityMutation, + UpdateActivityMutationVariables +> +export const ActivityCollectionDocument = { + __meta__: { hash: '3e04fac286fc4b6bc6c6d91483ca2b248b25bad6' }, + kind: 'Document', + definitions: [ + { + kind: 'OperationDefinition', + operation: 'query', + name: { kind: 'Name', value: 'activityCollection' }, + variableDefinitions: [ + { + kind: 'VariableDefinition', + variable: { kind: 'Variable', name: { kind: 'Name', value: 'id' } }, + type: { + kind: 'NonNullType', + type: { kind: 'NamedType', name: { kind: 'Name', value: 'UUID' } } + } + } + ], + selectionSet: { + kind: 'SelectionSet', + selections: [ + { kind: 'Field', name: { kind: 'Name', value: '__typename' } }, + { + kind: 'Field', + name: { kind: 'Name', value: 'activityCollection' }, + arguments: [ + { + kind: 'Argument', + name: { kind: 'Name', value: 'filter' }, + value: { + kind: 'ObjectValue', + fields: [ + { + kind: 'ObjectField', + name: { kind: 'Name', value: 'id' }, + value: { + kind: 'ObjectValue', + fields: [ + { + kind: 'ObjectField', + name: { kind: 'Name', value: 'eq' }, + value: { + kind: 'Variable', + name: { kind: 'Name', value: 'id' } + } + } + ] + } + } + ] + } + } + ], + selectionSet: { + kind: 'SelectionSet', + selections: [ + { kind: 'Field', name: { kind: 'Name', value: '__typename' } }, + { + kind: 'Field', + name: { kind: 'Name', value: 'edges' }, + selectionSet: { + kind: 'SelectionSet', + selections: [ + { + kind: 'Field', + name: { kind: 'Name', value: '__typename' } + }, + { + kind: 'Field', + name: { kind: 'Name', value: 'node' }, + selectionSet: { + kind: 'SelectionSet', + selections: [ + { + kind: 'Field', + name: { kind: 'Name', value: '__typename' } + }, + { + kind: 'Field', + name: { kind: 'Name', value: 'id' } + }, + { + kind: 'Field', + name: { kind: 'Name', value: 'trip_id' } + }, + { + kind: 'Field', + name: { kind: 'Name', value: 'title' } + }, + { + kind: 'Field', + name: { kind: 'Name', value: 'time_from' } + }, + { + kind: 'Field', + name: { kind: 'Name', value: 'time_to' } + }, + { + kind: 'Field', + name: { kind: 'Name', value: 'address' } + }, + { + kind: 'Field', + name: { kind: 'Name', value: 'url' } + }, + { + kind: 'Field', + name: { kind: 'Name', value: 'memo' } + }, + { + kind: 'Field', + name: { kind: 'Name', value: 'cost' } }, { kind: 'Field', @@ -1833,7 +2277,72 @@ export const ActivityCollectionDocument = { }, { kind: 'Field', - name: { kind: 'Name', value: 'image_url' } + name: { + kind: 'Name', + value: 'activity_uploaded_filesCollection' + }, + selectionSet: { + kind: 'SelectionSet', + selections: [ + { + kind: 'Field', + name: { kind: 'Name', value: '__typename' } + }, + { + kind: 'Field', + name: { kind: 'Name', value: 'edges' }, + selectionSet: { + kind: 'SelectionSet', + selections: [ + { + kind: 'Field', + name: { + kind: 'Name', + value: '__typename' + } + }, + { + kind: 'Field', + name: { kind: 'Name', value: 'node' }, + selectionSet: { + kind: 'SelectionSet', + selections: [ + { + kind: 'Field', + name: { + kind: 'Name', + value: '__typename' + } + }, + { + kind: 'Field', + name: { + kind: 'Name', + value: 'id' + } + }, + { + kind: 'Field', + name: { + kind: 'Name', + value: 'file_name' + } + }, + { + kind: 'Field', + name: { + kind: 'Name', + value: 'file_url' + } + } + ] + } + } + ] + } + } + ] + } } ] } @@ -1852,91 +2361,120 @@ export const ActivityCollectionDocument = { ActivityCollectionQuery, ActivityCollectionQueryVariables > -export const CreateActivityDocument = { - __meta__: { hash: '22e6378e9a0ec7a9c28a6430981dcfebf7820216' }, +export const DeleteInvitationDocument = { + __meta__: { hash: 'f83929f3ffa8a8ea910e5e66156925ab379aa04d' }, kind: 'Document', definitions: [ { kind: 'OperationDefinition', operation: 'mutation', - name: { kind: 'Name', value: 'createActivity' }, + name: { kind: 'Name', value: 'deleteInvitation' }, variableDefinitions: [ { kind: 'VariableDefinition', - variable: { - kind: 'Variable', - name: { kind: 'Name', value: 'trip_id' } - }, + variable: { kind: 'Variable', name: { kind: 'Name', value: 'id' } }, type: { kind: 'NonNullType', type: { kind: 'NamedType', name: { kind: 'Name', value: 'UUID' } } } - }, + } + ], + selectionSet: { + kind: 'SelectionSet', + selections: [ + { kind: 'Field', name: { kind: 'Name', value: '__typename' } }, + { + kind: 'Field', + name: { kind: 'Name', value: 'deleteFrominvitationsCollection' }, + arguments: [ + { + kind: 'Argument', + name: { kind: 'Name', value: 'filter' }, + value: { + kind: 'ObjectValue', + fields: [ + { + kind: 'ObjectField', + name: { kind: 'Name', value: 'id' }, + value: { + kind: 'ObjectValue', + fields: [ + { + kind: 'ObjectField', + name: { kind: 'Name', value: 'eq' }, + value: { + kind: 'Variable', + name: { kind: 'Name', value: 'id' } + } + } + ] + } + } + ] + } + } + ], + selectionSet: { + kind: 'SelectionSet', + selections: [ + { kind: 'Field', name: { kind: 'Name', value: '__typename' } }, + { + kind: 'Field', + name: { kind: 'Name', value: 'records' }, + selectionSet: { + kind: 'SelectionSet', + selections: [ + { + kind: 'Field', + name: { kind: 'Name', value: '__typename' } + }, + { kind: 'Field', name: { kind: 'Name', value: 'id' } }, + { kind: 'Field', name: { kind: 'Name', value: 'email' } }, + { + kind: 'Field', + name: { kind: 'Name', value: 'permission_level' } + } + ] + } + } + ] + } + } + ] + } + } + ] +} as unknown as DocumentNode< + DeleteInvitationMutation, + DeleteInvitationMutationVariables +> +export const UpdateInvitationDocument = { + __meta__: { hash: '173d22f901d3e0b557eb5eb4ce5ab0adededf9e7' }, + kind: 'Document', + definitions: [ + { + kind: 'OperationDefinition', + operation: 'mutation', + name: { kind: 'Name', value: 'updateInvitation' }, + variableDefinitions: [ { kind: 'VariableDefinition', - variable: { - kind: 'Variable', - name: { kind: 'Name', value: 'title' } - }, + variable: { kind: 'Variable', name: { kind: 'Name', value: 'id' } }, type: { kind: 'NonNullType', - type: { kind: 'NamedType', name: { kind: 'Name', value: 'String' } } + type: { kind: 'NamedType', name: { kind: 'Name', value: 'UUID' } } } }, { kind: 'VariableDefinition', - variable: { - kind: 'Variable', - name: { kind: 'Name', value: 'time_from' } - }, - type: { kind: 'NamedType', name: { kind: 'Name', value: 'Datetime' } } - }, - { - kind: 'VariableDefinition', - variable: { - kind: 'Variable', - name: { kind: 'Name', value: 'time_to' } - }, - type: { kind: 'NamedType', name: { kind: 'Name', value: 'Datetime' } } - }, - { - kind: 'VariableDefinition', - variable: { - kind: 'Variable', - name: { kind: 'Name', value: 'address' } - }, - type: { kind: 'NamedType', name: { kind: 'Name', value: 'String' } } - }, - { - kind: 'VariableDefinition', - variable: { kind: 'Variable', name: { kind: 'Name', value: 'url' } }, - type: { kind: 'NamedType', name: { kind: 'Name', value: 'String' } } - }, - { - kind: 'VariableDefinition', - variable: { kind: 'Variable', name: { kind: 'Name', value: 'memo' } }, - type: { kind: 'NamedType', name: { kind: 'Name', value: 'String' } } - }, - { - kind: 'VariableDefinition', - variable: { kind: 'Variable', name: { kind: 'Name', value: 'cost' } }, - type: { kind: 'NamedType', name: { kind: 'Name', value: 'BigFloat' } } - }, - { - kind: 'VariableDefinition', - variable: { - kind: 'Variable', - name: { kind: 'Name', value: 'cost_unit' } - }, - type: { kind: 'NamedType', name: { kind: 'Name', value: 'String' } } - }, - { - kind: 'VariableDefinition', - variable: { - kind: 'Variable', - name: { kind: 'Name', value: 'image_url' } - }, - type: { kind: 'NamedType', name: { kind: 'Name', value: 'String' } } + variable: { kind: 'Variable', name: { kind: 'Name', value: 'set' } }, + type: { + kind: 'NonNullType', + type: { + kind: 'NamedType', + name: { kind: 'Name', value: 'invitationsUpdateInput' } + } + } } ], selectionSet: { @@ -1945,98 +2483,128 @@ export const CreateActivityDocument = { { kind: 'Field', name: { kind: 'Name', value: '__typename' } }, { kind: 'Field', - name: { kind: 'Name', value: 'insertIntoactivityCollection' }, + name: { kind: 'Name', value: 'updateinvitationsCollection' }, arguments: [ { kind: 'Argument', - name: { kind: 'Name', value: 'objects' }, + name: { kind: 'Name', value: 'set' }, value: { - kind: 'ListValue', - values: [ + kind: 'Variable', + name: { kind: 'Name', value: 'set' } + } + }, + { + kind: 'Argument', + name: { kind: 'Name', value: 'filter' }, + value: { + kind: 'ObjectValue', + fields: [ { - kind: 'ObjectValue', - fields: [ - { - kind: 'ObjectField', - name: { kind: 'Name', value: 'trip_id' }, - value: { - kind: 'Variable', - name: { kind: 'Name', value: 'trip_id' } - } - }, - { - kind: 'ObjectField', - name: { kind: 'Name', value: 'title' }, - value: { - kind: 'Variable', - name: { kind: 'Name', value: 'title' } - } - }, - { - kind: 'ObjectField', - name: { kind: 'Name', value: 'time_from' }, - value: { - kind: 'Variable', - name: { kind: 'Name', value: 'time_from' } - } - }, - { - kind: 'ObjectField', - name: { kind: 'Name', value: 'time_to' }, - value: { - kind: 'Variable', - name: { kind: 'Name', value: 'time_to' } - } - }, - { - kind: 'ObjectField', - name: { kind: 'Name', value: 'address' }, - value: { - kind: 'Variable', - name: { kind: 'Name', value: 'address' } - } - }, - { - kind: 'ObjectField', - name: { kind: 'Name', value: 'url' }, - value: { - kind: 'Variable', - name: { kind: 'Name', value: 'url' } - } - }, - { - kind: 'ObjectField', - name: { kind: 'Name', value: 'memo' }, - value: { - kind: 'Variable', - name: { kind: 'Name', value: 'memo' } - } - }, - { - kind: 'ObjectField', - name: { kind: 'Name', value: 'cost' }, - value: { - kind: 'Variable', - name: { kind: 'Name', value: 'cost' } - } - }, - { - kind: 'ObjectField', - name: { kind: 'Name', value: 'cost_unit' }, - value: { - kind: 'Variable', - name: { kind: 'Name', value: 'cost_unit' } + kind: 'ObjectField', + name: { kind: 'Name', value: 'id' }, + value: { + kind: 'ObjectValue', + fields: [ + { + kind: 'ObjectField', + name: { kind: 'Name', value: 'eq' }, + value: { + kind: 'Variable', + name: { kind: 'Name', value: 'id' } + } } - }, - { - kind: 'ObjectField', - name: { kind: 'Name', value: 'image_url' }, - value: { - kind: 'Variable', - name: { kind: 'Name', value: 'image_url' } + ] + } + } + ] + } + } + ], + selectionSet: { + kind: 'SelectionSet', + selections: [ + { kind: 'Field', name: { kind: 'Name', value: '__typename' } }, + { + kind: 'Field', + name: { kind: 'Name', value: 'records' }, + selectionSet: { + kind: 'SelectionSet', + selections: [ + { + kind: 'Field', + name: { kind: 'Name', value: '__typename' } + }, + { kind: 'Field', name: { kind: 'Name', value: 'id' } }, + { kind: 'Field', name: { kind: 'Name', value: 'email' } }, + { + kind: 'Field', + name: { kind: 'Name', value: 'permission_level' } + } + ] + } + } + ] + } + } + ] + } + } + ] +} as unknown as DocumentNode< + UpdateInvitationMutation, + UpdateInvitationMutationVariables +> +export const TripSharedUsersDocument = { + __meta__: { hash: '16ece6918ea030b3bf8bcf763c1a296e90d6dcf9' }, + kind: 'Document', + definitions: [ + { + kind: 'OperationDefinition', + operation: 'query', + name: { kind: 'Name', value: 'tripSharedUsers' }, + variableDefinitions: [ + { + kind: 'VariableDefinition', + variable: { + kind: 'Variable', + name: { kind: 'Name', value: 'tripId' } + }, + type: { + kind: 'NonNullType', + type: { kind: 'NamedType', name: { kind: 'Name', value: 'UUID' } } + } + } + ], + selectionSet: { + kind: 'SelectionSet', + selections: [ + { kind: 'Field', name: { kind: 'Name', value: '__typename' } }, + { + kind: 'Field', + name: { kind: 'Name', value: 'tripsCollection' }, + arguments: [ + { + kind: 'Argument', + name: { kind: 'Name', value: 'filter' }, + value: { + kind: 'ObjectValue', + fields: [ + { + kind: 'ObjectField', + name: { kind: 'Name', value: 'id' }, + value: { + kind: 'ObjectValue', + fields: [ + { + kind: 'ObjectField', + name: { kind: 'Name', value: 'eq' }, + value: { + kind: 'Variable', + name: { kind: 'Name', value: 'tripId' } + } } - } - ] + ] + } } ] } @@ -2048,7 +2616,7 @@ export const CreateActivityDocument = { { kind: 'Field', name: { kind: 'Name', value: '__typename' } }, { kind: 'Field', - name: { kind: 'Name', value: 'records' }, + name: { kind: 'Name', value: 'edges' }, selectionSet: { kind: 'SelectionSet', selections: [ @@ -2056,8 +2624,169 @@ export const CreateActivityDocument = { kind: 'Field', name: { kind: 'Name', value: '__typename' } }, - { kind: 'Field', name: { kind: 'Name', value: 'id' } }, - { kind: 'Field', name: { kind: 'Name', value: 'title' } } + { + kind: 'Field', + name: { kind: 'Name', value: 'node' }, + selectionSet: { + kind: 'SelectionSet', + selections: [ + { + kind: 'Field', + name: { kind: 'Name', value: '__typename' } + }, + { + kind: 'Field', + name: { kind: 'Name', value: 'id' } + }, + { + kind: 'Field', + name: { kind: 'Name', value: 'title' } + }, + { + kind: 'Field', + name: { kind: 'Name', value: 'users' }, + selectionSet: { + kind: 'SelectionSet', + selections: [ + { + kind: 'Field', + name: { kind: 'Name', value: '__typename' } + }, + { + kind: 'Field', + name: { kind: 'Name', value: 'id' } + }, + { + kind: 'Field', + name: { kind: 'Name', value: 'name' } + }, + { + kind: 'Field', + name: { + kind: 'Name', + value: 'profile_picture_url' + } + }, + { + kind: 'Field', + name: { kind: 'Name', value: 'email' } + } + ] + } + }, + { + kind: 'Field', + name: { + kind: 'Name', + value: 'invitationsCollection' + }, + selectionSet: { + kind: 'SelectionSet', + selections: [ + { + kind: 'Field', + name: { kind: 'Name', value: '__typename' } + }, + { + kind: 'Field', + name: { kind: 'Name', value: 'edges' }, + selectionSet: { + kind: 'SelectionSet', + selections: [ + { + kind: 'Field', + name: { + kind: 'Name', + value: '__typename' + } + }, + { + kind: 'Field', + name: { kind: 'Name', value: 'node' }, + selectionSet: { + kind: 'SelectionSet', + selections: [ + { + kind: 'Field', + name: { + kind: 'Name', + value: '__typename' + } + }, + { + kind: 'Field', + name: { + kind: 'Name', + value: 'id' + } + }, + { + kind: 'Field', + name: { + kind: 'Name', + value: 'permission_level' + } + }, + { + kind: 'Field', + name: { + kind: 'Name', + value: 'users' + }, + selectionSet: { + kind: 'SelectionSet', + selections: [ + { + kind: 'Field', + name: { + kind: 'Name', + value: '__typename' + } + }, + { + kind: 'Field', + name: { + kind: 'Name', + value: 'id' + } + }, + { + kind: 'Field', + name: { + kind: 'Name', + value: 'name' + } + }, + { + kind: 'Field', + name: { + kind: 'Name', + value: 'email' + } + }, + { + kind: 'Field', + name: { + kind: 'Name', + value: + 'profile_picture_url' + } + } + ] + } + } + ] + } + } + ] + } + } + ] + } + } + ] + } + } ] } } @@ -2069,8 +2798,8 @@ export const CreateActivityDocument = { } ] } as unknown as DocumentNode< - CreateActivityMutation, - CreateActivityMutationVariables + TripSharedUsersQuery, + TripSharedUsersQueryVariables > export const CreateTagDocument = { __meta__: { hash: '9ecd6081f83febe06337ebd01345eef596b81cf9' }, @@ -2834,7 +3563,7 @@ export const TagsCollectionDocument = { ] } as unknown as DocumentNode export const TripDetailsDocument = { - __meta__: { hash: '1bc05beaca139a887f8c922c4de4dc6c86706670' }, + __meta__: { hash: 'e40d7c2a09852d29b44908c4c24cbcfa2dbce660' }, kind: 'Document', definitions: [ { @@ -2935,6 +3664,30 @@ export const TripDetailsDocument = { kind: 'Field', name: { kind: 'Name', value: 'cost_unit' } }, + { + kind: 'Field', + name: { kind: 'Name', value: 'users' }, + selectionSet: { + kind: 'SelectionSet', + selections: [ + { + kind: 'Field', + name: { kind: 'Name', value: '__typename' } + }, + { + kind: 'Field', + name: { kind: 'Name', value: 'id' } + }, + { + kind: 'Field', + name: { + kind: 'Name', + value: 'profile_picture_url' + } + } + ] + } + }, { kind: 'Field', name: { @@ -3287,7 +4040,7 @@ export const TripTagsCollectionDocument = { TripTagsCollectionQueryVariables > export const TripsCollectionDocument = { - __meta__: { hash: '3256c7ff43134c13502c53f475e55fa91f55cabb' }, + __meta__: { hash: '848b1879d86d9282d2bb3a3d1016f42dd7e5cc56' }, kind: 'Document', definitions: [ { @@ -3436,6 +4189,34 @@ export const TripsCollectionDocument = { kind: 'Field', name: { kind: 'Name', value: 'created_at' } }, + { + kind: 'Field', + name: { kind: 'Name', value: 'users' }, + selectionSet: { + kind: 'SelectionSet', + selections: [ + { + kind: 'Field', + name: { kind: 'Name', value: '__typename' } + }, + { + kind: 'Field', + name: { kind: 'Name', value: 'id' } + }, + { + kind: 'Field', + name: { kind: 'Name', value: 'name' } + }, + { + kind: 'Field', + name: { + kind: 'Name', + value: 'profile_picture_url' + } + } + ] + } + }, { kind: 'Field', name: { diff --git a/graphql-codegen/generated/persisted-documents.json b/graphql-codegen/generated/persisted-documents.json index 26cadb0..e7ba8fe 100644 --- a/graphql-codegen/generated/persisted-documents.json +++ b/graphql-codegen/generated/persisted-documents.json @@ -1,7 +1,13 @@ { "00c528b2b1c851c06119aedb1fba6b5c885713cf": "query getUser($id: UUID!) { __typename usersCollection(filter: {id: {eq: $id}}) { __typename edges { __typename node { __typename email id name profile_picture_url } } } }", - "5ba311a19d53ac42096cb55d1830aaf08f96fccf": "query activityCollection($id: UUID!) { __typename activityCollection(filter: {id: {eq: $id}}) { __typename edges { __typename node { __typename address cost cost_unit id image_url memo time_from time_to title trip_id url } } } }", - "22e6378e9a0ec7a9c28a6430981dcfebf7820216": "mutation createActivity($address: String, $cost: BigFloat, $cost_unit: String, $image_url: String, $memo: String, $time_from: Datetime, $time_to: Datetime, $title: String!, $trip_id: UUID!, $url: String) { __typename insertIntoactivityCollection( objects: [{trip_id: $trip_id, title: $title, time_from: $time_from, time_to: $time_to, address: $address, url: $url, memo: $memo, cost: $cost, cost_unit: $cost_unit, image_url: $image_url}] ) { __typename records { __typename id title } } }", + "374de4fe4f2de1741f44619ae25c008fee655937": "mutation createActivity($object: activityInsertInput!) { __typename insertIntoactivityCollection(objects: [$object]) { __typename records { __typename id title } } }", + "9b12c83c4bb7cae7ead1221919c3842b1d446e35": "mutation createActivityUploadedFiles($objects: [activity_uploaded_filesInsertInput!]!) { __typename insertIntoactivity_uploaded_filesCollection(objects: $objects) { __typename records { __typename activity_id file_name file_url id } } }", + "f86bef447c736e2937994ec37ca883ee109fa6c5": "mutation DeleteActivity($id: UUID!) { __typename deleteFromactivityCollection(filter: {id: {eq: $id}}) { __typename records { __typename id title trip_id } } }", + "d6d6be943e738534556ff6a112b8dea268daf1f6": "mutation updateActivity($id: UUID!, $set: activityUpdateInput!) { __typename updateactivityCollection(set: $set, filter: {id: {eq: $id}}) { __typename records { __typename id title } } }", + "3e04fac286fc4b6bc6c6d91483ca2b248b25bad6": "query activityCollection($id: UUID!) { __typename activityCollection(filter: {id: {eq: $id}}) { __typename edges { __typename node { __typename activity_uploaded_filesCollection { __typename edges { __typename node { __typename file_name file_url id } } } address cost cost_unit id memo time_from time_to title trip_id url } } } }", + "f83929f3ffa8a8ea910e5e66156925ab379aa04d": "mutation deleteInvitation($id: UUID!) { __typename deleteFrominvitationsCollection(filter: {id: {eq: $id}}) { __typename records { __typename email id permission_level } } }", + "173d22f901d3e0b557eb5eb4ce5ab0adededf9e7": "mutation updateInvitation($id: UUID!, $set: invitationsUpdateInput!) { __typename updateinvitationsCollection(set: $set, filter: {id: {eq: $id}}) { __typename records { __typename email id permission_level } } }", + "16ece6918ea030b3bf8bcf763c1a296e90d6dcf9": "query tripSharedUsers($tripId: UUID!) { __typename tripsCollection(filter: {id: {eq: $tripId}}) { __typename edges { __typename node { __typename id invitationsCollection { __typename edges { __typename node { __typename id permission_level users { __typename email id name profile_picture_url } } } } title users { __typename email id name profile_picture_url } } } } }", "9ecd6081f83febe06337ebd01345eef596b81cf9": "mutation createTag($name: String!, $userId: UUID!) { __typename insertIntotagsCollection(objects: [{name: $name, user_id: $userId}]) { __typename records { __typename id name } } }", "68140ac8465fd7c6f5bab39db9eec02dab9501ef": "mutation createTrip($object: tripsInsertInput!) { __typename insertIntotripsCollection(objects: [$object]) { __typename records { __typename id title } } }", "b86b0c68b8ee2697ff1b539e5df92575cedb30f0": "mutation createTripTag($tagId: UUID!, $tripId: UUID!) { __typename insertIntotrip_tagsCollection(objects: [{trip_id: $tripId, tag_id: $tagId}]) { __typename records { __typename id tag_id trip_id } } }", @@ -10,7 +16,7 @@ "1a4d048db574dedfebd859dc737e16a42021f3ff": "mutation deleteTripTag($id: UUID!) { __typename deleteFromtrip_tagsCollection(filter: {id: {eq: $id}}) { __typename records { __typename id } } }", "7b9783d44e5c70098239e977664434de3eae6204": "mutation updateTrip($id: UUID!, $set: tripsUpdateInput!) { __typename updatetripsCollection(set: $set, filter: {id: {eq: $id}}) { __typename records { __typename id title } } }", "994a2e7e0694c279cbfeff6c8696cbbe6a0c687c": "query tagsCollection($userId: UUID!) { __typename tagsCollection( filter: {user_id: {eq: $userId}} orderBy: {created_at: AscNullsLast} ) { __typename edges { __typename node { __typename id name } } } }", - "1bc05beaca139a887f8c922c4de4dc6c86706670": "query tripDetails($id: UUID) { __typename tripsCollection(filter: {id: {eq: $id}}) { __typename edges { __typename node { __typename activityCollection { __typename edges { __typename node { __typename address id time_from time_to title } } } cost cost_unit date_from date_to id image_url invitationsCollection { __typename edges { __typename node { __typename users { __typename id profile_picture_url } } } } title trip_tagsCollection { __typename edges { __typename node { __typename tags { __typename id name } } } } } } } }", + "e40d7c2a09852d29b44908c4c24cbcfa2dbce660": "query tripDetails($id: UUID) { __typename tripsCollection(filter: {id: {eq: $id}}) { __typename edges { __typename node { __typename activityCollection { __typename edges { __typename node { __typename address id time_from time_to title } } } cost cost_unit date_from date_to id image_url invitationsCollection { __typename edges { __typename node { __typename users { __typename id profile_picture_url } } } } title trip_tagsCollection { __typename edges { __typename node { __typename tags { __typename id name } } } } users { __typename id profile_picture_url } } } } }", "f4142b2a2f4ab96ce0e69488851fdff976486652": "query tripTagsCollection($filter: trip_tagsFilter) { __typename trip_tagsCollection(filter: $filter) { __typename edges { __typename node { __typename id tag_id trip_id } } } }", - "3256c7ff43134c13502c53f475e55fa91f55cabb": "query tripsCollection($after: Cursor, $filter: tripsFilter, $first: Int!, $orderBy: [tripsOrderBy!]) { __typename tripsCollection( filter: $filter first: $first after: $after orderBy: $orderBy ) { __typename edges { __typename node { __typename activityCollection { __typename edges { __typename node { __typename id } } } created_at date_from date_to id id image_url invitationsCollection { __typename edges { __typename node { __typename users { __typename id profile_picture_url } } } } title } } pageInfo { __typename endCursor hasNextPage hasPreviousPage startCursor } } }" + "848b1879d86d9282d2bb3a3d1016f42dd7e5cc56": "query tripsCollection($after: Cursor, $filter: tripsFilter, $first: Int!, $orderBy: [tripsOrderBy!]) { __typename tripsCollection( filter: $filter first: $first after: $after orderBy: $orderBy ) { __typename edges { __typename node { __typename activityCollection { __typename edges { __typename node { __typename id } } } created_at date_from date_to id id image_url invitationsCollection { __typename edges { __typename node { __typename users { __typename id profile_picture_url } } } } title users { __typename id name profile_picture_url } } } pageInfo { __typename endCursor hasNextPage hasPreviousPage startCursor } } }" } diff --git a/package.json b/package.json index 24a5dfe..643ecb1 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,6 @@ "react-datepicker": "^5.0.0", "react-datetime-picker": "^5.6.0", "react-dom": "^18", - "react-dropzone": "^14.2.3", "react-slick": "^0.29.0", "slick-carousel": "^1.8.1" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f6dca88..e643e88 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -62,9 +62,6 @@ dependencies: react-dom: specifier: ^18 version: 18.2.0(react@18.2.0) - react-dropzone: - specifier: ^14.2.3 - version: 14.2.3(react@18.2.0) react-slick: specifier: ^0.29.0 version: 0.29.0(react-dom@18.2.0)(react@18.2.0) @@ -8436,11 +8433,6 @@ packages: hasBin: true dev: true - /attr-accept@2.2.2: - resolution: {integrity: sha512-7prDjvt9HmqiZ0cl5CRjtS84sEyhsHP2coDkaZKRKVfCDo9s7iw7ChVmar78Gu9pC4SoR/28wFu/G5JJhTnqEg==} - engines: {node: '>=4'} - dev: false - /auto-bind@4.0.0: resolution: {integrity: sha512-Hdw8qdNiqdJ8LqT0iK0sVzkFbzg6fhnQqqfWhBDxcHZvU75+B+ayzTy8x+k5Ix0Y92XOhOUlx74ps+bA6BeYMQ==} engines: {node: '>=8'} @@ -11140,13 +11132,6 @@ packages: flat-cache: 3.1.1 dev: true - /file-selector@0.6.0: - resolution: {integrity: sha512-QlZ5yJC0VxHxQQsQhXvBaC7VRJ2uaxTf+Tfpu4Z/OcVQJVpZO+DGU0rkoVW5ce2SccxugvpBJoMvUs59iILYdw==} - engines: {node: '>= 12'} - dependencies: - tslib: 2.6.2 - dev: false - /file-system-cache@1.1.0: resolution: {integrity: sha512-IzF5MBq+5CR0jXx5RxPe4BICl/oEhBSXKaL9fLhAXrIfIUS77Hr4vzrYyqYMHN6uTt+BOqi3fDCTjjEBCjERKw==} dependencies: @@ -15243,18 +15228,6 @@ packages: react: 18.2.0 scheduler: 0.23.0 - /react-dropzone@14.2.3(react@18.2.0): - resolution: {integrity: sha512-O3om8I+PkFKbxCukfIR3QAGftYXDZfOE2N1mr/7qebQJHs7U+/RSL/9xomJNpRg9kM5h9soQSdf0Gc7OHF5Fug==} - engines: {node: '>= 10.13'} - peerDependencies: - react: '>= 16.8 || 18.0.0' - dependencies: - attr-accept: 2.2.2 - file-selector: 0.6.0 - prop-types: 15.8.1 - react: 18.2.0 - dev: false - /react-element-to-jsx-string@15.0.0(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-UDg4lXB6BzlobN60P8fHWVPX3Kyw8ORrTeBtClmIlGdkOOE+GYQSFvmEU5iLLpwp/6v42DINwNcwOhOLfQ//FQ==} peerDependencies: