add basic slot page
This commit is contained in:
parent
209114a394
commit
1d1a90b6d3
@ -16,10 +16,10 @@ export async function addSlot(input: AddSlotInput) {
|
||||
|
||||
return api.createSlot({
|
||||
...input,
|
||||
date: formatDate(input.date),
|
||||
date: formatDate(input.date).db(),
|
||||
master: customer?.documentId,
|
||||
time_end: formatTime(input.time_end),
|
||||
time_start: formatTime(input.time_start),
|
||||
time_end: formatTime(input.time_end).db(),
|
||||
time_start: formatTime(input.time_start).db(),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,25 @@
|
||||
import { getSlot } from '@/actions/slots';
|
||||
import { PageHeader } from '@/components/navigation';
|
||||
import { TimeCard } from '@/components/schedule';
|
||||
import { dehydrate, HydrationBoundary, QueryClient } from '@tanstack/react-query';
|
||||
|
||||
type Props = { params: Promise<{ documentId: string }> };
|
||||
|
||||
export default async function ProfilePage(props: Readonly<Props>) {
|
||||
const parameters = await props.params;
|
||||
const { documentId } = parameters;
|
||||
|
||||
const queryClient = new QueryClient();
|
||||
|
||||
await queryClient.prefetchQuery({
|
||||
queryFn: () => getSlot({ documentId }),
|
||||
queryKey: ['schedule', 'slots', 'get', documentId],
|
||||
});
|
||||
|
||||
return (
|
||||
<HydrationBoundary state={dehydrate(queryClient)}>
|
||||
<PageHeader title={undefined} />
|
||||
<TimeCard {...parameters} />
|
||||
</HydrationBoundary>
|
||||
);
|
||||
}
|
||||
@ -1,2 +1,3 @@
|
||||
export * from './calendar';
|
||||
export * from './time-card';
|
||||
export * from './time-slots';
|
||||
|
||||
22
apps/web/components/schedule/time-card.tsx
Normal file
22
apps/web/components/schedule/time-card.tsx
Normal file
@ -0,0 +1,22 @@
|
||||
'use client';
|
||||
import { type SlotProps } from './types';
|
||||
import { useSlotQuery } from '@/hooks/slots';
|
||||
import { formatDate, formatTime } from '@/utils/date';
|
||||
|
||||
export function TimeCard({ documentId }: Readonly<SlotProps>) {
|
||||
const { data } = useSlotQuery({ documentId });
|
||||
|
||||
if (!data?.slot) return null;
|
||||
|
||||
return (
|
||||
<div className="flex flex-col p-4">
|
||||
<span className="mb-2 tracking-wide">{formatDate(data?.slot?.date).user()}</span>
|
||||
<span className="mt-2 text-3xl font-bold tracking-wide">
|
||||
{formatTime(data?.slot?.time_start).user()}
|
||||
</span>
|
||||
<span className="mt-2 text-3xl font-bold tracking-wide">
|
||||
{formatTime(data?.slot?.time_end).user()}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
'use client';
|
||||
import { type SlotProps } from '../../types';
|
||||
import { ContextProvider } from '../context';
|
||||
import { type SlotProps } from '../types';
|
||||
import { ReadonlyTimeRange } from './time-pair';
|
||||
import { useSlotQuery } from '@/hooks/slots';
|
||||
import { withContext } from '@/utils/context';
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
'use client';
|
||||
import { type Slot } from '../../types';
|
||||
import { Context, type ContextType } from '../context';
|
||||
import { type Slot } from '../types';
|
||||
import { useSlotAdd } from '@/hooks/slots';
|
||||
import { parseTime } from '@/utils/date';
|
||||
import { formatTime } from '@/utils/date';
|
||||
import { Input } from '@repo/ui/components/ui/input';
|
||||
import { cn } from '@repo/ui/lib/utils';
|
||||
import { use } from 'react';
|
||||
|
||||
type TimePairProps = Pick<ContextType, 'endTime' | 'setEndTime' | 'setStartTime' | 'startTime'> & {
|
||||
@ -25,12 +26,16 @@ export function AddTimePair() {
|
||||
);
|
||||
}
|
||||
|
||||
export function ReadonlyTimeRange({ time_end, time_start }: Readonly<Slot>) {
|
||||
export function ReadonlyTimeRange({
|
||||
className,
|
||||
time_end,
|
||||
time_start,
|
||||
}: Readonly<Slot> & { readonly className?: string }) {
|
||||
return (
|
||||
<div className="flex flex-row items-center gap-2 text-lg font-bold">
|
||||
<span>{parseTime(time_start)}</span>
|
||||
<div className={cn('flex flex-row items-center gap-2 text-lg font-bold', className)}>
|
||||
<span className="tracking-wider">{formatTime(time_start).user()}</span>
|
||||
{' - '}
|
||||
<span>{parseTime(time_end)}</span>
|
||||
<span className="tracking-wider">{formatTime(time_end).user()}</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -18,7 +18,7 @@ export const useSlots = () => {
|
||||
getSlots({
|
||||
filters: {
|
||||
date: {
|
||||
eq: formatDate(selectedDate),
|
||||
eq: formatDate(selectedDate).db(),
|
||||
},
|
||||
},
|
||||
}),
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
/* eslint-disable import/no-unassigned-import */
|
||||
import dayjs from 'dayjs';
|
||||
import 'dayjs/locale/ru';
|
||||
|
||||
export function combineDateTime(date: Date, time: string) {
|
||||
const [hours = '00', minutes = '00'] = time.split(':');
|
||||
@ -12,16 +14,22 @@ export function combineDateTime(date: Date, time: string) {
|
||||
);
|
||||
}
|
||||
|
||||
export function formatDate(date: Date) {
|
||||
return dayjs(date).format('YYYY-MM-DD');
|
||||
export function formatDate(date: Date | string) {
|
||||
return {
|
||||
db: () => dayjs(date).format('YYYY-MM-DD'),
|
||||
user: () => {
|
||||
const lang = document.documentElement.lang || 'ru';
|
||||
dayjs.locale(lang);
|
||||
return dayjs(date).format('D MMMM YYYY');
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function formatTime(time: string) {
|
||||
return `${time}:00`;
|
||||
}
|
||||
|
||||
export function parseTime(time: string) {
|
||||
const [hours = '00', minutes = '00'] = time.split(':');
|
||||
|
||||
return `${hours}:${minutes}`;
|
||||
return {
|
||||
db: () => `${hours}:${minutes}:00`,
|
||||
user: () => `${hours}:${minutes}`,
|
||||
};
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user