Skip to content

Commit

Permalink
tallied both render calendar and pricing toggle
Browse files Browse the repository at this point in the history
  • Loading branch information
teetangh committed Dec 11, 2024
1 parent 1abe0e2 commit 02f2398
Show file tree
Hide file tree
Showing 8 changed files with 104 additions and 67 deletions.
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import React, { useEffect, useState } from "react";
import { useToast } from "@/components/ui/use-toast";
import { Card, CardContent } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Card, CardContent } from "@/components/ui/card";
import { ClassPlan, WebinarPlan } from "@prisma/client";
import { CalendarIcon, ClockIcon } from "lucide-react";
import { Class, Webinar, ClassPlan, WebinarPlan } from "@prisma/client";
import React from "react";

interface ClassesAndWebinarsProps {
classPlans: ClassPlan[];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const ConsultantSkeletonLoader: React.FC = () => {
let dotIndex = 0;

const interval = setInterval(() => {
setLoadingText((prevText) => {
setLoadingText(() => {
const baseText = "Please wait while we are fetching consultant details";
return `${baseText}${dots[dotIndex]}`;
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,16 @@ import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
DialogTrigger
} from "@/components/ui/dialog";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { motion } from "framer-motion";
import { ClockIcon, X } from "lucide-react";
import { ClockIcon } from "lucide-react";
import { useSession } from "next-auth/react";
import { useState, useMemo } from "react";
import { PricingOption, defaultConsultationOptions, defaultSubscriptionOptions } from "./defaults";
import { useMemo, useState } from "react";
import { PricingOption, defaultConsultationOptions, defaultSubscriptionOptions } from "../defaults";

interface PricingToggleProps {
consultationOptions?: PricingOption[];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,18 @@ interface WeeklyAvailabilityProps {
selectedSlotId?: string;
}

function convertUTCToLocal(date: Date): Date {
const offset = date.getTimezoneOffset();
return new Date(date.getTime() - (offset * 60 * 1000));
}

const formatTime = (isoString: string): string => {
try {
// Extract hours and minutes from the ISO string
const date = new Date(isoString);
if (isNaN(date.getTime())) {
throw new Error("Invalid date");
}
return date.toLocaleTimeString([], {
// Convert UTC time to local time
const utcDate = new Date(isoString);
const localDate = convertUTCToLocal(utcDate);

return localDate.toLocaleTimeString([], {
hour: "2-digit",
minute: "2-digit",
hour12: true,
Expand Down
134 changes: 83 additions & 51 deletions app/explore/experts/[consultantId]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,20 @@ import { TSlotTiming } from "@/types/slots";
import {
ConsultantReview,
ConsultationPlan,
DayOfWeek,
SubscriptionPlan,
User,
} from "@prisma/client";
import { StarIcon } from "lucide-react";
import Image from "next/image";
import Link from "next/link";
import { use, useCallback, useEffect, useMemo, useState } from "react";
import { ClassesAndWebinars } from "./ClassesAndWebinars";
import { ConsultantSkeletonLoader } from "./ConsultantSkeletonLoader";
import { CustomAvailability } from "./CustomAvailability";
import PricingToggle from "./PricingToggle";
import Review from "./Review";
import { WeeklyAvailability } from "./WeeklyAvailability";
import { ClassesAndWebinars } from "./components/ClassesAndWebinars";
import { ConsultantSkeletonLoader } from "./components/ConsultantSkeletonLoader";
import { CustomAvailability } from "./components/CustomAvailability";
import PricingToggle from "./components/PricingToggle";
import Review from "./components/Review";
import { WeeklyAvailability } from "./components/WeeklyAvailability";

interface PricingOption {
title: string;
Expand All @@ -39,6 +40,21 @@ interface PricingOption {
type Params = Promise<{ consultantId: string }>;
type SearchParams = Promise<{ [key: string]: string | string[] | undefined }>;

const dayMap: Record<number, DayOfWeek> = {
0: DayOfWeek.SUNDAY,
1: DayOfWeek.MONDAY,
2: DayOfWeek.TUESDAY,
3: DayOfWeek.WEDNESDAY,
4: DayOfWeek.THURSDAY,
5: DayOfWeek.FRIDAY,
6: DayOfWeek.SATURDAY
};

function convertUTCToLocal(date: Date): Date {
const offset = date.getTimezoneOffset();
return new Date(date.getTime() - (offset * 60 * 1000));
}

export default function ExpertProfile(
props: Readonly<{
params: Params;
Expand Down Expand Up @@ -69,7 +85,6 @@ export default function ExpertProfile(
params.consultantId,
);
setConsultantDetails(consultantData);
console.log(consultantData);
if (consultantData.userId) {
const userData = await fetchUserDetails(consultantData.userId);
setUserDetails(userData);
Expand Down Expand Up @@ -103,28 +118,51 @@ export default function ExpertProfile(
// For weekly schedule, use the slots directly from consultantDetails
const weeklySlots = consultantDetails.slotsOfAvailabilityWeekly.map(
(slot) => {
// Extract time from the ISO string and ensure it's a string
const startTimeStr =
typeof slot.slotStartTimeInUTC === "string"
? slot.slotStartTimeInUTC
: new Date(slot.slotStartTimeInUTC).toISOString();
const endTimeStr =
typeof slot.slotEndTimeInUTC === "string"
? slot.slotEndTimeInUTC
: new Date(slot.slotEndTimeInUTC).toISOString();
// Get the selected date's day
const selectedDay = dayMap[selectedDate.getDay()];

// Only map slots for the selected day
if (slot.dayOfWeekforStartTimeInUTC !== selectedDay) {
return null;
}

// Create a new date object for the selected date
const slotDate = new Date(selectedDate);

// Parse hours and minutes from the UTC time
const startTime = new Date(slot.slotStartTimeInUTC);
const endTime = new Date(slot.slotEndTimeInUTC);

// Convert UTC times to local times
const localStartTime = convertUTCToLocal(startTime);
const localEndTime = convertUTCToLocal(endTime);

// Set the hours and minutes on the selected date
const startDateTime = new Date(slotDate);
startDateTime.setHours(localStartTime.getHours(), localStartTime.getMinutes(), 0, 0);

const endDateTime = new Date(slotDate);
endDateTime.setHours(localEndTime.getHours(), localEndTime.getMinutes(), 0, 0);

// If the slot crosses midnight, adjust the end date
if (endDateTime < startDateTime) {
endDateTime.setDate(endDateTime.getDate() + 1);
}

return {
slotId: slot.id,
dateInISO: selectedDate.toISOString(),
slotStartTimeInUTC: startTimeStr,
slotEndTimeInUTC: endTimeStr,
dayOfWeek: slot.dayOfWeekforStartTimeInUTC,
slotStartTimeInUTC: startDateTime.toISOString(),
slotEndTimeInUTC: endDateTime.toISOString(),
slotOfAvailabilityId: slot.id,
slotOfAppointmentId: "",
localStartTime: startTimeStr,
localEndTime: endTimeStr,
localStartTime: startDateTime.toLocaleTimeString(),
localEndTime: endDateTime.toLocaleTimeString(),
};
},
);
).filter((slot): slot is TSlotTiming => slot !== null);

setSlotTimings(weeklySlots);
} else if (consultantDetails.scheduleType === "CUSTOM") {
// For custom schedule, use the custom slots from consultantDetails
Expand All @@ -137,28 +175,23 @@ export default function ExpertProfile(
);
return slotDate.toDateString() === selectedDate.toDateString();
})
.map((slot) => ({
slotId: slot.id,
dateInISO: selectedDate.toISOString(),
slotStartTimeInUTC:
typeof slot.slotStartTimeInUTC === "string"
? slot.slotStartTimeInUTC
: new Date(slot.slotStartTimeInUTC).toISOString(),
slotEndTimeInUTC:
typeof slot.slotEndTimeInUTC === "string"
? slot.slotEndTimeInUTC
: new Date(slot.slotEndTimeInUTC).toISOString(),
slotOfAvailabilityId: slot.id,
slotOfAppointmentId: "",
localStartTime:
typeof slot.slotStartTimeInUTC === "string"
? slot.slotStartTimeInUTC
: new Date(slot.slotStartTimeInUTC).toISOString(),
localEndTime:
typeof slot.slotEndTimeInUTC === "string"
? slot.slotEndTimeInUTC
: new Date(slot.slotEndTimeInUTC).toISOString(),
}));
.map((slot) => {
const startDateTime = convertUTCToLocal(new Date(slot.slotStartTimeInUTC));
const endDateTime = convertUTCToLocal(new Date(slot.slotEndTimeInUTC));

return {
slotId: slot.id,
dateInISO: selectedDate.toISOString(),
dayOfWeek: dayMap[startDateTime.getDay()],
slotStartTimeInUTC: startDateTime.toISOString(),
slotEndTimeInUTC: endDateTime.toISOString(),
slotOfAvailabilityId: slot.id,
slotOfAppointmentId: "",
localStartTime: startDateTime.toLocaleTimeString(),
localEndTime: endDateTime.toLocaleTimeString(),
};
});

setSlotTimings(customSlots);
}
}
Expand Down Expand Up @@ -264,16 +297,13 @@ export default function ExpertProfile(
setSelectedSlot({
slotId: slot.id,
dateInISO: new Date().toISOString(),
dayOfWeek: slot.dayOfWeekforStartTimeInUTC,
slotStartTimeInUTC: slot.slotStartTimeInUTC,
slotEndTimeInUTC: slot.slotEndTimeInUTC,
slotOfAvailabilityId: slot.id,
slotOfAppointmentId: "",
localStartTime: new Date(
`1970-01-01T${slot.slotStartTimeInUTC}`,
).toISOString(),
localEndTime: new Date(
`1970-01-01T${slot.slotEndTimeInUTC}`,
).toISOString(),
localStartTime: new Date(slot.slotStartTimeInUTC).toLocaleTimeString(),
localEndTime: new Date(slot.slotEndTimeInUTC).toLocaleTimeString(),
})
}
selectedSlotId={selectedSlot?.slotId}
Expand Down Expand Up @@ -302,12 +332,13 @@ export default function ExpertProfile(
setSelectedSlot({
slotId: slot.id,
dateInISO: new Date(slot.slotStartTimeInUTC).toISOString(),
dayOfWeek: dayMap[new Date(slot.slotStartTimeInUTC).getDay()],
slotStartTimeInUTC: slot.slotStartTimeInUTC,
slotEndTimeInUTC: slot.slotEndTimeInUTC,
slotOfAvailabilityId: slot.id,
slotOfAppointmentId: "",
localStartTime: new Date(slot.slotStartTimeInUTC).toISOString(),
localEndTime: new Date(slot.slotEndTimeInUTC).toISOString(),
localStartTime: new Date(slot.slotStartTimeInUTC).toLocaleTimeString(),
localEndTime: new Date(slot.slotEndTimeInUTC).toLocaleTimeString(),
})
}
selectedSlotId={selectedSlot?.slotId}
Expand All @@ -316,6 +347,7 @@ export default function ExpertProfile(
}
return null;
}, [consultantDetails, selectedSlot]);

const isConsultationPlan = (
plan: ConsultationPlan | SubscriptionPlan,
): plan is ConsultationPlan => {
Expand Down
3 changes: 3 additions & 0 deletions types/slots.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { DayOfWeek } from "@prisma/client";

export type TSlotTiming = {
slotId: string;
dateInISO: string;
dayOfWeek: DayOfWeek;
slotStartTimeInUTC: string;
slotEndTimeInUTC: string;
slotOfAvailabilityId: string;
Expand Down

0 comments on commit 02f2398

Please sign in to comment.