From 0cbf271fd1a6464edcba7c28bc3f64c474bffc4f Mon Sep 17 00:00:00 2001 From: Kana Taguchi Date: Mon, 29 Jan 2024 19:56:25 -0800 Subject: [PATCH] Add data logic related tags --- app/components/date/custom-date-picker.tsx | 106 +++++ app/components/date/index.ts | 1 + app/components/input/index.ts | 2 +- app/components/input/input-form.tsx | 14 +- .../{input-icon.tsx => input-icon-button.tsx} | 4 +- ...orm.stories.tsx => input-form.stories.tsx} | 0 ...ries.tsx => input-icon-button.stories.tsx} | 10 +- app/libs/utils/date.ts | 26 ++ app/libs/utils/index.ts | 4 +- app/trip/[id]/edit/page.tsx | 109 ++++-- app/trip/components/tag-form-modal.tsx | 5 +- app/trip/components/trip-form.tsx | 205 ++++++---- app/trip/components/trip-search.tsx | 4 +- app/trip/graphql/mutation/createTrip.graphql | 4 +- .../graphql/mutation/createTripTag.graphql | 12 + .../graphql/mutation/deleteTripTag.graphql | 8 + .../graphql/query/tripTagsCollection.graphql | 11 + app/trip/schema.ts | 5 +- graphql-codegen/generated/api.ts | 277 ++++++++++++- graphql-codegen/generated/gql.ts | 30 +- graphql-codegen/generated/graphql.ts | 363 +++++++++++++++++- .../generated/persisted-documents.json | 5 +- package.json | 3 + pnpm-lock.yaml | 125 ++++++ 24 files changed, 1186 insertions(+), 147 deletions(-) create mode 100644 app/components/date/custom-date-picker.tsx create mode 100644 app/components/date/index.ts rename app/components/input/{input-icon.tsx => input-icon-button.tsx} (90%) rename app/components/input/stories/{inputForm.stories.tsx => input-form.stories.tsx} (100%) rename app/components/input/stories/{inputIcon.stories.tsx => input-icon-button.stories.tsx} (53%) create mode 100644 app/trip/graphql/mutation/createTripTag.graphql create mode 100644 app/trip/graphql/mutation/deleteTripTag.graphql create mode 100644 app/trip/graphql/query/tripTagsCollection.graphql diff --git a/app/components/date/custom-date-picker.tsx b/app/components/date/custom-date-picker.tsx new file mode 100644 index 0000000..8cbde6d --- /dev/null +++ b/app/components/date/custom-date-picker.tsx @@ -0,0 +1,106 @@ +import DatePicker from 'react-datepicker' +import { Box, useColorMode } from '@chakra-ui/react' +import { FiCalendar } from 'react-icons/fi' +import 'react-datepicker/dist/react-datepicker.css' +import { InputForm } from '@/components/input' + +type DatePickerProps = { + selectedDate: Date | null + onChange: (date: Date) => void + placeholderText: string + dateFormat?: string | string[] | undefined +} + +export const CustomDatePicker = ({ + selectedDate, + onChange, + placeholderText, + dateFormat +}: DatePickerProps) => { + const { colorMode } = useColorMode() + + const datePickerStyles = { + '.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' + }, + '.react-datepicker__month-container': { + backgroundColor: colorMode === 'dark' ? 'gray.700' : 'white', + width: { base: '100%', md: '400px' } + }, + '.react-datepicker__triangle': { + display: 'none' + }, + '.react-datepicker__header': { + 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: '32px' + }, + '.react-datepicker__navigation--next': { + right: '32px' + }, + '.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: '2.4rem', md: '2.8rem' }, + lineHeight: { base: '2.4rem', md: '2.8rem' }, + color: colorMode === 'dark' ? 'gray.300' : 'black' + }, + '.react-datepicker__day': { + width: { base: '2.4rem', 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' + } + } + + return ( + + } + /> + + ) +} diff --git a/app/components/date/index.ts b/app/components/date/index.ts new file mode 100644 index 0000000..6ec423b --- /dev/null +++ b/app/components/date/index.ts @@ -0,0 +1 @@ +export { CustomDatePicker } from './custom-date-picker' diff --git a/app/components/input/index.ts b/app/components/input/index.ts index d4f1b9c..3da76d4 100644 --- a/app/components/input/index.ts +++ b/app/components/input/index.ts @@ -1,3 +1,3 @@ export { InputForm } from './input-form' -export { InputIcon } from './input-icon' +export { InputIconButton } from './input-icon-button' export { TextareaForm } from './textarea-form' diff --git a/app/components/input/input-form.tsx b/app/components/input/input-form.tsx index 50923cb..237044f 100644 --- a/app/components/input/input-form.tsx +++ b/app/components/input/input-form.tsx @@ -1,13 +1,18 @@ +import { IconType } from 'react-icons' import { Input as ChakraFormInput, InputProps as ChakraInputProps, InputGroup, + InputRightElement, forwardRef, useColorModeValue } from '@chakra-ui/react' -export const InputForm = forwardRef( - (props: ChakraInputProps, ref: React.Ref) => { +type InputFormProps = { + rightIcon?: IconType +} +export const InputForm = forwardRef( + ({ rightIcon: RightIcon, ...props }, ref) => { const bgColor = useColorModeValue('white', 'gray.700') const borderColor = useColorModeValue('gray.300', 'gray.500') const placeholdercolor = useColorModeValue('gray.400', 'gray.600') @@ -24,6 +29,11 @@ export const InputForm = forwardRef( color: placeholdercolor }} /> + {RightIcon && ( + + + + )} ) } diff --git a/app/components/input/input-icon.tsx b/app/components/input/input-icon-button.tsx similarity index 90% rename from app/components/input/input-icon.tsx rename to app/components/input/input-icon-button.tsx index 9e23325..02316bb 100644 --- a/app/components/input/input-icon.tsx +++ b/app/components/input/input-icon-button.tsx @@ -9,13 +9,13 @@ import { useColorModeValue } from '@chakra-ui/react' -type InputIconProps = { +type InputIconButtonProps = { ariaLabel: string icon: IconType onClick?: () => void } -export const InputIcon = forwardRef( +export const InputIconButton = forwardRef( ({ ariaLabel, icon: Icon, onClick, ...props }, ref) => { const bgColor = useColorModeValue('white', 'gray.700') const borderColor = useColorModeValue('primary.700', 'gray.500') diff --git a/app/components/input/stories/inputForm.stories.tsx b/app/components/input/stories/input-form.stories.tsx similarity index 100% rename from app/components/input/stories/inputForm.stories.tsx rename to app/components/input/stories/input-form.stories.tsx diff --git a/app/components/input/stories/inputIcon.stories.tsx b/app/components/input/stories/input-icon-button.stories.tsx similarity index 53% rename from app/components/input/stories/inputIcon.stories.tsx rename to app/components/input/stories/input-icon-button.stories.tsx index 59ca0e6..a2a6456 100644 --- a/app/components/input/stories/inputIcon.stories.tsx +++ b/app/components/input/stories/input-icon-button.stories.tsx @@ -1,13 +1,13 @@ import { Meta, StoryObj } from '@storybook/react' import { FiSearch } from 'react-icons/fi' -import { InputIcon } from '@/components/input' +import { InputIconButton } from '@/components/input' -const meta: Meta = { - title: 'Input Icon', - component: InputIcon +const meta: Meta = { + title: 'Input Icon Button', + component: InputIconButton } export default meta -type Story = StoryObj +type Story = StoryObj export const Default: Story = { args: { diff --git a/app/libs/utils/date.ts b/app/libs/utils/date.ts index edd625a..4779a4d 100644 --- a/app/libs/utils/date.ts +++ b/app/libs/utils/date.ts @@ -1,3 +1,7 @@ +import { zonedTimeToUtc, toDate, utcToZonedTime, format } from 'date-fns-tz' + +const TIMEZONE = 'Asia/Tokyo' + /** * @param date - ISO date string e.g. '2023-01-01' * @param type - 'dayMonthYear' | 'dayMonth' @@ -54,3 +58,25 @@ export const formatToDateTime = (date: string | null | undefined) => { return `${monthDay} ${hours}:${minutes}` } + +/** + * + * @param isoString - ISO date string + * @returns - Date Object ex. Mon Jan 01 2024 00:00:00 GMT-0800 (Pacific Standard Time) + */ +export const getDateObj = (isoString: string) => { + const parsedDate = toDate(isoString, { timeZone: TIMEZONE }) + const dateObj = utcToZonedTime(parsedDate, TIMEZONE) + return dateObj +} + +/** + * @param date - Date Object + * @returns - ISO date string with Tokyo timezone ex.2024-01-01T12:00:00+09:00 + */ +export const formatToISODate = (date: Date) => { + const isoString = format(date, "yyyy-MM-dd'T'HH:mm:ssXXX", { + timeZone: TIMEZONE + }) + return isoString +} diff --git a/app/libs/utils/index.ts b/app/libs/utils/index.ts index eb4ca56..4d3aec5 100644 --- a/app/libs/utils/index.ts +++ b/app/libs/utils/index.ts @@ -2,5 +2,7 @@ export { formatDateToSlash, extractTimeFromDate, formatDbTimeToDate, - formatToDateTime + formatToDateTime, + getDateObj, + formatToISODate } from './date' diff --git a/app/trip/[id]/edit/page.tsx b/app/trip/[id]/edit/page.tsx index 6f11739..2c40bfb 100644 --- a/app/trip/[id]/edit/page.tsx +++ b/app/trip/[id]/edit/page.tsx @@ -6,7 +6,11 @@ import { Loading } from '@/components/loading' import { Header, Footer } from '@/components/navigation' import { useUserId } from '@/providers/session-provider' import { TripForm } from '../../components' -import { useTagsCollectionQuery, useTripDetailsQuery } from '@generated/api' +import { + useTagsCollectionQuery, + useTripDetailsQuery, + useTripTagsCollectionQuery +} from '@generated/api' export default function TripEditPage({ params }: { params: { id: string } }) { const bg = useColorModeValue('white', 'gray.800') @@ -14,12 +18,24 @@ export default function TripEditPage({ params }: { params: { id: string } }) { const userId = useUserId() - const { data: tripData, loading: tripLoading } = useTripDetailsQuery({ + const { + data: tripData, + loading: tripLoading, + refetch: tripRefetch, + networkStatus: tripNetWorkStatus + } = useTripDetailsQuery({ variables: { id: params.id - } + }, + notifyOnNetworkStatusChange: true }) + const tripDataCollection = tripData?.tripsCollection?.edges[0]?.node + const tripDetailsRefetch = () => { + tripRefetch() + } + const tripDetailsRefetchLoading = tripNetWorkStatus === NetworkStatus.refetch + const { data: tagsData, loading: tagsLoading, @@ -30,17 +46,39 @@ export default function TripEditPage({ params }: { params: { id: string } }) { notifyOnNetworkStatusChange: true }) - if ((!tripData && !tripLoading) || (!tagsData && !tagsLoading)) - throw new Error('No trip data found') - - const tripDataCollection = tripData?.tripsCollection?.edges[0]?.node - const tagsCollectionRefetch = () => { tagsRefetch() } - const tagsRefetchLoading = tagsNetWorkStatus === NetworkStatus.refetch + const { + data: tripTagsData, + refetch: tripTagsRefetch, + networkStatus: tripTagsNetWorkStatus + } = useTripTagsCollectionQuery({ + variables: { + filter: { + trip_id: { eq: params.id } + } + }, + notifyOnNetworkStatusChange: true + }) + + const tripsTagsDataArray = tripTagsData?.trip_tagsCollection?.edges.map( + (tag) => ({ + id: tag.node.id, + tag_id: tag.node.tag_id || '', + trip_id: tag.node.trip_id || '' + }) + ) + const tripTagsCollectionRefetch = () => { + tripTagsRefetch() + } + const tripTagsRefetchLoading = tripTagsNetWorkStatus === NetworkStatus.refetch + + if ((!tripData && !tripLoading) || (!tagsData && !tagsLoading)) + throw new Error('No trip data found') + console.log('tripDataCollection', tripDataCollection) console.log('tagsData', tagsData) @@ -57,31 +95,40 @@ export default function TripEditPage({ params }: { params: { id: string } }) { Edit Trip - {!tripDataCollection || tripLoading ? ( + {!tripDataCollection || tripLoading || !tripsTagsDataArray ? ( ) : ( ({ - id: tag.node.id, - name: tag.node.name - })) || [] - } - checkedTags={ - tripDataCollection.trip_tagsCollection?.edges.map((tag) => ({ - id: tag.node.tags?.id || '', - name: tag.node.tags?.name || '' - })) || [] - } - cost={tripDataCollection.cost} - costUnit={tripDataCollection.cost_unit} - tagsCollectionRefetch={tagsCollectionRefetch} - tagsRefetchLoading={tagsRefetchLoading} + tripDetails={{ + id: tripDataCollection.id, + image: tripDataCollection.image_storage_object_id, + title: tripDataCollection.title, + dateFrom: tripDataCollection.date_from, + dateTo: tripDataCollection.date_to, + cost: tripDataCollection.cost, + costUnit: tripDataCollection.cost_unit, + refetch: tripDetailsRefetch, + refetchLoading: tripDetailsRefetchLoading + }} + tags={{ + data: + tagsData?.tagsCollection?.edges.map((tag) => ({ + id: tag.node.id, + name: tag.node.name + })) || [], + refetch: tagsCollectionRefetch, + refetchLoading: tagsRefetchLoading + }} + tripTags={{ + data: + tripTagsData?.trip_tagsCollection?.edges.map((tripTag) => ({ + id: tripTag.node.id, + tag_id: tripTag.node.tag_id || '', + trip_id: tripTag.node.trip_id || '' + })) || [], + refetch: tripTagsCollectionRefetch, + refetchLoading: tripTagsRefetchLoading + }} /> )} diff --git a/app/trip/components/tag-form-modal.tsx b/app/trip/components/tag-form-modal.tsx index 2f05244..6e0bd5d 100644 --- a/app/trip/components/tag-form-modal.tsx +++ b/app/trip/components/tag-form-modal.tsx @@ -17,7 +17,7 @@ import { useToast } from '@chakra-ui/react' import { FiPlusCircle, FiX } from 'react-icons/fi' -import { InputIcon } from '@/components/input' +import { InputIconButton } from '@/components/input' import { Loading } from '@/components/loading' import { useUserId } from '@/providers/session-provider' import { TagSchema, tagSchemaResolver } from '../schema' @@ -54,6 +54,7 @@ export const TagFormModal = ({ const addTag = async (input: TagSchema) => { try { + await createTagMutation({ variables: { name: input.name, @@ -155,7 +156,7 @@ export const TagFormModal = ({ - void - tagsRefetchLoading: boolean + tripDetails: { + id: string + image: string | null | undefined + title: string + dateFrom: string + dateTo: string | null | undefined + cost: number | null | undefined + costUnit: string | null | undefined + refetch: () => void + refetchLoading: boolean + } + tags: { + data: { id: string; name: string }[] + refetch: () => void + refetchLoading: boolean + } + tripTags: { + data: { id: string; tag_id: string; trip_id: string }[] + refetch: () => void + refetchLoading: boolean + } } -export const TripForm = ({ - id, - image, - title, - dateFrom, - dateTo, - allTags, - checkedTags, - cost, - costUnit, - tagsCollectionRefetch, - tagsRefetchLoading -}: TripFormProps) => { +export const TripForm = ({ tripDetails, tags, tripTags }: TripFormProps) => { const imageSrc = useColorModeValue( '/images/no_image_light.jpg', '/images/no_image_dark.jpg' ) const { isOpen, onOpen, onClose } = useDisclosure() + const toast = useToast() + + console.log('tripTagsData', tripTags.data) + + const [createTripTagMutation, { loading: isTripTagCreating }] = + useCreateTripTagMutation() + const [deleteTripTagMutation, { loading: isTripTagDeleting }] = + useDeleteTripTagMutation() const { register, @@ -60,24 +72,67 @@ export const TripForm = ({ formState: { errors } } = useForm({ defaultValues: { - title: title, - date_from: dateFrom, - date_to: dateTo, - image_storage_object_id: image, - checkedTags: checkedTags.map((tag) => tag.id), - cost: cost ? cost.toString() : '', - cost_unit: costUnit + title: tripDetails.title, + date_from: getDateObj(tripDetails.dateFrom), + date_to: tripDetails.dateTo ? getDateObj(tripDetails.dateTo) : null, + image_storage_object_id: tripDetails.image, + cost: tripDetails.cost ? tripDetails.cost.toString() : '', + cost_unit: tripDetails.costUnit }, resolver: tripSchemaResolver }) console.log('errors', errors) + const tagClickHandler = async (selectedTagId: string) => { + try { + const isTagIdAlreadyExists = tripTags.data.find( + (tripTag) => tripTag.tag_id === selectedTagId + ) + + if (isTagIdAlreadyExists) { + await deleteTripTagMutation({ + variables: { + id: isTagIdAlreadyExists.id + } + }) + tripTags.refetch() + return + } + + if (!isTagIdAlreadyExists) { + await createTripTagMutation({ + variables: { + tripId: tripDetails.id, + tagId: selectedTagId + } + }) + tripTags.refetch() + } + } catch (error) { + console.error(error) + toast({ + title: "We're sorry, but you failed to update a tag", + description: + error instanceof Error ? error.message : 'Please try again later.', + status: 'error', + duration: 5000, + isClosable: true, + position: 'top' + }) + } + } + const updateTrip = async (data: TripSchema) => { console.log('submit!', { - id, + tripId: tripDetails.id, data }) + + if (data.date_to) { + const dateTo = formatToISODate(data.date_to) + console.log('dateTo', dateTo) + } } return ( @@ -99,18 +154,35 @@ export const TripForm = ({ Date From - console.log('onChange')} - value={null} + ( + + )} /> {errors?.date_from?.message} Date To - console.log('onChange')} - value={null} + + ( + + )} /> {errors?.date_to?.message} @@ -118,7 +190,7 @@ export const TripForm = ({ Image - + Select Image @@ -126,37 +198,36 @@ export const TripForm = ({ - + Tag - ( - - - {tagsRefetchLoading ? ( - - ) : ( - <> - {allTags.map((tag) => ( - - {tag.name} - - ))} - - )} - - - )} - /> - {errors?.checkedTags?.message} + + tag.tag_id)}> + + {tags.refetchLoading ? ( + + ) : ( + <> + {tags.data.map((tag) => ( + tagClickHandler(tag.id)} + > + {tag.name} + + ))} + + )} + + Manage Tags - + @@ -190,8 +261,8 @@ export const TripForm = ({ ) diff --git a/app/trip/components/trip-search.tsx b/app/trip/components/trip-search.tsx index b40241f..a6fc3b7 100644 --- a/app/trip/components/trip-search.tsx +++ b/app/trip/components/trip-search.tsx @@ -3,7 +3,7 @@ import { useRef, FormEvent, KeyboardEvent } from 'react' import { Box } from '@chakra-ui/react' import { useRouter } from 'next/navigation' import { FiSearch } from 'react-icons/fi' -import { InputIcon } from '@/components/input' +import { InputIconButton } from '@/components/input' export const TripSearch = () => { const router = useRouter() @@ -38,7 +38,7 @@ export const TripSearch = () => { return ( - cost_unit?: Maybe created_at: Scalars['Datetime']['output'] - date_from: Scalars['Date']['output'] - date_to?: Maybe + date_from: Scalars['Datetime']['output'] + date_to?: Maybe description?: Maybe id: Scalars['UUID']['output'] image_storage_object_id?: Maybe @@ -972,8 +972,8 @@ export type TripsFilter = { cost?: InputMaybe cost_unit?: InputMaybe created_at?: InputMaybe - date_from?: InputMaybe - date_to?: InputMaybe + date_from?: InputMaybe + date_to?: InputMaybe description?: InputMaybe id?: InputMaybe image_storage_object_id?: InputMaybe @@ -986,8 +986,8 @@ export type TripsInsertInput = { cost?: InputMaybe cost_unit?: InputMaybe created_at?: InputMaybe - date_from?: InputMaybe - date_to?: InputMaybe + date_from?: InputMaybe + date_to?: InputMaybe description?: InputMaybe id?: InputMaybe image_storage_object_id?: InputMaybe @@ -1020,8 +1020,8 @@ export type TripsUpdateInput = { cost?: InputMaybe cost_unit?: InputMaybe created_at?: InputMaybe - date_from?: InputMaybe - date_to?: InputMaybe + date_from?: InputMaybe + date_to?: InputMaybe description?: InputMaybe id?: InputMaybe image_storage_object_id?: InputMaybe @@ -1206,8 +1206,8 @@ export type CreateTagMutation = { export type CreateTripMutationVariables = Exact<{ user_id: Scalars['UUID']['input'] title: Scalars['String']['input'] - date_from?: InputMaybe - date_to?: InputMaybe + date_from: Scalars['Datetime']['input'] + date_to?: InputMaybe }> export type CreateTripMutation = { @@ -1218,6 +1218,24 @@ export type CreateTripMutation = { } | null } +export type CreateTripTagMutationVariables = Exact<{ + tripId: Scalars['UUID']['input'] + tagId: Scalars['UUID']['input'] +}> + +export type CreateTripTagMutation = { + __typename: 'Mutation' + insertIntotrip_tagsCollection?: { + __typename: 'trip_tagsInsertResponse' + records: Array<{ + __typename: 'trip_tags' + id: string + tag_id?: string | null + trip_id?: string | null + }> + } | null +} + export type DeleteTagMutationVariables = Exact<{ id: Scalars['UUID']['input'] }> @@ -1230,6 +1248,18 @@ export type DeleteTagMutation = { } } +export type DeleteTripTagMutationVariables = Exact<{ + id: Scalars['UUID']['input'] +}> + +export type DeleteTripTagMutation = { + __typename: 'Mutation' + deleteFromtrip_tagsCollection: { + __typename: 'trip_tagsDeleteResponse' + records: Array<{ __typename: 'trip_tags'; id: string }> + } +} + export type TagsCollectionQueryVariables = Exact<{ userId: Scalars['UUID']['input'] }> @@ -1307,6 +1337,26 @@ export type TripDetailsQuery = { } | null } +export type TripTagsCollectionQueryVariables = Exact<{ + filter?: InputMaybe +}> + +export type TripTagsCollectionQuery = { + __typename: 'Query' + trip_tagsCollection?: { + __typename: 'trip_tagsConnection' + edges: Array<{ + __typename: 'trip_tagsEdge' + node: { + __typename: 'trip_tags' + id: string + trip_id?: string | null + tag_id?: string | null + } + }> + } | null +} + export type TripsCollectionQueryVariables = Exact<{ filter?: InputMaybe orderBy?: InputMaybe | TripsOrderBy> @@ -1593,8 +1643,8 @@ export const CreateTripDocument = gql` mutation createTrip( $user_id: UUID! $title: String! - $date_from: Date - $date_to: Date + $date_from: Datetime! + $date_to: Datetime ) { __typename insertIntotripsCollection( @@ -1661,6 +1711,66 @@ export type CreateTripMutationOptions = Apollo.BaseMutationOptions< CreateTripMutation, CreateTripMutationVariables > +export const CreateTripTagDocument = gql` + mutation createTripTag($tripId: UUID!, $tagId: UUID!) { + __typename + insertIntotrip_tagsCollection( + objects: [{ trip_id: $tripId, tag_id: $tagId }] + ) { + __typename + records { + __typename + id + tag_id + trip_id + } + } + } +` +export type CreateTripTagMutationFn = Apollo.MutationFunction< + CreateTripTagMutation, + CreateTripTagMutationVariables +> + +/** + * __useCreateTripTagMutation__ + * + * To run a mutation, you first call `useCreateTripTagMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useCreateTripTagMutation` 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 [createTripTagMutation, { data, loading, error }] = useCreateTripTagMutation({ + * variables: { + * tripId: // value for 'tripId' + * tagId: // value for 'tagId' + * }, + * }); + */ +export function useCreateTripTagMutation( + baseOptions?: Apollo.MutationHookOptions< + CreateTripTagMutation, + CreateTripTagMutationVariables + > +) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation< + CreateTripTagMutation, + CreateTripTagMutationVariables + >(CreateTripTagDocument, options) +} +export type CreateTripTagMutationHookResult = ReturnType< + typeof useCreateTripTagMutation +> +export type CreateTripTagMutationResult = + Apollo.MutationResult +export type CreateTripTagMutationOptions = Apollo.BaseMutationOptions< + CreateTripTagMutation, + CreateTripTagMutationVariables +> export const DeleteTagDocument = gql` mutation deleteTag($id: UUID!) { __typename @@ -1716,6 +1826,61 @@ export type DeleteTagMutationOptions = Apollo.BaseMutationOptions< DeleteTagMutation, DeleteTagMutationVariables > +export const DeleteTripTagDocument = gql` + mutation deleteTripTag($id: UUID!) { + __typename + deleteFromtrip_tagsCollection(filter: { id: { eq: $id } }) { + __typename + records { + __typename + id + } + } + } +` +export type DeleteTripTagMutationFn = Apollo.MutationFunction< + DeleteTripTagMutation, + DeleteTripTagMutationVariables +> + +/** + * __useDeleteTripTagMutation__ + * + * To run a mutation, you first call `useDeleteTripTagMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useDeleteTripTagMutation` 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 [deleteTripTagMutation, { data, loading, error }] = useDeleteTripTagMutation({ + * variables: { + * id: // value for 'id' + * }, + * }); + */ +export function useDeleteTripTagMutation( + baseOptions?: Apollo.MutationHookOptions< + DeleteTripTagMutation, + DeleteTripTagMutationVariables + > +) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation< + DeleteTripTagMutation, + DeleteTripTagMutationVariables + >(DeleteTripTagDocument, options) +} +export type DeleteTripTagMutationHookResult = ReturnType< + typeof useDeleteTripTagMutation +> +export type DeleteTripTagMutationResult = + Apollo.MutationResult +export type DeleteTripTagMutationOptions = Apollo.BaseMutationOptions< + DeleteTripTagMutation, + DeleteTripTagMutationVariables +> export const TagsCollectionDocument = gql` query tagsCollection($userId: UUID!) { __typename @@ -1936,6 +2101,94 @@ export type TripDetailsQueryResult = Apollo.QueryResult< export function refetchTripDetailsQuery(variables: TripDetailsQueryVariables) { return { query: TripDetailsDocument, variables: variables } } +export const TripTagsCollectionDocument = gql` + query tripTagsCollection($filter: trip_tagsFilter) { + __typename + trip_tagsCollection(filter: $filter) { + __typename + edges { + __typename + node { + __typename + id + trip_id + tag_id + } + } + } + } +` + +/** + * __useTripTagsCollectionQuery__ + * + * To run a query within a React component, call `useTripTagsCollectionQuery` and pass it any options that fit your needs. + * When your component renders, `useTripTagsCollectionQuery` 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 } = useTripTagsCollectionQuery({ + * variables: { + * filter: // value for 'filter' + * }, + * }); + */ +export function useTripTagsCollectionQuery( + baseOptions?: Apollo.QueryHookOptions< + TripTagsCollectionQuery, + TripTagsCollectionQueryVariables + > +) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useQuery< + TripTagsCollectionQuery, + TripTagsCollectionQueryVariables + >(TripTagsCollectionDocument, options) +} +export function useTripTagsCollectionLazyQuery( + baseOptions?: Apollo.LazyQueryHookOptions< + TripTagsCollectionQuery, + TripTagsCollectionQueryVariables + > +) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useLazyQuery< + TripTagsCollectionQuery, + TripTagsCollectionQueryVariables + >(TripTagsCollectionDocument, options) +} +export function useTripTagsCollectionSuspenseQuery( + baseOptions?: Apollo.SuspenseQueryHookOptions< + TripTagsCollectionQuery, + TripTagsCollectionQueryVariables + > +) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useSuspenseQuery< + TripTagsCollectionQuery, + TripTagsCollectionQueryVariables + >(TripTagsCollectionDocument, options) +} +export type TripTagsCollectionQueryHookResult = ReturnType< + typeof useTripTagsCollectionQuery +> +export type TripTagsCollectionLazyQueryHookResult = ReturnType< + typeof useTripTagsCollectionLazyQuery +> +export type TripTagsCollectionSuspenseQueryHookResult = ReturnType< + typeof useTripTagsCollectionSuspenseQuery +> +export type TripTagsCollectionQueryResult = Apollo.QueryResult< + TripTagsCollectionQuery, + TripTagsCollectionQueryVariables +> +export function refetchTripTagsCollectionQuery( + variables?: TripTagsCollectionQueryVariables +) { + return { query: TripTagsCollectionDocument, variables: variables } +} export const TripsCollectionDocument = gql` query tripsCollection( $filter: tripsFilter diff --git a/graphql-codegen/generated/gql.ts b/graphql-codegen/generated/gql.ts index 9d112f9..36f3aff 100644 --- a/graphql-codegen/generated/gql.ts +++ b/graphql-codegen/generated/gql.ts @@ -19,14 +19,20 @@ const documents = { types.ActivityCollectionDocument, '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($user_id: UUID!, $title: String!, $date_from: Date, $date_to: Date) {\n insertIntotripsCollection(\n objects: [{user_id: $user_id, title: $title, date_from: $date_from, date_to: $date_to}]\n ) {\n records {\n __typename\n id\n title\n }\n }\n}': + 'mutation createTrip($user_id: UUID!, $title: String!, $date_from: Datetime!, $date_to: Datetime) {\n insertIntotripsCollection(\n objects: [{user_id: $user_id, title: $title, date_from: $date_from, date_to: $date_to}]\n ) {\n records {\n __typename\n id\n title\n }\n }\n}': types.CreateTripDocument, + 'mutation createTripTag($tripId: UUID!, $tagId: UUID!) {\n insertIntotrip_tagsCollection(objects: [{trip_id: $tripId, tag_id: $tagId}]) {\n records {\n __typename\n id\n tag_id\n trip_id\n }\n }\n}': + types.CreateTripTagDocument, 'mutation deleteTag($id: UUID!) {\n deleteFromtagsCollection(filter: {id: {eq: $id}}) {\n records {\n __typename\n id\n name\n }\n }\n}': types.DeleteTagDocument, + 'mutation deleteTripTag($id: UUID!) {\n deleteFromtrip_tagsCollection(filter: {id: {eq: $id}}) {\n records {\n __typename\n id\n }\n }\n}': + types.DeleteTripTagDocument, '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_storage_object_id\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}': 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_storage_object_id\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}': types.TripsCollectionDocument } @@ -67,14 +73,26 @@ 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: 'mutation createTrip($user_id: UUID!, $title: String!, $date_from: Date, $date_to: Date) {\n insertIntotripsCollection(\n objects: [{user_id: $user_id, title: $title, date_from: $date_from, date_to: $date_to}]\n ) {\n records {\n __typename\n id\n title\n }\n }\n}' -): (typeof documents)['mutation createTrip($user_id: UUID!, $title: String!, $date_from: Date, $date_to: Date) {\n insertIntotripsCollection(\n objects: [{user_id: $user_id, title: $title, date_from: $date_from, date_to: $date_to}]\n ) {\n records {\n __typename\n id\n title\n }\n }\n}'] + source: 'mutation createTrip($user_id: UUID!, $title: String!, $date_from: Datetime!, $date_to: Datetime) {\n insertIntotripsCollection(\n objects: [{user_id: $user_id, title: $title, date_from: $date_from, date_to: $date_to}]\n ) {\n records {\n __typename\n id\n title\n }\n }\n}' +): (typeof documents)['mutation createTrip($user_id: UUID!, $title: String!, $date_from: Datetime!, $date_to: Datetime) {\n insertIntotripsCollection(\n objects: [{user_id: $user_id, title: $title, date_from: $date_from, date_to: $date_to}]\n ) {\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 createTripTag($tripId: UUID!, $tagId: UUID!) {\n insertIntotrip_tagsCollection(objects: [{trip_id: $tripId, tag_id: $tagId}]) {\n records {\n __typename\n id\n tag_id\n trip_id\n }\n }\n}' +): (typeof documents)['mutation createTripTag($tripId: UUID!, $tagId: UUID!) {\n insertIntotrip_tagsCollection(objects: [{trip_id: $tripId, tag_id: $tagId}]) {\n records {\n __typename\n id\n tag_id\n trip_id\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 deleteTag($id: UUID!) {\n deleteFromtagsCollection(filter: {id: {eq: $id}}) {\n records {\n __typename\n id\n name\n }\n }\n}' ): (typeof documents)['mutation deleteTag($id: UUID!) {\n deleteFromtagsCollection(filter: {id: {eq: $id}}) {\n records {\n __typename\n id\n name\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 deleteTripTag($id: UUID!) {\n deleteFromtrip_tagsCollection(filter: {id: {eq: $id}}) {\n records {\n __typename\n id\n }\n }\n}' +): (typeof documents)['mutation deleteTripTag($id: UUID!) {\n deleteFromtrip_tagsCollection(filter: {id: {eq: $id}}) {\n records {\n __typename\n id\n }\n }\n}'] /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ @@ -87,6 +105,12 @@ export function graphql( 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_storage_object_id\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_storage_object_id\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}'] +/** + * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. + */ +export function graphql( + source: '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}' +): (typeof documents)['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}'] /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ diff --git a/graphql-codegen/generated/graphql.ts b/graphql-codegen/generated/graphql.ts index 34153c1..b5f50ce 100644 --- a/graphql-codegen/generated/graphql.ts +++ b/graphql-codegen/generated/graphql.ts @@ -915,8 +915,8 @@ export type Trips = Node & { cost?: Maybe cost_unit?: Maybe created_at: Scalars['Datetime']['output'] - date_from: Scalars['Date']['output'] - date_to?: Maybe + date_from: Scalars['Datetime']['output'] + date_to?: Maybe description?: Maybe id: Scalars['UUID']['output'] image_storage_object_id?: Maybe @@ -980,8 +980,8 @@ export type TripsFilter = { cost?: InputMaybe cost_unit?: InputMaybe created_at?: InputMaybe - date_from?: InputMaybe - date_to?: InputMaybe + date_from?: InputMaybe + date_to?: InputMaybe description?: InputMaybe id?: InputMaybe image_storage_object_id?: InputMaybe @@ -994,8 +994,8 @@ export type TripsInsertInput = { cost?: InputMaybe cost_unit?: InputMaybe created_at?: InputMaybe - date_from?: InputMaybe - date_to?: InputMaybe + date_from?: InputMaybe + date_to?: InputMaybe description?: InputMaybe id?: InputMaybe image_storage_object_id?: InputMaybe @@ -1028,8 +1028,8 @@ export type TripsUpdateInput = { cost?: InputMaybe cost_unit?: InputMaybe created_at?: InputMaybe - date_from?: InputMaybe - date_to?: InputMaybe + date_from?: InputMaybe + date_to?: InputMaybe description?: InputMaybe id?: InputMaybe image_storage_object_id?: InputMaybe @@ -1214,8 +1214,8 @@ export type CreateTagMutation = { export type CreateTripMutationVariables = Exact<{ user_id: Scalars['UUID']['input'] title: Scalars['String']['input'] - date_from?: InputMaybe - date_to?: InputMaybe + date_from: Scalars['Datetime']['input'] + date_to?: InputMaybe }> export type CreateTripMutation = { @@ -1226,6 +1226,24 @@ export type CreateTripMutation = { } | null } +export type CreateTripTagMutationVariables = Exact<{ + tripId: Scalars['UUID']['input'] + tagId: Scalars['UUID']['input'] +}> + +export type CreateTripTagMutation = { + __typename: 'Mutation' + insertIntotrip_tagsCollection?: { + __typename: 'trip_tagsInsertResponse' + records: Array<{ + __typename: 'trip_tags' + id: string + tag_id?: string | null + trip_id?: string | null + }> + } | null +} + export type DeleteTagMutationVariables = Exact<{ id: Scalars['UUID']['input'] }> @@ -1238,6 +1256,18 @@ export type DeleteTagMutation = { } } +export type DeleteTripTagMutationVariables = Exact<{ + id: Scalars['UUID']['input'] +}> + +export type DeleteTripTagMutation = { + __typename: 'Mutation' + deleteFromtrip_tagsCollection: { + __typename: 'trip_tagsDeleteResponse' + records: Array<{ __typename: 'trip_tags'; id: string }> + } +} + export type TagsCollectionQueryVariables = Exact<{ userId: Scalars['UUID']['input'] }> @@ -1315,6 +1345,26 @@ export type TripDetailsQuery = { } | null } +export type TripTagsCollectionQueryVariables = Exact<{ + filter?: InputMaybe +}> + +export type TripTagsCollectionQuery = { + __typename: 'Query' + trip_tagsCollection?: { + __typename: 'trip_tagsConnection' + edges: Array<{ + __typename: 'trip_tagsEdge' + node: { + __typename: 'trip_tags' + id: string + trip_id?: string | null + tag_id?: string | null + } + }> + } | null +} + export type TripsCollectionQueryVariables = Exact<{ filter?: InputMaybe orderBy?: InputMaybe | TripsOrderBy> @@ -1712,7 +1762,7 @@ export const CreateTagDocument = { ] } as unknown as DocumentNode export const CreateTripDocument = { - __meta__: { hash: '995473133e320e5f7ef165df54d56100c62b3a75' }, + __meta__: { hash: 'aca942ce9802822f0ecd793697b6b6bf16d25152' }, kind: 'Document', definitions: [ { @@ -1748,7 +1798,13 @@ export const CreateTripDocument = { kind: 'Variable', name: { kind: 'Name', value: 'date_from' } }, - type: { kind: 'NamedType', name: { kind: 'Name', value: 'Date' } } + type: { + kind: 'NonNullType', + type: { + kind: 'NamedType', + name: { kind: 'Name', value: 'Datetime' } + } + } }, { kind: 'VariableDefinition', @@ -1756,7 +1812,7 @@ export const CreateTripDocument = { kind: 'Variable', name: { kind: 'Name', value: 'date_to' } }, - type: { kind: 'NamedType', name: { kind: 'Name', value: 'Date' } } + type: { kind: 'NamedType', name: { kind: 'Name', value: 'Datetime' } } } ], selectionSet: { @@ -1841,6 +1897,114 @@ export const CreateTripDocument = { } ] } as unknown as DocumentNode +export const CreateTripTagDocument = { + __meta__: { hash: 'b86b0c68b8ee2697ff1b539e5df92575cedb30f0' }, + kind: 'Document', + definitions: [ + { + kind: 'OperationDefinition', + operation: 'mutation', + name: { kind: 'Name', value: 'createTripTag' }, + variableDefinitions: [ + { + kind: 'VariableDefinition', + variable: { + kind: 'Variable', + name: { kind: 'Name', value: 'tripId' } + }, + type: { + kind: 'NonNullType', + type: { kind: 'NamedType', name: { kind: 'Name', value: 'UUID' } } + } + }, + { + kind: 'VariableDefinition', + variable: { + kind: 'Variable', + name: { kind: 'Name', value: 'tagId' } + }, + 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: 'insertIntotrip_tagsCollection' }, + arguments: [ + { + kind: 'Argument', + name: { kind: 'Name', value: 'objects' }, + value: { + kind: 'ListValue', + values: [ + { + kind: 'ObjectValue', + fields: [ + { + kind: 'ObjectField', + name: { kind: 'Name', value: 'trip_id' }, + value: { + kind: 'Variable', + name: { kind: 'Name', value: 'tripId' } + } + }, + { + kind: 'ObjectField', + name: { kind: 'Name', value: 'tag_id' }, + value: { + kind: 'Variable', + name: { kind: 'Name', value: 'tagId' } + } + } + ] + } + ] + } + } + ], + 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: 'tag_id' } + }, + { + kind: 'Field', + name: { kind: 'Name', value: 'trip_id' } + } + ] + } + } + ] + } + } + ] + } + } + ] +} as unknown as DocumentNode< + CreateTripTagMutation, + CreateTripTagMutationVariables +> export const DeleteTagDocument = { __meta__: { hash: 'c661c9a00fdae1dbac69eeb283611e0c9202cf55' }, kind: 'Document', @@ -1921,6 +2085,88 @@ export const DeleteTagDocument = { } ] } as unknown as DocumentNode +export const DeleteTripTagDocument = { + __meta__: { hash: '1a4d048db574dedfebd859dc737e16a42021f3ff' }, + kind: 'Document', + definitions: [ + { + kind: 'OperationDefinition', + operation: 'mutation', + name: { kind: 'Name', value: 'deleteTripTag' }, + 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: 'deleteFromtrip_tagsCollection' }, + 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' } } + ] + } + } + ] + } + } + ] + } + } + ] +} as unknown as DocumentNode< + DeleteTripTagMutation, + DeleteTripTagMutationVariables +> export const TagsCollectionDocument = { __meta__: { hash: '994a2e7e0694c279cbfeff6c8696cbbe6a0c687c' }, kind: 'Document', @@ -2405,6 +2651,97 @@ export const TripDetailsDocument = { } ] } as unknown as DocumentNode +export const TripTagsCollectionDocument = { + __meta__: { hash: 'f4142b2a2f4ab96ce0e69488851fdff976486652' }, + kind: 'Document', + definitions: [ + { + kind: 'OperationDefinition', + operation: 'query', + name: { kind: 'Name', value: 'tripTagsCollection' }, + variableDefinitions: [ + { + kind: 'VariableDefinition', + variable: { + kind: 'Variable', + name: { kind: 'Name', value: 'filter' } + }, + type: { + kind: 'NamedType', + name: { kind: 'Name', value: 'trip_tagsFilter' } + } + } + ], + selectionSet: { + kind: 'SelectionSet', + selections: [ + { kind: 'Field', name: { kind: 'Name', value: '__typename' } }, + { + kind: 'Field', + name: { kind: 'Name', value: 'trip_tagsCollection' }, + arguments: [ + { + kind: 'Argument', + name: { kind: 'Name', value: 'filter' }, + value: { + kind: 'Variable', + name: { kind: 'Name', value: 'filter' } + } + } + ], + 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: 'tag_id' } + } + ] + } + } + ] + } + } + ] + } + } + ] + } + } + ] +} as unknown as DocumentNode< + TripTagsCollectionQuery, + TripTagsCollectionQueryVariables +> export const TripsCollectionDocument = { __meta__: { hash: '70a61f873c23f1db13cef7cd265a9845e9bfc53e' }, kind: 'Document', diff --git a/graphql-codegen/generated/persisted-documents.json b/graphql-codegen/generated/persisted-documents.json index 5dfda2f..0bb8b8b 100644 --- a/graphql-codegen/generated/persisted-documents.json +++ b/graphql-codegen/generated/persisted-documents.json @@ -2,9 +2,12 @@ "00c528b2b1c851c06119aedb1fba6b5c885713cf": "query getUser($id: UUID!) { __typename usersCollection(filter: {id: {eq: $id}}) { __typename edges { __typename node { __typename email id name profile_picture_url } } } }", "2d419044f6b09dcfdf15e868fceccda14add69f4": "query activityCollection($id: UUID!) { __typename activityCollection(filter: {id: {eq: $id}}) { __typename edges { __typename node { __typename address cost id image_storage_object_id memo time_from time_to title trip_id url } } } }", "9ecd6081f83febe06337ebd01345eef596b81cf9": "mutation createTag($name: String!, $userId: UUID!) { __typename insertIntotagsCollection(objects: [{name: $name, user_id: $userId}]) { __typename records { __typename id name } } }", - "995473133e320e5f7ef165df54d56100c62b3a75": "mutation createTrip($date_from: Date, $date_to: Date, $title: String!, $user_id: UUID!) { __typename insertIntotripsCollection( objects: [{user_id: $user_id, title: $title, date_from: $date_from, date_to: $date_to}] ) { __typename records { __typename id title } } }", + "aca942ce9802822f0ecd793697b6b6bf16d25152": "mutation createTrip($date_from: Datetime!, $date_to: Datetime, $title: String!, $user_id: UUID!) { __typename insertIntotripsCollection( objects: [{user_id: $user_id, title: $title, date_from: $date_from, date_to: $date_to}] ) { __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 } } }", "c661c9a00fdae1dbac69eeb283611e0c9202cf55": "mutation deleteTag($id: UUID!) { __typename deleteFromtagsCollection(filter: {id: {eq: $id}}) { __typename records { __typename id name } } }", + "1a4d048db574dedfebd859dc737e16a42021f3ff": "mutation deleteTripTag($id: UUID!) { __typename deleteFromtrip_tagsCollection(filter: {id: {eq: $id}}) { __typename records { __typename id } } }", "994a2e7e0694c279cbfeff6c8696cbbe6a0c687c": "query tagsCollection($userId: UUID!) { __typename tagsCollection( filter: {user_id: {eq: $userId}} orderBy: {created_at: AscNullsLast} ) { __typename edges { __typename node { __typename id name } } } }", "12df849b2205e5cf49fd291f6cb8582aa49100c3": "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_storage_object_id invitationsCollection { __typename edges { __typename node { __typename users { __typename id profile_picture_url } } } } title trip_tagsCollection { __typename edges { __typename node { __typename tags { __typename id name } } } } } } } }", + "f4142b2a2f4ab96ce0e69488851fdff976486652": "query tripTagsCollection($filter: trip_tagsFilter) { __typename trip_tagsCollection(filter: $filter) { __typename edges { __typename node { __typename id tag_id trip_id } } } }", "70a61f873c23f1db13cef7cd265a9845e9bfc53e": "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_storage_object_id invitationsCollection { __typename edges { __typename node { __typename users { __typename id profile_picture_url } } } } title } } pageInfo { __typename endCursor hasNextPage hasPreviousPage startCursor } } }" } diff --git a/package.json b/package.json index 0dc97a4..1e450e5 100644 --- a/package.json +++ b/package.json @@ -24,12 +24,14 @@ "@emotion/styled": "^11.11.0", "@graphql-codegen/client-preset": "^4.1.0", "@types/jest": "^29.5.11", + "date-fns-tz": "^2.0.0", "framer-motion": "^10.16.4", "graphql": "^16.8.1", "next": "14.0.1", "react": "^18", "react-calendar": "^4.7.0", "react-clock": "^4.6.0", + "react-datepicker": "^5.0.0", "react-datetime-picker": "^5.6.0", "react-dom": "^18", "react-dropzone": "^14.2.3", @@ -60,6 +62,7 @@ "@testing-library/user-event": "^14.5.1", "@types/node": "^20", "@types/react": "^18", + "@types/react-datepicker": "^4.19.5", "@types/react-dom": "^18", "@types/react-slick": "^0.23.12", "@typescript-eslint/eslint-plugin": "^6.10.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7111f07..caf40b4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -29,6 +29,9 @@ dependencies: '@types/jest': specifier: ^29.5.11 version: 29.5.11 + date-fns-tz: + specifier: ^2.0.0 + version: 2.0.0(date-fns@2.30.0) framer-motion: specifier: ^10.16.4 version: 10.16.4(react-dom@18.2.0)(react@18.2.0) @@ -47,6 +50,9 @@ dependencies: react-clock: specifier: ^4.6.0 version: 4.6.0(@types/react@18.2.36)(react-dom@18.2.0)(react@18.2.0) + react-datepicker: + specifier: ^5.0.0 + version: 5.0.0(react-dom@18.2.0)(react@18.2.0) react-datetime-picker: specifier: ^5.6.0 version: 5.6.0(@types/react-dom@18.2.14)(@types/react@18.2.36)(react-dom@18.2.0)(react@18.2.0) @@ -133,6 +139,9 @@ devDependencies: '@types/react': specifier: ^18 version: 18.2.36 + '@types/react-datepicker': + specifier: ^4.19.5 + version: 4.19.5(react-dom@18.2.0)(react@18.2.0) '@types/react-dom': specifier: ^18 version: 18.2.14 @@ -3157,6 +3166,12 @@ packages: '@floating-ui/utils': 0.1.6 dev: true + /@floating-ui/core@1.6.0: + resolution: {integrity: sha512-PcF++MykgmTj3CIyOQbKA/hDzOAiqI3mhuoN44WRCopIs1sgoDoU4oty4Jtqaj/y3oDU6fnVSm4QG0a3t5i0+g==} + dependencies: + '@floating-ui/utils': 0.2.1 + dev: false + /@floating-ui/dom@1.5.3: resolution: {integrity: sha512-ClAbQnEqJAKCJOEbbLo5IUlZHkNszqhuxS4fHAVxRPXPya6Ysf2G8KypnYcOTpx6I8xcgF9bbHb6g/2KpbV8qA==} dependencies: @@ -3164,6 +3179,13 @@ packages: '@floating-ui/utils': 0.1.6 dev: true + /@floating-ui/dom@1.6.0: + resolution: {integrity: sha512-SZ0BEXzsaaS6THZfZJUcAobbZTD+MvfGM42bxgeg0Tnkp4/an/avqwAXiVLsFtIBZtfsx3Ymvwx0+KnnhdA/9g==} + dependencies: + '@floating-ui/core': 1.6.0 + '@floating-ui/utils': 0.2.1 + dev: false + /@floating-ui/react-dom@2.0.2(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-5qhlDvjaLmAst/rKb3VdlCinwTF4EYMiVxuuc/HVUjs46W0zgtbMmAZ1UTsDrRTxRmUEzl92mOtWbeeXL26lSQ==} peerDependencies: @@ -3175,10 +3197,38 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: true + /@floating-ui/react-dom@2.0.7(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-B5GJxKUyPcGsvE1vua+Abvw0t6zVMyTbtG+Jk7BoI4hfc5Ahv50dstRIAn0nS0274kR9gnKwxIXyGA8EzBZJrA==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + dependencies: + '@floating-ui/dom': 1.6.0 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@floating-ui/react@0.26.7(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-0uMI9IBJBPPt8N+8uRg4gazJvQReWTu/fVUHHLfAOuy1WB6f242jtjWm52hLJG8nzuZVuU+2crW4lJbJQoqeIA==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + dependencies: + '@floating-ui/react-dom': 2.0.7(react-dom@18.2.0)(react@18.2.0) + '@floating-ui/utils': 0.2.1 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + tabbable: 6.2.0 + dev: false + /@floating-ui/utils@0.1.6: resolution: {integrity: sha512-OfX7E2oUDYxtBvsuS4e/jSn4Q9Qb6DzgeYtsAdkPZ47znpoNsMgZw0+tVijiv3uGNR6dgNlty6r9rzIzHjtd/A==} dev: true + /@floating-ui/utils@0.2.1: + resolution: {integrity: sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q==} + dev: false + /@graphql-codegen/add@5.0.0(graphql@16.8.1): resolution: {integrity: sha512-ynWDOsK2yxtFHwcJTB9shoSkUd7YXd6ZE57f0nk7W5cu/nAgxZZpEsnTPEpZB/Mjf14YRGe2uJHQ7AfElHjqUQ==} peerDependencies: @@ -7180,6 +7230,18 @@ packages: resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} dev: true + /@types/react-datepicker@4.19.5(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-tKpuj19p9T4sBQm3Bw13CPuhalo4CFOe/LcSUGJ5z6DmHoiBX3uq33iMKePeSEq7OxyU8O1rh5emAm92nyXZLg==} + dependencies: + '@popperjs/core': 2.11.8 + '@types/react': 18.2.36 + date-fns: 2.30.0 + react-popper: 2.3.0(@popperjs/core@2.11.8)(react-dom@18.2.0)(react@18.2.0) + transitivePeerDependencies: + - react + - react-dom + dev: true + /@types/react-dom@18.2.14: resolution: {integrity: sha512-V835xgdSVmyQmI1KLV2BEIUgqEuinxp9O4G6g3FqO/SqLac049E53aysv0oEFD2kHfejeKU+ZqL2bcFWj9gLAQ==} dependencies: @@ -9725,6 +9787,20 @@ packages: resolution: {integrity: sha512-8YnDaaf7N3k/q5HnTJVuzSyLETjoZjVmHc4AeKAzOvKHEFQKcn64OKBfzHYtE9zGjctNM7V9I0MfnUVLpi7M5g==} dev: true + /date-fns-tz@2.0.0(date-fns@2.30.0): + resolution: {integrity: sha512-OAtcLdB9vxSXTWHdT8b398ARImVwQMyjfYGkKD2zaGpHseG2UPHbHjXELReErZFxWdSLph3c2zOaaTyHfOhERQ==} + peerDependencies: + date-fns: '>=2.0.0' + dependencies: + date-fns: 2.30.0 + dev: false + + /date-fns@2.30.0: + resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==} + engines: {node: '>=0.11'} + dependencies: + '@babel/runtime': 7.23.2 + /debounce@1.2.1: resolution: {integrity: sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==} dev: true @@ -15083,6 +15159,21 @@ packages: - '@types/react-dom' dev: false + /react-datepicker@5.0.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-AYpBCzinlE0fpltMtjjcpkiIyZVI3o9rbrhaMuf7oZcFp4LyRW2veCwORVFdcj4ProqnKTwNJBrTtauyanjMwg==} + peerDependencies: + react: ^16.9.0 || ^17 || ^18 + react-dom: ^16.9.0 || ^17 || ^18 + dependencies: + '@floating-ui/react': 0.26.7(react-dom@18.2.0)(react@18.2.0) + classnames: 2.5.1 + date-fns: 2.30.0 + prop-types: 15.8.1 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react-onclickoutside: 6.13.0(react-dom@18.2.0)(react@18.2.0) + dev: false + /react-datetime-picker@5.6.0(@types/react-dom@18.2.14)(@types/react@18.2.36)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-zbYSuYuiRj4/6lR9xGjAgw7V4gpTGtzOwZIfw1TONj6K6OKuaDreczS+6ijJjwLYlMcx8V+Sw1IMP+K059wnnA==} peerDependencies: @@ -15249,6 +15340,30 @@ packages: /react-is@18.1.0: resolution: {integrity: sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==} + /react-onclickoutside@6.13.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-ty8So6tcUpIb+ZE+1HAhbLROvAIJYyJe/1vRrrcmW+jLsaM+/powDRqxzo6hSh9CuRZGSL1Q8mvcF5WRD93a0A==} + peerDependencies: + react: ^15.5.x || ^16.x || ^17.x || ^18.x + react-dom: ^15.5.x || ^16.x || ^17.x || ^18.x + dependencies: + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /react-popper@2.3.0(@popperjs/core@2.11.8)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-e1hj8lL3uM+sgSR4Lxzn5h1GxBlpa4CQz0XLF8kx4MDrDRWY0Ena4c97PUeSX9i5W3UAfDP0z0FXCTQkoXUl3Q==} + peerDependencies: + '@popperjs/core': ^2.0.0 + react: ^16.8.0 || ^17 || ^18 + react-dom: ^16.8.0 || ^17 || ^18 + dependencies: + '@popperjs/core': 2.11.8 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react-fast-compare: 3.2.2 + warning: 4.0.3 + dev: true + /react-refresh@0.11.0: resolution: {integrity: sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==} engines: {node: '>=0.10.0'} @@ -16614,6 +16729,10 @@ packages: resolution: {integrity: sha512-AsS729u2RHUfEra9xJrE39peJcc2stq2+poBXX8bcM08Y6g9j/i/PUzwNQqkaJde7Ntg1TO7bSREbR5sdosQ+g==} dev: true + /tabbable@6.2.0: + resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==} + dev: false + /tapable@1.1.3: resolution: {integrity: sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==} engines: {node: '>=6'} @@ -17517,6 +17636,12 @@ packages: makeerror: 1.0.12 dev: true + /warning@4.0.3: + resolution: {integrity: sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==} + dependencies: + loose-envify: 1.4.0 + dev: true + /watchpack-chokidar2@2.0.1: resolution: {integrity: sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww==} requiresBuild: true