Skip to content

Commit

Permalink
feat(web): select calendar field
Browse files Browse the repository at this point in the history
  • Loading branch information
nichenqin committed Jan 3, 2023
1 parent f8a1726 commit 69d6d37
Show file tree
Hide file tree
Showing 11 changed files with 401 additions and 53 deletions.
74 changes: 74 additions & 0 deletions apps/web/components/calendar-ui/calendar-board.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import type { QueryRecords } from '@egodb/core'
import type { ICalendarField } from '@egodb/core/view/calendar'
import { Calendar, Container } from '@egodb/ui'
import { useSetAtom } from 'jotai'
import { useState } from 'react'
import { createRecordInitialValueAtom } from '../create-record-form/create-record-initial-value.atom'
import { createRecordFormDrawerOpened } from '../create-record-form/drawer-opened.atom'
import type { ITableBaseProps } from '../table/table-base-props'
import { Day } from './day'

interface IProps extends ITableBaseProps {
field: ICalendarField
records: QueryRecords
}

export const CalendarBoard: React.FC<IProps> = ({ field }) => {
const [date, setDate] = useState<Date | null>(null)
const setOpened = useSetAtom(createRecordFormDrawerOpened)
const setInitialValue = useSetAtom(createRecordInitialValueAtom)

const onChange = (date: Date) => {
setDate(date)
setOpened(true)
setInitialValue({ [field.name.value]: date })
}

return (
<Container w="100%" h="100%" maw="100%" p={0}>
<Calendar
value={date}
onChange={onChange}
h="100%"
bg="white"
fullWidth
size="xl"
allowLevelChange={false}
renderDay={(date) => <Day date={date} />}
styles={(theme) => ({
calendarHeader: {
height: 30,
marginBottom: 0,
paddingBottom: 10,
backgroundColor: theme.colorScheme === 'dark' ? theme.colors.dark[5] : theme.colors.gray[0],
},
calendarHeaderControl: {
height: '100%',
},
calendarHeaderLevel: {
height: '100%',
fontSize: theme.fontSizes.md,
},
month: { height: 'calc(100% - 40px)' },
cell: {
border: `1px solid ${theme.colorScheme === 'dark' ? theme.colors.dark[4] : theme.colors.gray[1]}`,
},
day: {
padding: theme.spacing.xs,
borderRadius: 0,
height: '100%',
display: 'inline-flex',
flexDirection: 'column',
fontSize: theme.fontSizes.sm,
},
weekday: { fontSize: theme.fontSizes.lg },
weekdayCell: {
fontSize: theme.fontSizes.xs,
border: `1px solid ${theme.colorScheme === 'dark' ? theme.colors.dark[4] : theme.colors.gray[1]}`,
height: 20,
},
})}
/>
</Container>
)
}
7 changes: 7 additions & 0 deletions apps/web/components/calendar-ui/calendar-step.atom.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { atom } from 'jotai'

export const calendarStep = atom(0)

export const calendarStepZero = atom(null, (get, set) => set(calendarStep, 0))
export const calendarStepOne = atom(null, (get, set) => set(calendarStep, 1))
export const calendarStepTwo = atom(null, (get, set) => set(calendarStep, 2))
65 changes: 16 additions & 49 deletions apps/web/components/calendar-ui/calendar-ui.tsx
Original file line number Diff line number Diff line change
@@ -1,60 +1,27 @@
import type { QueryRecords } from '@egodb/core'
import { Calendar, Container } from '@egodb/ui'
import { useState } from 'react'
import type { ICalendarField } from '@egodb/core/view/calendar'
import { Center, Container } from '@egodb/ui'
import type { ITableBaseProps } from '../table/table-base-props'
import { Day } from './day'
import { CalendarBoard } from './calendar-board'
import { SelectCalendarField } from './select-calendar-field'

interface IProps extends ITableBaseProps {
records: QueryRecords
}

export const CalendarUI: React.FC<IProps> = () => {
const [date, setDate] = useState<Date | null>(null)
export const CalendarUI: React.FC<IProps> = ({ table, records }) => {
const view = table.mustGetView()
const calendarFieldId = view.calendarFieldId.into()
if (calendarFieldId) {
const field = table.schema.getFieldById(calendarFieldId.value).into() as ICalendarField
return <CalendarBoard table={table} records={records} field={field} />
}

return (
<Container w="100%" h="100%" maw="100%" p={0}>
<Calendar
value={date}
onChange={setDate}
h="100%"
bg="white"
fullWidth
size="xl"
allowLevelChange={false}
renderDay={(date) => <Day date={date} />}
styles={(theme) => ({
calendarHeader: {
height: 30,
marginBottom: 0,
paddingBottom: 10,
backgroundColor: theme.colorScheme === 'dark' ? theme.colors.dark[5] : theme.colors.gray[0],
},
calendarHeaderControl: {
height: '100%',
},
calendarHeaderLevel: {
height: '100%',
fontSize: theme.fontSizes.md,
},
month: { height: 'calc(100% - 40px)' },
cell: {
border: `1px solid ${theme.colorScheme === 'dark' ? theme.colors.dark[4] : theme.colors.gray[1]}`,
},
day: {
padding: theme.spacing.xs,
borderRadius: 0,
height: '100%',
display: 'inline-flex',
flexDirection: 'column',
fontSize: theme.fontSizes.sm,
},
weekday: { fontSize: theme.fontSizes.lg },
weekdayCell: {
fontSize: theme.fontSizes.xs,
border: `1px solid ${theme.colorScheme === 'dark' ? theme.colors.dark[4] : theme.colors.gray[1]}`,
height: 20,
},
})}
/>
<Container h="100%" w={450}>
<Center h="100%" w="100%">
<SelectCalendarField table={table} />
</Center>
</Container>
)
}
92 changes: 92 additions & 0 deletions apps/web/components/calendar-ui/create-calendar-date-field.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import type { ICreateDateFieldSchema } from '@egodb/core'
import { createDateFieldSchema, FieldId } from '@egodb/core'
import {
Button,
Card,
FocusTrap,
Group,
IconChevronLeft,
Stack,
Text,
TextInput,
useForm,
zodResolver,
} from '@egodb/ui'
import { useSetAtom } from 'jotai'
import { trpc } from '../../trpc'
import type { ITableBaseProps } from '../table/table-base-props'
import { calendarStepZero } from './calendar-step.atom'

interface IProps extends ITableBaseProps {
onSuccess?: () => void
}

export const CreateCalendarDateField: React.FC<IProps> = ({ table, onSuccess }) => {
const form = useForm<ICreateDateFieldSchema>({
initialValues: {
type: 'date',
id: 'id',
name: '',
},
validate: zodResolver(createDateFieldSchema),
})

const utils = trpc.useContext()

const setCalendarField = trpc.table.view.calendar.setField.useMutation({
onSuccess() {
utils.table.get.refetch()
setStepZero()
onSuccess?.()
},
})

const createDateField = trpc.table.field.create.useMutation({
onSuccess(_, variables) {
const id = variables.field.id

setCalendarField.mutate({
tableId: table.id.value,
field: id,
})
},
})

const onSubmit = form.onSubmit((values) => {
createDateField.mutate({
id: table.id.value,
field: { ...values, id: FieldId.create().value },
})
})

const setStepZero = useSetAtom(calendarStepZero)

return (
<form onSubmit={onSubmit}>
<Card shadow="sm">
<Card.Section withBorder inheritPadding py="sm">
<Text>create new date field</Text>
</Card.Section>

<Card.Section withBorder inheritPadding py="sm">
<Stack spacing="xs">
<FocusTrap>
<TextInput {...form.getInputProps('name')} placeholder="new date field name" />
</FocusTrap>
</Stack>
</Card.Section>

<Card.Section withBorder inheritPadding py="sm">
<Group position="right">
<Button leftIcon={<IconChevronLeft size={14} />} size="xs" variant="white" onClick={setStepZero}>
Select Existing Field
</Button>
<Button size="xs" type="submit" disabled={!form.isValid()}>
Done
</Button>
</Group>
</Card.Section>
</Card>
</form>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import type { ICreateDateRangeFieldSchema } from '@egodb/core'
import { createDateRangeFieldSchema } from '@egodb/core'
import { FieldId } from '@egodb/core'
import {
Button,
Card,
FocusTrap,
Group,
IconChevronLeft,
Stack,
Text,
TextInput,
useForm,
zodResolver,
} from '@egodb/ui'
import { useSetAtom } from 'jotai'
import { trpc } from '../../trpc'
import type { ITableBaseProps } from '../table/table-base-props'
import { calendarStepZero } from './calendar-step.atom'

interface IProps extends ITableBaseProps {
onSuccess?: () => void
}

export const CreateCalendarDateRangeField: React.FC<IProps> = ({ table, onSuccess }) => {
const form = useForm<ICreateDateRangeFieldSchema>({
initialValues: {
type: 'date-range',
id: 'id',
name: '',
},
validate: zodResolver(createDateRangeFieldSchema),
})

const utils = trpc.useContext()

const setCalendarField = trpc.table.view.calendar.setField.useMutation({
onSuccess() {
utils.table.get.refetch()
setStepZero()
onSuccess?.()
},
})

const createDateRangeField = trpc.table.field.create.useMutation({
onSuccess(_, variables) {
const id = variables.field.id

setCalendarField.mutate({
tableId: table.id.value,
field: id,
})
},
})

const onSubmit = form.onSubmit((values) => {
createDateRangeField.mutate({
id: table.id.value,
field: { ...values, id: FieldId.create().value },
})
})

const setStepZero = useSetAtom(calendarStepZero)

return (
<form onSubmit={onSubmit}>
<Card shadow="sm">
<Card.Section withBorder inheritPadding py="sm">
<Text>create new date range field</Text>
</Card.Section>

<Card.Section withBorder inheritPadding py="sm">
<Stack spacing="xs">
<FocusTrap>
<TextInput {...form.getInputProps('name')} placeholder="new date range field name" />
</FocusTrap>
</Stack>
</Card.Section>

<Card.Section withBorder inheritPadding py="sm">
<Group position="right">
<Button leftIcon={<IconChevronLeft size={14} />} size="xs" variant="white" onClick={setStepZero}>
Select Existing Field
</Button>
<Button size="xs" type="submit" disabled={!form.isValid()}>
Done
</Button>
</Group>
</Card.Section>
</Card>
</form>
)
}
22 changes: 22 additions & 0 deletions apps/web/components/calendar-ui/select-calendar-field.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { useAtomValue } from 'jotai'
import type { ITableBaseProps } from '../table/table-base-props'
import { calendarStep } from './calendar-step.atom'
import { CreateCalendarDateField } from './create-calendar-date-field'
import { CreateCalendarDateRangeField } from './create-calendar-date-range-field'
import { SelectExistingCalendarField } from './select-existing-calendar-field'

interface IProps extends ITableBaseProps {
onSuccess?: () => void
}

export const SelectCalendarField: React.FC<IProps> = ({ table, onSuccess }) => {
const step = useAtomValue(calendarStep)

return (
<>
{step === 0 ? <SelectExistingCalendarField onSuccess={onSuccess} table={table} /> : null}
{step === 1 ? <CreateCalendarDateField onSuccess={onSuccess} table={table} /> : null}
{step === 2 ? <CreateCalendarDateRangeField onSuccess={onSuccess} table={table} /> : null}
</>
)
}
Loading

0 comments on commit 69d6d37

Please sign in to comment.