From f1c87a13053244878f06bed41422e962a8795938 Mon Sep 17 00:00:00 2001 From: Dasha Date: Tue, 3 Mar 2026 16:34:04 +0100 Subject: [PATCH 1/5] Add description field to appointment schema and types --- server/src/db/schemes/appointmentSchema.ts | 1 + server/src/db/schemes/types/appointment.types.ts | 1 + server/src/types/appointment/appointment.types.ts | 1 + 3 files changed, 3 insertions(+) diff --git a/server/src/db/schemes/appointmentSchema.ts b/server/src/db/schemes/appointmentSchema.ts index 0d5e278..6b2e6ea 100644 --- a/server/src/db/schemes/appointmentSchema.ts +++ b/server/src/db/schemes/appointmentSchema.ts @@ -22,6 +22,7 @@ export const AppointmentSchema = new mongoose.Schema( price: { type: String, required: true }, date: { type: String, required: true }, time: { type: String, required: true }, + description: { type: String, default: "" }, status: { type: String, required: true, diff --git a/server/src/db/schemes/types/appointment.types.ts b/server/src/db/schemes/types/appointment.types.ts index 2ea51c4..bf7db7f 100644 --- a/server/src/db/schemes/types/appointment.types.ts +++ b/server/src/db/schemes/types/appointment.types.ts @@ -14,6 +14,7 @@ export interface AppointmentTypeDB { price: string; date: string; time: string; + description?: string; status: "pending" | "approved" | "rejected"; videoCall?: string; isRegularStudent?: boolean; diff --git a/server/src/types/appointment/appointment.types.ts b/server/src/types/appointment/appointment.types.ts index 3a64264..d4ae26d 100644 --- a/server/src/types/appointment/appointment.types.ts +++ b/server/src/types/appointment/appointment.types.ts @@ -10,6 +10,7 @@ export interface CreateAppointmentType { price: string; date: string; time: string; + description?: string; } export interface UpdateAppointmentStatusType { From 09554d869e5cc8a5161e7de53e29ae91b7f1a069 Mon Sep 17 00:00:00 2001 From: Dasha Date: Tue, 3 Mar 2026 16:34:36 +0100 Subject: [PATCH 2/5] Update appointment service --- server/src/services/appointment/appointment.service.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/server/src/services/appointment/appointment.service.ts b/server/src/services/appointment/appointment.service.ts index df09bc4..e792d4a 100644 --- a/server/src/services/appointment/appointment.service.ts +++ b/server/src/services/appointment/appointment.service.ts @@ -73,6 +73,7 @@ export class AppointmentService { price: data.price, date: data.date, time: data.time, + description: data.description || "", status: "pending" as const, videoCall: `https://meet.google.com/${data.teacherId}-${data.studentId}-${Date.now()}`, isRegularStudent: false, @@ -303,6 +304,7 @@ export class AppointmentService { price: string | number; date: string; time: string; + description?: string; status: string; videoCall?: string; isRegularStudent?: boolean; @@ -325,6 +327,7 @@ export class AppointmentService { price: priceStr, date: apt.date, time: apt.time, + description: apt.description, status: apt.status, videoCall: apt.videoCall, isRegularStudent: apt.isRegularStudent, From 0dbff39055dd58bd556739d2497484b65c1b70ba Mon Sep 17 00:00:00 2001 From: Dasha Date: Tue, 3 Mar 2026 16:36:46 +0100 Subject: [PATCH 3/5] Add description --- client/src/components/appointmentCard/AppointmentCard.tsx | 1 + client/src/components/appointmentCard/AppointmentInfo.tsx | 8 ++++++++ .../bookingConfirmation/BookingConfirmation.tsx | 7 +++++++ .../teacherAppointmentCard/TeacherAppointmentCard.tsx | 1 + .../teacherAppointmentCard/TeacherAppointmentInfo.tsx | 8 ++++++++ .../mutations/useCreateAppointmentMutation.ts | 1 + client/src/types/appointments.types.ts | 1 + 7 files changed, 27 insertions(+) diff --git a/client/src/components/appointmentCard/AppointmentCard.tsx b/client/src/components/appointmentCard/AppointmentCard.tsx index e377c3f..7a941ee 100644 --- a/client/src/components/appointmentCard/AppointmentCard.tsx +++ b/client/src/components/appointmentCard/AppointmentCard.tsx @@ -57,6 +57,7 @@ export const AppointmentCard = ({ lesson={appointment.lesson} teacherName={appointment.teacherName} price={appointment.price} + description={appointment.description} weeklySchedule={appointment.weeklySchedule} isRegularTeacher={isRegularTeacher} /> diff --git a/client/src/components/appointmentCard/AppointmentInfo.tsx b/client/src/components/appointmentCard/AppointmentInfo.tsx index bb0b1e8..d340462 100644 --- a/client/src/components/appointmentCard/AppointmentInfo.tsx +++ b/client/src/components/appointmentCard/AppointmentInfo.tsx @@ -4,6 +4,7 @@ export type AppointmentInfoProps = { lesson?: string; teacherName?: string; price: string; + description?: string; weeklySchedule?: WeeklyScheduleSlot[]; isRegularTeacher?: boolean; }; @@ -33,6 +34,7 @@ export const AppointmentInfo = ({ lesson, teacherName, price, + description, weeklySchedule, isRegularTeacher = false, }: AppointmentInfoProps) => { @@ -50,6 +52,12 @@ export const AppointmentInfo = ({ {teacherName || "Teacher"} + {description && ( +
+ {description} +
+ )} +
{price} euro /hour
diff --git a/client/src/components/bookingConfirmation/BookingConfirmation.tsx b/client/src/components/bookingConfirmation/BookingConfirmation.tsx index c0660e0..43a3257 100644 --- a/client/src/components/bookingConfirmation/BookingConfirmation.tsx +++ b/client/src/components/bookingConfirmation/BookingConfirmation.tsx @@ -28,6 +28,7 @@ export const BookingConfirmation = ({ selectedSubject, selectedLevel, selectedPrice, + description, onSuccess: onSuccessCallback, } = payload; @@ -52,6 +53,7 @@ export const BookingConfirmation = ({ "General Lesson", price: selectedPrice?.toString() || teacher.priceFrom?.toString() || "0", level: selectedLevel || "", + description: description || "", }; createAppointment(appointmentData, { @@ -93,6 +95,11 @@ export const BookingConfirmation = ({

Price: €{selectedPrice || teacher?.priceFrom}

+ {description && ( +

+ Description: {description} +

+ )}

The lesson request will be sent to the teacher.

diff --git a/client/src/components/teacherAppointmentCard/TeacherAppointmentCard.tsx b/client/src/components/teacherAppointmentCard/TeacherAppointmentCard.tsx index db78e4c..9dc8a0c 100644 --- a/client/src/components/teacherAppointmentCard/TeacherAppointmentCard.tsx +++ b/client/src/components/teacherAppointmentCard/TeacherAppointmentCard.tsx @@ -59,6 +59,7 @@ export const TeacherAppointmentCard = ({ lesson={appointment.lesson} studentName={appointment.studentName} price={appointment.price} + description={appointment.description} weeklySchedule={appointment.weeklySchedule} isRegularTab={isRegularTab} /> diff --git a/client/src/components/teacherAppointmentCard/TeacherAppointmentInfo.tsx b/client/src/components/teacherAppointmentCard/TeacherAppointmentInfo.tsx index 1459368..429eb86 100644 --- a/client/src/components/teacherAppointmentCard/TeacherAppointmentInfo.tsx +++ b/client/src/components/teacherAppointmentCard/TeacherAppointmentInfo.tsx @@ -4,6 +4,7 @@ export type TeacherAppointmentInfoProps = { lesson?: string; studentName?: string; price: string; + description?: string; weeklySchedule?: WeeklyScheduleSlot[]; isRegularTab?: boolean; }; @@ -33,6 +34,7 @@ export const TeacherAppointmentInfo = ({ lesson, studentName, price, + description, weeklySchedule, isRegularTab = false, }: TeacherAppointmentInfoProps) => { @@ -54,6 +56,12 @@ export const TeacherAppointmentInfo = ({ {price} euro /hour + {description && ( +
+ {description} +
+ )} + {isRegularTab && weeklySchedule && weeklySchedule.length > 0 && (
{formatSchedule(weeklySchedule)} diff --git a/client/src/features/appointments/mutations/useCreateAppointmentMutation.ts b/client/src/features/appointments/mutations/useCreateAppointmentMutation.ts index f2a439b..337956f 100644 --- a/client/src/features/appointments/mutations/useCreateAppointmentMutation.ts +++ b/client/src/features/appointments/mutations/useCreateAppointmentMutation.ts @@ -12,6 +12,7 @@ interface CreateAppointmentRequest { time: string; lesson: string; price: string; + description?: string; } const createAppointment = async ( diff --git a/client/src/types/appointments.types.ts b/client/src/types/appointments.types.ts index 4d9e071..dd28f4e 100644 --- a/client/src/types/appointments.types.ts +++ b/client/src/types/appointments.types.ts @@ -12,6 +12,7 @@ export interface Appointment { price: string; date: string; time: string; + description?: string; status: AppointmentStatus; videoCall?: string; isRegularStudent?: boolean; From 547640cfa1c13cdd70fb81078199423921216cca Mon Sep 17 00:00:00 2001 From: Dasha Date: Tue, 3 Mar 2026 16:46:59 +0100 Subject: [PATCH 4/5] feat: regular students improve --- client/package-lock.json | 35 ++++---------- .../RegularStudentScheduleModal.tsx | 32 +++++++++++++ .../teacherSchedule/TeacherSchedule.tsx | 47 ++++++++++++++++++- client/src/store/modals.store.ts | 1 + .../appointmentDescription.validation.ts | 24 ++++++++++ server/package-lock.json | 11 ----- server/src/routes/uploadRoute.ts | 4 +- 7 files changed, 114 insertions(+), 40 deletions(-) create mode 100644 client/src/utils/appointmentDescription.validation.ts diff --git a/client/package-lock.json b/client/package-lock.json index aaa77f5..fcf79b1 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -130,7 +130,6 @@ "integrity": "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.28.6", "@babel/generator": "^7.28.6", @@ -2124,7 +2123,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=18" }, @@ -2148,7 +2146,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=18" } @@ -4904,7 +4901,6 @@ "resolved": "https://registry.npmjs.org/@stream-io/video-client/-/video-client-1.43.0.tgz", "integrity": "sha512-DIP24SzyvvhCZ0ac6jrZ2ks4G9KWYCySlVGaRrRGVpsqQNINW6tOXXuKCCoZAQPlv279M3Jt1hf/fQjZMqNtvg==", "license": "See license in LICENSE", - "peer": true, "dependencies": { "@protobuf-ts/runtime": "^2.11.1", "@protobuf-ts/runtime-rpc": "^2.11.1", @@ -5342,7 +5338,8 @@ "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@types/babel__core": { "version": "7.20.5", @@ -5464,7 +5461,6 @@ "integrity": "sha512-Lpo8kgb/igvMIPeNV2rsYKTgaORYdO1XGVZ4Qz3akwOj0ySGYMPlQWa8BaLn0G63D1aSaAQ5ldR06wCpChQCjA==", "devOptional": true, "license": "MIT", - "peer": true, "dependencies": { "csstype": "^3.2.2" } @@ -5475,7 +5471,6 @@ "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", "devOptional": true, "license": "MIT", - "peer": true, "peerDependencies": { "@types/react": "^19.2.0" } @@ -5619,7 +5614,6 @@ "integrity": "sha512-BtE0k6cjwjLZoZixN0t5AKP0kSzlGu7FctRXYuPAm//aaiZhmfq1JwdYpYr1brzEspYyFeF+8XF5j2VK6oalrA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.54.0", "@typescript-eslint/types": "8.54.0", @@ -6547,7 +6541,6 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -7119,7 +7112,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -7273,7 +7265,6 @@ "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.5.1.tgz", "integrity": "sha512-GIjfiT9dbmHRiYi6Nl2yFCq7kkwdkp1W/lp2J99rX0yo9tgJGn3lKQATztIjb5tVtevcBtIdICNWqlq5+E8/Pw==", "license": "MIT", - "peer": true, "dependencies": { "@kurkle/color": "^0.3.0" }, @@ -7743,7 +7734,8 @@ "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/dotenv": { "version": "17.2.3", @@ -8128,7 +8120,6 @@ "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -8189,7 +8180,6 @@ "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", "dev": true, "license": "MIT", - "peer": true, "bin": { "eslint-config-prettier": "bin/cli.js" }, @@ -11327,7 +11317,6 @@ "integrity": "sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "cssstyle": "^4.2.1", "data-urls": "^5.0.0", @@ -11903,6 +11892,7 @@ "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", "dev": true, "license": "MIT", + "peer": true, "bin": { "lz-string": "bin/bin.js" } @@ -12723,7 +12713,6 @@ "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", "dev": true, "license": "MIT", - "peer": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -12869,7 +12858,6 @@ "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -13066,6 +13054,7 @@ "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", @@ -13081,6 +13070,7 @@ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=10" }, @@ -13173,7 +13163,6 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -13193,7 +13182,6 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz", "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==", "license": "MIT", - "peer": true, "dependencies": { "scheduler": "^0.27.0" }, @@ -13206,7 +13194,6 @@ "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.71.1.tgz", "integrity": "sha512-9SUJKCGKo8HUSsCO+y0CtqkqI5nNuaDqTxyqPsZPqIwudpj4rCrAz/jZV+jn57bx5gtZKOh3neQu94DXMc+w5w==", "license": "MIT", - "peer": true, "engines": { "node": ">=18.0.0" }, @@ -13223,7 +13210,8 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/react-refresh": { "version": "0.18.0", @@ -14409,7 +14397,6 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -14658,7 +14645,6 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "devOptional": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -14902,7 +14888,6 @@ "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz", "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", "license": "MIT", - "peer": true, "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", @@ -14994,7 +14979,6 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -15475,7 +15459,6 @@ "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz", "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==", "license": "MIT", - "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } diff --git a/client/src/components/regularStudentScheduleModal/RegularStudentScheduleModal.tsx b/client/src/components/regularStudentScheduleModal/RegularStudentScheduleModal.tsx index 913e34d..2fe4fab 100644 --- a/client/src/components/regularStudentScheduleModal/RegularStudentScheduleModal.tsx +++ b/client/src/components/regularStudentScheduleModal/RegularStudentScheduleModal.tsx @@ -3,6 +3,7 @@ import { Button } from "../ui/button/Button"; import Cross from "../icons/Cross"; import { SelectComponent } from "../ui/select/Select"; import { WeeklyScheduleSlot } from "../../types/appointments.types"; +import { useModalStore } from "../../store/modals.store"; interface RegularStudentScheduleModalProps { isOpen: boolean; @@ -40,6 +41,7 @@ const ModalContent = ({ useState(initialSavedSlots); const [currentDay, setCurrentDay] = useState("Monday"); const [currentHour, setCurrentHour] = useState(7); + const { open: openModal } = useModalStore(); const isDuplicate = savedSlots.some( (slot) => slot.day === currentDay && slot.hour === currentHour, @@ -78,6 +80,15 @@ const ModalContent = ({ }; const handleSave = () => { + if (!hasScheduleChanged) { + openModal("alert", { + title: "No Changes Made", + message: + "Please click on 'Add to Schedule' button to add lessons before saving.", + }); + return; + } + onSave(savedSlots); onClose(); }; @@ -86,6 +97,27 @@ const ModalContent = ({ onClose(); }; + const hasScheduleChanged = (() => { + if (savedSlots.length !== initialSavedSlots.length) { + return true; + } + + const sortSlots = (slots: WeeklyScheduleSlot[]) => + [...slots].sort((a, b) => { + if (a.day !== b.day) return a.day.localeCompare(b.day); + return a.hour - b.hour; + }); + + const sortedSaved = sortSlots(savedSlots); + const sortedInitial = sortSlots(initialSavedSlots); + + return !sortedSaved.every( + (slot, index) => + slot.day === sortedInitial[index]?.day && + slot.hour === sortedInitial[index]?.hour, + ); + })(); + return (
diff --git a/client/src/components/teacherSection/teacherSchedule/TeacherSchedule.tsx b/client/src/components/teacherSection/teacherSchedule/TeacherSchedule.tsx index 308c776..c43891c 100644 --- a/client/src/components/teacherSection/teacherSchedule/TeacherSchedule.tsx +++ b/client/src/components/teacherSection/teacherSchedule/TeacherSchedule.tsx @@ -7,6 +7,7 @@ import { useAuthSessionStore } from "../../../store/authSession.store"; import { useTeacherAppointmentsQuery } from "../../../features/appointments/query/useTeacherAppointmentsQuery"; import { SelectComponent } from "../../ui/select/Select.tsx"; import { Button } from "../../ui/button/Button"; +import { getDescriptionValidation } from "../../../utils/appointmentDescription.validation"; interface TeacherScheduleProps { teacher?: TeacherType; @@ -18,6 +19,7 @@ export default function TeacherSchedule({ teacher }: TeacherScheduleProps) { const [selectedSubject, setSelectedSubject] = useState(""); const [selectedLevel, setSelectedLevel] = useState(""); const [selectedTime, setSelectedTime] = useState(null); + const [description, setDescription] = useState(""); const [showSubjectLevelSelection, setShowSubjectLevelSelection] = useState(false); @@ -87,6 +89,12 @@ export default function TeacherSchedule({ teacher }: TeacherScheduleProps) { return levelItem.price; }, [selectedSubject, selectedLevel, teacher]); + const descriptionValidation = useMemo(() => { + return getDescriptionValidation(description); + }, [description]); + + const { wordCount, isValid: isDescriptionValid } = descriptionValidation; + const handleDateSelection = (date: Date): void => { setSelectedDate(date); setShowTimeAndBook(true); @@ -128,6 +136,7 @@ export default function TeacherSchedule({ teacher }: TeacherScheduleProps) { selectedSubject, selectedLevel, selectedPrice: selectedPrice || undefined, + description, onSuccess: () => { setSelectedDate(null); setShowTimeAndBook(false); @@ -135,6 +144,7 @@ export default function TeacherSchedule({ teacher }: TeacherScheduleProps) { setShowSubjectLevelSelection(false); setSelectedSubject(""); setSelectedLevel(""); + setDescription(""); }, }); } @@ -313,11 +323,44 @@ export default function TeacherSchedule({ teacher }: TeacherScheduleProps) {
)} + {selectedSubject && selectedLevel && ( +
+ +