Skip to content

Commit

Permalink
Merge pull request #21 from tnamdevnote/chore/use-datetime
Browse files Browse the repository at this point in the history
Chore/timevalue->datetime
  • Loading branch information
tnamdevnote authored May 7, 2024
2 parents 37e9220 + 7460924 commit 04aeb2c
Show file tree
Hide file tree
Showing 8 changed files with 41 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { mutate } from "swr";
import AppointmentTimeslots from "./appointmentTimeslots";

interface AppointmentDateTimePickerProps {
availableDates: string[];
availableDates?: string[];
}

function AppointmentDateTimePicker({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { Badge } from "@/components/atoms/badge";
import { FormControl } from "@/components/molecules/form";
import { TimeslotSchema } from "@/lib/formSchema";
import { formatToDisplayTime } from "@/lib/utils";
import { format } from "date-fns";
import { useState } from "react";
import { useController } from "react-hook-form";
import useSWR from "swr";
Expand All @@ -27,7 +29,6 @@ function AppointmentTimeslots({ currentDate }: AppointmentTimeslotsProps) {
e: React.SyntheticEvent<HTMLDivElement>,
timeslot: z.infer<typeof TimeslotSchema>,
) => {
// getValues('timeslot').id
field.onChange(timeslot);
if (selected !== timeslot.id) {
return setSelected(timeslot.id);
Expand All @@ -52,7 +53,7 @@ function AppointmentTimeslots({ currentDate }: AppointmentTimeslotsProps) {
className="shrink flex-grow-0"
key={timeslot.id}
selected={selected === timeslot.id}
label={timeslot.time}
label={formatToDisplayTime(timeslot.time)}
onClick={(e) => handleSelect(e, timeslot)}
/>
))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
} from "@/components/molecules/form";
import { useToast } from "@/components/molecules/toast";
import { FormSchema } from "@/lib/formSchema";
import { cn } from "@/lib/utils";
import { cn, formatToDisplayDate, formatToDisplayTime } from "@/lib/utils";
import AppointmentDateTimePicker from "../appointmentDateTimePicker/appointmentDateTimePicker";

/**
Expand All @@ -42,10 +42,10 @@ async function sendEmail(formValues: z.infer<typeof FormSchema>) {
const res = await fetch("/api/email", {
method: "POST",
headers: { "Content-type": "application/json" },
// This is a mock data. Replace with proper form values later.

body: JSON.stringify({
date: new Date(timeslot.date).toUTCString().slice(0, 16),
time: format(new Date(`${timeslot.date} ${timeslot.time}`), "p"),
date: formatToDisplayDate(timeslot.date),
time: formatToDisplayTime(timeslot.time),
location,
comment,
}),
Expand All @@ -71,8 +71,6 @@ interface AppointmentFormProps {
onClose?: () => void;
}

const AVAILABLE_DATES = ["2024-05-06", "2024-05-02", "2024-05-13"];

/**
* A client side form component that handles both creating and editing appointments.
*/
Expand Down Expand Up @@ -143,9 +141,7 @@ export const AppointmentForm = ({
<FormLabel className="sr-only">
Pick your appointment date
</FormLabel>
<AppointmentDateTimePicker
availableDates={AVAILABLE_DATES}
/>
<AppointmentDateTimePicker />
<FormDescription />
<FormMessage />
</FormItem>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import CancelDialog from "../cancelDialog/cancelDialog";
import { getKindeServerSession } from "@kinde-oss/kinde-auth-nextjs/server";
import { getAppointments } from "@/lib/sanity/client";
import { format } from "date-fns";
import { formatToDisplayDate, formatToDisplayTime } from "@/lib/utils";

export default async function UpcomingAppointments() {
const { getUser } = getKindeServerSession();
Expand All @@ -33,11 +34,11 @@ export default async function UpcomingAppointments() {
<CardContent className="flex flex-col gap-4">
<p className="inline-flex gap-2 text-base font-bold">
<CalendarIcon />
{new Date(date).toUTCString().slice(0, 16)}
{formatToDisplayDate(date)}
</p>
<p className="inline-flex gap-2 text-base font-bold">
<ClockIcon />
{format(new Date(`${date} ${time}`), "p")}
{formatToDisplayTime(time)}
</p>
<p className="text-sm">
{[address1, address2, city, state, zipCode]
Expand Down
4 changes: 2 additions & 2 deletions app/api/timeslots/[date]/route.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getAvailableTimeSlot } from "@/lib/sanity/client";
import { getAvailableTimeSlots } from "@/lib/sanity/client";
import { formatISO } from "date-fns";
import { NextRequest } from "next/server";

Expand All @@ -12,6 +12,6 @@ export async function GET(
representation: "date",
});

const res = await getAvailableTimeSlot(formattedDate);
const res = await getAvailableTimeSlots(formattedDate);
return Response.json(res, { status: 200 });
}
19 changes: 10 additions & 9 deletions lib/sanity/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,16 +46,17 @@ export const getAvailableDate = async () => {
return Object.keys(distinctDates);
};

export const getAvailableTimeSlot = async (date: string) => {
export const getAvailableTimeSlots = async (date: string) => {
const timeSlots = await client.fetch(
`*[_type=='timeslot'
&& date=='${date}'
&& !(_id in *[_type=='appointment'].timeslot._ref)
]{
"id": _id,
date,
"time": duration.start
}`,
&& date == '${date}'
&& dateTime(time) >= dateTime(now())
]{
"id": _id,
date,
time,
}`,
{},
{ cache: "no-store" },
);
Expand All @@ -79,12 +80,12 @@ export const getAppointments = async (userId = "") => {
const res = await client.fetch<APPOINTMENT_QUERYResult>(
`*[_type=='appointment'
&& customer->_id == '${userId}'
&& timeslot->date >= now()
&& dateTime(timeslot->time) >= dateTime(now())
]{
"id":_id,
"timeslotId":timeslot->_id,
"date":timeslot->date,
"time":timeslot->duration.start,
"time":timeslot->time,
address1,
address2,
city,
Expand Down
7 changes: 4 additions & 3 deletions lib/sanity/sanity.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -262,18 +262,19 @@ export type AVAILABLE_DATE_QUERYResult = Array<{
id: string;
date: string;
}>;
// Source: ./groq/groq.ts
// Variable: AVAILABLE_TIMESLOT_QUERY
// Query: *[_type=='timeslot' && date=='' && !(_id in *[_type=='appointment'].timeslot._ref)]{ "id": _id, date, "startTime": duration.start}
// Query: *[_type=='timeslot' && !(_id in *[_type=='appointment'].timeslot._ref) && date == '' && dateTime(timeslot) >= dateTime(now())]{ "id": _id, date, timeslot,}
export type AVAILABLE_TIMESLOT_QUERYResult = Array<{
id: string;
date: string;
time: string;
timeslot: string;
}>;
// Variable: IS_TIMESLOT_RESERVED_QUERY
// Query: count(*[_type=='appointment' && references('') ]) > 0
export type IS_TIMESLOT_RESERVED_QUERYResult = unknown;
// Variable: APPOINTMENT_QUERY
// Query: *[_type=='appointment' && customer->_id == '']{ "id":_id, "timeslotId":timeslot->_id, "date":timeslot->date, "time":timeslot->duration.start, address1, address2, city, state, zipCode, comment, customer->{"id": _id, firstName, lastName}, stylist->{"id": _id, firstName, lastName}}
// Query: *[_type=='appointment' && customer->_id == '' && dateTime(timeslot->timeslot) >= dateTime(now())]{ "id":_id, "timeslotId":timeslot->_id, "date":timeslot->date, "time":timeslot->timeslot, address1, address2, city, state, zipCode, comment, customer->{"id": _id, firstName, lastName}, stylist->{"id": _id, firstName, lastName}}
export type APPOINTMENT_QUERYResult = Array<{
id: string;
timeslotId: string;
Expand Down
18 changes: 13 additions & 5 deletions lib/utils.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
import { type ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";
import { get, set, ref, child } from "firebase/database";
import { format } from "date-fns";

export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}

export function dateTimeToUnixTimeStamp(date: string, time: string) {
const combinedDateTimeString = date + "T" + time;
const dateTime = new Date(combinedDateTimeString);
const unixTimeStamp = dateTime.getTime() / 1000;
return unixTimeStamp;
/** Convert incoming date string to UTC format. This only returns date portion. */
export function formatToDisplayDate(date: string): string {
const res = new Date(date).toUTCString().slice(0, 16);

return res;
}

/** Convert incoming date string to HH:mm AM/PM format*/
export function formatToDisplayTime(time: string): string {
const res = format(new Date(`${time}`), "p");

return res;
}

export function unixToDateTimeStrings(unixTimeStamp: number) {
Expand Down

0 comments on commit 04aeb2c

Please sign in to comment.