select time feature & get final order values
This commit is contained in:
parent
7fcf67eece
commit
3738c4e2a9
@ -6,6 +6,7 @@ import dayjs from 'dayjs';
|
||||
export function DateSelect() {
|
||||
const selectedDate = useOrderStore((store) => store.date);
|
||||
const setDate = useOrderStore((store) => store.setDate);
|
||||
const setTime = useOrderStore((store) => store.setTime);
|
||||
|
||||
return (
|
||||
<Calendar
|
||||
@ -16,6 +17,7 @@ export function DateSelect() {
|
||||
mode="single"
|
||||
onSelect={(date) => {
|
||||
if (date) setDate(date);
|
||||
setTime(null);
|
||||
}}
|
||||
selected={selectedDate}
|
||||
/>
|
||||
|
||||
@ -1,31 +1,34 @@
|
||||
/* eslint-disable canonical/id-match */
|
||||
'use client';
|
||||
import { useSlots } from '@/hooks/slots';
|
||||
import { useOrderStore } from '@/stores/order';
|
||||
import { Enum_Slot_State, type SlotFieldsFragment } from '@repo/graphql/types';
|
||||
import { Button } from '@repo/ui/components/ui/button';
|
||||
import dayjs, { type Dayjs } from 'dayjs';
|
||||
import { sift } from 'radash';
|
||||
|
||||
type TimeSlotsProps = {
|
||||
endTime?: string;
|
||||
interval?: number;
|
||||
startTime?: string;
|
||||
};
|
||||
const generateTimeSlots = (start: string, end: string, interval: number): Dayjs[] => {
|
||||
const generateTimeSlots = (slots: SlotFieldsFragment[]): Dayjs[] => {
|
||||
const times: Dayjs[] = [];
|
||||
let currentTime = dayjs(start, 'HH:mm');
|
||||
const endTime = dayjs(end, 'HH:mm');
|
||||
for (const slot of slots) {
|
||||
let currentTime = dayjs(`${slot.date} ${slot.time_start}`);
|
||||
const endTime = dayjs(`${slot.date} ${slot.time_end}`);
|
||||
|
||||
while (currentTime.isBefore(endTime) || currentTime.isSame(endTime)) {
|
||||
times.push(currentTime);
|
||||
currentTime = currentTime.add(interval, 'minute');
|
||||
while (currentTime.isBefore(endTime) || currentTime.isSame(endTime)) {
|
||||
times.push(currentTime);
|
||||
currentTime = currentTime.add(30, 'minute');
|
||||
}
|
||||
}
|
||||
|
||||
return times;
|
||||
};
|
||||
|
||||
export function TimeSelect({
|
||||
endTime = '2025-03-10T20:00:00',
|
||||
interval = 30,
|
||||
startTime = '2025-03-10T09:00:00',
|
||||
}: Readonly<TimeSlotsProps>) {
|
||||
const timeSlots = generateTimeSlots(startTime, endTime, interval);
|
||||
export function TimeSelect() {
|
||||
const masterId = useOrderStore((store) => store.masterId);
|
||||
const date = useOrderStore((store) => store.date);
|
||||
const { data } = useSlots({ date, masterId });
|
||||
|
||||
const openedSlots = data?.data.slots.filter((slot) => slot?.state === Enum_Slot_State.Open);
|
||||
const timeSlots = generateTimeSlots(openedSlots ? sift(openedSlots) : []);
|
||||
|
||||
const morning = timeSlots.filter((time) => time.hour() < 12);
|
||||
const afternoon = timeSlots.filter((time) => time.hour() >= 12 && time.hour() < 18);
|
||||
@ -41,6 +44,8 @@ export function TimeSelect({
|
||||
}
|
||||
|
||||
function TimeSlotsButtons({ times, title }: Readonly<{ times: Dayjs[]; title: string }>) {
|
||||
const setTime = useOrderStore((store) => store.setTime);
|
||||
|
||||
if (!times.length) return null;
|
||||
|
||||
return (
|
||||
@ -48,7 +53,12 @@ function TimeSlotsButtons({ times, title }: Readonly<{ times: Dayjs[]; title: st
|
||||
<h2 className="text-lg font-semibold">{title}</h2>
|
||||
<div className="grid grid-cols-3 gap-2">
|
||||
{times.map((time) => (
|
||||
<Button className="mb-2" key={time.toString()} variant="outline">
|
||||
<Button
|
||||
className="mb-2"
|
||||
key={time.toString()}
|
||||
onClick={() => setTime(time.format('HH:mm'))}
|
||||
variant="outline"
|
||||
>
|
||||
{time.format('HH:mm')}
|
||||
</Button>
|
||||
))}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
export * from './back-button';
|
||||
export * from './contacts-grid';
|
||||
export * from './datetime-select';
|
||||
export * from './next-button';
|
||||
export * from './service-select';
|
||||
export * from './submit-button';
|
||||
|
||||
@ -2,34 +2,38 @@
|
||||
import { useOrderStore } from '@/stores/order';
|
||||
import { Button } from '@repo/ui/components/ui/button';
|
||||
|
||||
export function SubmitButton() {
|
||||
const step = useOrderStore((store) => store.step);
|
||||
const nextStep = useOrderStore((store) => store.nextStep);
|
||||
|
||||
function handleOnClick() {
|
||||
if (step !== 'success') {
|
||||
nextStep();
|
||||
}
|
||||
}
|
||||
export function NextButton() {
|
||||
const { clientId, date, masterId, nextStep, serviceId, step, time } = useOrderStore(
|
||||
(store) => store,
|
||||
);
|
||||
|
||||
const disabled = useButtonDisabled();
|
||||
|
||||
function handleOnClick() {
|
||||
nextStep();
|
||||
// eslint-disable-next-line no-console
|
||||
console.log({ clientId, date, masterId, serviceId, step, time });
|
||||
}
|
||||
|
||||
return (
|
||||
<Button className="w-full" disabled={disabled} onClick={() => handleOnClick()} type="button">
|
||||
{step === 'success' ? 'Создать' : 'Продолжить'}
|
||||
{step === 'datetime-select' ? 'Завершить' : 'Далее'}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
function useButtonDisabled() {
|
||||
const step = useOrderStore((state) => state.step);
|
||||
const clientId = useOrderStore((state) => state.clientId);
|
||||
const masterId = useOrderStore((state) => state.masterId);
|
||||
const serviceId = useOrderStore((state) => state.serviceId);
|
||||
const step = useOrderStore((state) => state.step);
|
||||
const date = useOrderStore((state) => state.date);
|
||||
const time = useOrderStore((state) => state.time);
|
||||
|
||||
return (
|
||||
(step === 'master-select' && !masterId) ||
|
||||
(step === 'client-select' && !clientId) ||
|
||||
(step === 'service-select' && !serviceId)
|
||||
(step === 'service-select' && !serviceId) ||
|
||||
(step === 'datetime-select' && (!date || !time))
|
||||
);
|
||||
}
|
||||
@ -5,8 +5,8 @@ import {
|
||||
ClientsGrid,
|
||||
DateTimeSelect,
|
||||
MastersGrid,
|
||||
NextButton,
|
||||
ServiceSelect,
|
||||
SubmitButton,
|
||||
} from './components';
|
||||
import { OrderStoreProvider, useOrderStore } from '@/stores/order';
|
||||
import { useInitOrderStore } from '@/stores/order/hooks';
|
||||
@ -30,7 +30,7 @@ export const OrderForm = withContext(OrderStoreProvider)(function () {
|
||||
<div className="space-y-4 [&>*]:px-4">
|
||||
{getStepComponent(step)}
|
||||
<div className="space-y-2">
|
||||
<SubmitButton />
|
||||
<NextButton />
|
||||
<BackButton />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -18,7 +18,7 @@ type SlotMutationInput = {
|
||||
|
||||
type SlotQueryInput = {
|
||||
date: Date;
|
||||
masterId?: string;
|
||||
masterId?: null | string;
|
||||
};
|
||||
|
||||
export const useSlots = ({ date, masterId }: SlotQueryInput) => {
|
||||
|
||||
@ -20,6 +20,7 @@ export type OrderStore = {
|
||||
export type Steps =
|
||||
| 'client-select'
|
||||
| 'datetime-select'
|
||||
| 'error'
|
||||
| 'loading'
|
||||
| 'master-select'
|
||||
| 'service-select'
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user