Skip to content

Commit

Permalink
Change tags form
Browse files Browse the repository at this point in the history
  • Loading branch information
kanatagu committed Jan 26, 2024
1 parent ffe39a3 commit 4c0f5aa
Show file tree
Hide file tree
Showing 17 changed files with 1,103 additions and 108 deletions.
2 changes: 1 addition & 1 deletion app/components/input/input-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export const InputForm = forwardRef(
const placeholdercolor = useColorModeValue('gray.400', 'gray.600')

return (
<InputGroup minW={{ base: '100%', md: '23.75rem' }}>
<InputGroup minW={'100%'}>
<ChakraFormInput
{...props}
ref={ref}
Expand Down
1 change: 1 addition & 0 deletions app/components/input/input-icon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export const InputIcon = forwardRef<ChakraInputProps & InputIconProps, 'input'>(
type={onClick ? 'button' : 'submit'}
onClick={onClick}
color="primary.700"
isDisabled={props.isDisabled}
>
<Icon size="24px" />
</IconButton>
Expand Down
10 changes: 7 additions & 3 deletions app/components/loading/loading.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import { VStack, Spinner } from '@chakra-ui/react'

export const Loading = () => {
type LoadingProps = {
size?: string
p?: string
}
export const Loading = ({ size = 'xl', p = '60px' }: LoadingProps) => {
return (
<VStack align="center" p="60px">
<VStack align="center" p={p}>
<Spinner
thickness="4px"
speed="0.6s"
emptyColor="gray.200"
color="primary.500"
size="xl"
size={size}
/>
</VStack>
)
Expand Down
59 changes: 56 additions & 3 deletions app/trip/[id]/edit/page.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,48 @@
'use client'

import { NetworkStatus } from '@apollo/client'
import { Box, Container, Heading, useColorModeValue } from '@chakra-ui/react'
// import { Loading } from '@/components/loading'
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'

export default function TripEditPage({ params }: { params: { id: string } }) {
const bg = useColorModeValue('white', 'gray.800')
const color = useColorModeValue('black', 'gray.300')

console.log(params)
const userId = useUserId()

const { data: tripData, loading: tripLoading } = useTripDetailsQuery({
variables: {
id: params.id
}
})

const {
data: tagsData,
loading: tagsLoading,
refetch: tagsRefetch,
networkStatus: tagsNetWorkStatus
} = useTagsCollectionQuery({
variables: { userId },
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

console.log('tripDataCollection', tripDataCollection)
console.log('tagsData', tagsData)

return (
<>
Expand All @@ -24,7 +57,27 @@ export default function TripEditPage({ params }: { params: { id: string } }) {
Edit Trip
</Heading>
<Box mt="40px">
<TripForm />
{!tripDataCollection || tripLoading ? (
<Loading />
) : (
<TripForm
id={tripDataCollection.id}
image={tripDataCollection.image_storage_object_id}
title={tripDataCollection.title}
dateFrom={tripDataCollection.date_from}
dateTo={tripDataCollection.date_to}
tags={
tagsData?.tagsCollection?.edges.map((tag) => ({
id: tag.node.id,
name: tag.node.name
})) || []
}
cost={tripDataCollection.cost}
costUnit={tripDataCollection.cost_unit}
tagsCollectionRefetch={tagsCollectionRefetch}
tagsRefetchLoading={tagsRefetchLoading}
/>
)}
</Box>
</Container>
</Box>
Expand Down
2 changes: 1 addition & 1 deletion app/trip/components/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export { TagFormModal } from './tag-form-modal'
export { TripCard } from './trip-card'
export { TripFormTag } from './trip-form-tag'
export { TripForm } from './trip-form'
export { TripSearch } from './trip-search'
export { TripSort } from './trip-sort'
178 changes: 178 additions & 0 deletions app/trip/components/tag-form-modal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
import { KeyboardEvent } from 'react'
import { useForm } from 'react-hook-form'
import {
Modal,
ModalOverlay,
ModalContent,
ModalFooter,
ModalBody,
ModalCloseButton,
FormErrorMessage,
FormControl,
Flex,
Tag,
useColorModeValue,
Box,
Heading,
useToast
} from '@chakra-ui/react'
import { FiPlusCircle, FiX } from 'react-icons/fi'
import { InputIcon } from '@/components/input'
import { Loading } from '@/components/loading'
import { useUserId } from '@/providers/session-provider'
import { TagSchema, tagSchemaResolver } from '../schema'
import { useCreateTagMutation, useDeleteTagMutation } from '@generated/api'

type TagFormModalProps = {
isOpen: boolean
onClose: () => void
tags: { id: string; name: string }[]
tagsCollectionRefetch: () => void
}

export const TagFormModal = ({
isOpen,
onClose,
tags,
tagsCollectionRefetch
}: TagFormModalProps) => {
const tagBgColor = useColorModeValue('primary.700', 'primary.800')
const userId = useUserId()
const toast = useToast()

const {
register,
handleSubmit,
reset,
formState: { errors }
} = useForm<TagSchema>({
resolver: tagSchemaResolver
})

const [createTagMutation, { loading: isCreating }] = useCreateTagMutation()
const [deleteTagMutation, { loading: isDeleting }] = useDeleteTagMutation()

const addTag = async (input: TagSchema) => {
try {
await createTagMutation({
variables: {
name: input.name,
userId: userId
}
})
reset()
tagsCollectionRefetch()
} catch (error) {
console.error(error)
toast({
title: "We're sorry, but you failed to create a tag",
description:
error instanceof Error ? error.message : 'Please try again later.',
status: 'error',
duration: 5000,
isClosable: true,
position: 'top'
})
}
}

const addEnterHandler = (e: KeyboardEvent<HTMLInputElement>) => {
if (e.key === 'Enter') {
e.preventDefault()
handleSubmit(addTag)()
}
}

const deleteTag = async (id: string) => {
try {
await deleteTagMutation({
variables: {
id: id
}
})
tagsCollectionRefetch()
} catch (error) {
console.error(error)
toast({
title: "We're sorry, but you failed to delete a tag",
description:
error instanceof Error ? error.message : 'Please try again later.',
status: 'error',
duration: 5000,
isClosable: true,
position: 'top'
})
}
}

return (
<Modal isOpen={isOpen} onClose={onClose} isCentered>
<ModalOverlay />
<ModalContent maxW="30rem">
<ModalCloseButton />
<ModalBody pt="48px">
<Flex flexDir="column" gap="30px">
<Box as="form">
<Heading as="h2" fontSize="xl">
Tag List
</Heading>
<Flex columnGap="20px" rowGap="10px" flexWrap="wrap" mt="8px">
{isCreating || isDeleting ? (
<Loading p="10px" size="md" />
) : (
<>
{tags.map((tag) => (
<Tag
key={tag.id}
variant="solid"
bgColor={tagBgColor}
borderRadius="full"
px="14px"
py="6px"
gap="8px"
>
{tag.name}
<Box
as="button"
cursor="pointer"
_hover={{
opacity: '.7'
}}
type="button"
onClick={() => deleteTag(tag.id)}
>
<FiX size="18" />
</Box>
</Tag>
))}
</>
)}
</Flex>
</Box>
<Box as="form">
<Heading as="h2" fontSize="xl">
Add New Tag
</Heading>
<Box mt="8px">
<FormControl isInvalid={!!errors.name}>
<InputIcon
type={'text'}
placeholder={'Add tag'}
ariaLabel={'Add tag'}
icon={FiPlusCircle}
isDisabled={isCreating}
onKeyDown={(e) => addEnterHandler(e)}
onClick={handleSubmit((d) => addTag(d))}
{...register('name')}
/>
<FormErrorMessage>{errors?.name?.message}</FormErrorMessage>
</FormControl>
</Box>
</Box>
</Flex>
</ModalBody>
<ModalFooter />
</ModalContent>
</Modal>
)
}
77 changes: 0 additions & 77 deletions app/trip/components/trip-form-tag.tsx

This file was deleted.

Loading

0 comments on commit 4c0f5aa

Please sign in to comment.