diff --git a/apps/web/src/components/Settings/PersonalDetails.tsx b/apps/web/src/components/Settings/PersonalDetails.tsx index 51ca2ee65..5afa500d8 100644 --- a/apps/web/src/components/Settings/PersonalDetails.tsx +++ b/apps/web/src/components/Settings/PersonalDetails.tsx @@ -35,6 +35,7 @@ import { useBlock } from "@litespace/ui/hooks/common"; type Form = { name: string; email: string; + price?: number; phone: string; city: IUser.City | null; notice: number; @@ -97,6 +98,7 @@ const PersonalDetails: React.FC = ({ const validators = useMakeValidators
({ name: { required: !!name, validate: validateUserName }, email: { required: true, validate: validateEmail }, + price: { required: true }, phone: { required: false, validate: validatePhone }, notice: { required: false, validate: validateNotice }, }); @@ -240,6 +242,20 @@ const PersonalDetails: React.FC = ({ disabled={!forStudent} /> + {!forStudent ? ( + form.set("email", e.target.value)} + label={intl("labels.email")} + placeholder={intl("labels.email.placeholder")} + state={form.errors?.email ? "error" : undefined} + helper={form.errors?.email} + autoComplete="off" + /> + ) : null} + { + pgm.addColumn("tutors", { + price: { + type: "int", + notNull: false, + }, + }); +} + +export async function down(pgm: MigrationBuilder): Promise { + pgm.dropColumn("tutors", "price"); +} diff --git a/packages/models/src/tutors.ts b/packages/models/src/tutors.ts index b3ac32906..694804fc2 100644 --- a/packages/models/src/tutors.ts +++ b/packages/models/src/tutors.ts @@ -55,6 +55,7 @@ const fullTutorFields: FullTutorFieldsMap = { thumbnail: tutorColumn("thumbnail"), notice: tutorColumn("notice"), activated: tutorColumn("activated"), + price: tutorColumn("price"), bypass_onboarding: tutorColumn("bypass_onboarding"), } as const; @@ -85,6 +86,7 @@ export class Tutors { .update({ bio: payload.bio, about: payload.about, + price: payload.price, video: payload.video, notice: payload.notice, thumbnail: payload.thumbnail, @@ -507,6 +509,7 @@ export class Tutors { id: row.id, bio: row.bio, about: row.about, + price: row.price, video: row.video, thumbnail: row.thumbnail, studioId: row.studio_id, @@ -543,6 +546,7 @@ export class Tutors { id: row.id, bio: row.bio, about: row.about, + price: row.price, video: row.video, thumbnail: row.thumbnail, studioId: row.studio_id, diff --git a/packages/types/src/tutor.ts b/packages/types/src/tutor.ts index 706fe08fd..4bdaf49e7 100644 --- a/packages/types/src/tutor.ts +++ b/packages/types/src/tutor.ts @@ -5,6 +5,7 @@ export type Self = { id: number; bio: string | null; about: string | null; + price: number | null; video: string | null; studioId: number | null; thumbnail: string | null; @@ -74,6 +75,7 @@ export type Row = { notice: number; bio: string | null; about: string | null; + price: number | null; video: string | null; role: IUser.Role; activated: boolean; @@ -95,6 +97,7 @@ export type TutorMedia = { export type UpdatePayload = { bio?: string | null; about?: string | null; + price?: number | null; video?: string | null; thumbnail?: string | null; studioId?: number | null; diff --git a/packages/types/src/user.ts b/packages/types/src/user.ts index 930ef843e..177c3ba8f 100644 --- a/packages/types/src/user.ts +++ b/packages/types/src/user.ts @@ -156,6 +156,7 @@ export type UpdateApiPayload = { video?: null; bio?: string | null; about?: string | null; + price?: number | null; phone?: string | null; city?: City | null; studioId?: number | null; diff --git a/packages/utils/src/lesson.ts b/packages/utils/src/lesson.ts index a308f7b03..4dd2f27ef 100644 --- a/packages/utils/src/lesson.ts +++ b/packages/utils/src/lesson.ts @@ -1,4 +1,4 @@ -import { ILesson } from "@litespace/types"; +import { ILesson, ITutor } from "@litespace/types"; import { MINUTES_IN_HOUR, TOTAL_LESSON_HOURLY_RATE } from "@/constants"; import { sumBy } from "lodash"; @@ -6,8 +6,13 @@ import { sumBy } from "lodash"; * @param duration {ILesson.Duration} * @returns scaled lesson price */ -export function calculateLessonPrice(duration: ILesson.Duration): number { - return Math.floor((duration / MINUTES_IN_HOUR) * TOTAL_LESSON_HOURLY_RATE); +export function calculateLessonPrice( + duration: ILesson.Duration, + tutor?: ITutor.Self +): number { + return Math.floor( + (duration / MINUTES_IN_HOUR) * (tutor?.price ?? TOTAL_LESSON_HOURLY_RATE) + ); } export function sumLessonsDuration(lessons: ILesson.Self[]): number { diff --git a/services/server/src/handlers/user.ts b/services/server/src/handlers/user.ts index 7842e18d6..ac6c58198 100644 --- a/services/server/src/handlers/user.ts +++ b/services/server/src/handlers/user.ts @@ -276,6 +276,7 @@ function update(_: ApiContext) { video, bio, about, + price, notice, studioId, phone, @@ -382,6 +383,7 @@ function update(_: ApiContext) { const updateTutorPayload: ITutor.UpdatePayload = { bio, about, + price, notice, studioId, video, diff --git a/services/server/src/lib/lesson.ts b/services/server/src/lib/lesson.ts index b98d5a68c..24c830fe6 100644 --- a/services/server/src/lib/lesson.ts +++ b/services/server/src/lib/lesson.ts @@ -374,10 +374,13 @@ export async function createLesson({ slotId, start, duration, + price, }); if (tutor instanceof Error) return tutor; - const price = isTutorManager(tutor) ? 0 : calculateLessonPrice(duration); + const price = isTutorManager(tutor) + ? 0 + : calculateLessonPrice(duration, tutor.price); // Create the lesson with its associated room if it doesn't exist const roomMembers = [userId, tutorId];