diff --git a/apps/web/app/(main)/profile/schedule/page.tsx b/apps/web/app/(main)/profile/schedule/page.tsx index 5988505..3320219 100644 --- a/apps/web/app/(main)/profile/schedule/page.tsx +++ b/apps/web/app/(main)/profile/schedule/page.tsx @@ -1,3 +1,12 @@ +import { PageHeader } from '@/components/navigation'; +import { SlotsCalendar, TimeSlots } from '@/components/schedule'; + export default function SchedulePage() { - return 'Schedule'; + return ( + <> + + + + > + ); } diff --git a/apps/web/components/common/vanilla-calendar.tsx b/apps/web/components/common/vanilla-calendar.tsx new file mode 100644 index 0000000..b0e3be3 --- /dev/null +++ b/apps/web/components/common/vanilla-calendar.tsx @@ -0,0 +1,29 @@ +'use client'; +import { useLocale } from 'next-intl'; +import { useEffect, useRef, useState } from 'react'; +import 'vanilla-calendar-pro/styles/index.css'; +import { Calendar, type Options } from 'vanilla-calendar-pro'; + +type CalendarProps = React.HTMLAttributes & { + readonly config?: Options; +}; + +function VanillaCalendar({ config, ...attributes }: CalendarProps) { + const ref = useRef(null); + const [calendar, setCalendar] = useState(null); + const locale = useLocale(); + + useEffect(() => { + if (!ref.current) return; + setCalendar(new Calendar(ref.current, { ...config, locale })); + }, [config, locale, ref]); + + useEffect(() => { + if (!calendar) return; + calendar.init(); + }, [calendar]); + + return ; +} + +export default VanillaCalendar; diff --git a/apps/web/components/schedule/calendar.tsx b/apps/web/components/schedule/calendar.tsx new file mode 100644 index 0000000..7b2cf9b --- /dev/null +++ b/apps/web/components/schedule/calendar.tsx @@ -0,0 +1,14 @@ +import VanillaCalendar from '@/components/common/vanilla-calendar'; + +export function SlotsCalendar() { + return ( + + + + ); +} diff --git a/apps/web/components/schedule/index.ts b/apps/web/components/schedule/index.ts new file mode 100644 index 0000000..01500b8 --- /dev/null +++ b/apps/web/components/schedule/index.ts @@ -0,0 +1,2 @@ +export * from './calendar'; +export * from './time-slots'; diff --git a/apps/web/components/schedule/time-slots/add-slot-form.tsx b/apps/web/components/schedule/time-slots/add-slot-form.tsx new file mode 100644 index 0000000..5b2e169 --- /dev/null +++ b/apps/web/components/schedule/time-slots/add-slot-form.tsx @@ -0,0 +1,48 @@ +'use client'; +import { Button } from '@repo/ui/components/ui/button'; +import { Input } from '@repo/ui/components/ui/input'; +import { type FormEvent, useState } from 'react'; + +type Props = { + readonly onAddSlot: (startTime: string, endTime: string) => void; +}; + +export function AddSlotForm({ onAddSlot }: Props) { + const [startTime, setStartTime] = useState(''); + const [endTime, setEndTime] = useState(''); + + const handleSubmit = (event: FormEvent) => { + event.preventDefault(); + if (startTime && endTime) { + onAddSlot(startTime, endTime); + setStartTime(''); + setEndTime(''); + } + }; + + return ( + + + + setStartTime(event.target.value)} + required + type="time" + value={startTime} + /> + + + setEndTime(event.target.value)} + required + type="time" + value={endTime} + /> + + + Добавить + + ); +} diff --git a/apps/web/components/schedule/time-slots/index.tsx b/apps/web/components/schedule/time-slots/index.tsx new file mode 100644 index 0000000..df88b12 --- /dev/null +++ b/apps/web/components/schedule/time-slots/index.tsx @@ -0,0 +1,10 @@ +import { AddSlotForm } from './add-slot-form'; + +export function TimeSlots() { + return ( + + Добавить новый интервал + + + ); +} diff --git a/apps/web/package.json b/apps/web/package.json index 59a121a..500ebfd 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -27,6 +27,7 @@ "react": "catalog:", "react-dom": "catalog:", "use-debounce": "^10.0.4", + "vanilla-calendar-pro": "^3.0.3", "zod": "catalog:" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 24ffd59..a19094c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -177,6 +177,9 @@ importers: use-debounce: specifier: ^10.0.4 version: 10.0.4(react@19.0.0) + vanilla-calendar-pro: + specifier: ^3.0.3 + version: 3.0.3 zod: specifier: 'catalog:' version: 3.24.1 @@ -6121,6 +6124,9 @@ packages: resolution: {integrity: sha512-Z6Uz+TYwEqE7ZN50gwn+1LCVo9ZVrpxRPOhOLnncYkY1ZzOYtrX8Fwf/rFktZ8R5mJms6EZf5TqNOMeZmnPq9Q==} engines: {node: '>=12'} + vanilla-calendar-pro@3.0.3: + resolution: {integrity: sha512-bfmeGFaDeakk/OrwgM+22qDiRvIx1Zu+GG3+E/sCPjaKwbJR7AsDyRBfJQzVHRw3eeavU8jQQTRSFt8EPIPOGw==} + vite-node@2.1.8: resolution: {integrity: sha512-uPAwSr57kYjAUux+8E2j0q0Fxpn8M9VoyfGiRI8Kfktz9NcYMCenwY5RnZxnF1WTu3TGiYipirIzacLL3VVGFg==} engines: {node: ^18.0.0 || >=20.0.0} @@ -12945,6 +12951,8 @@ snapshots: value-or-promise@1.0.12: {} + vanilla-calendar-pro@3.0.3: {} + vite-node@2.1.8(@types/node@20.17.8): dependencies: cac: 6.7.14