generated from chingu-voyages/voyage-template
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #51 from chingu-voyages/feature/fetch-user-appt
Fetch User's Appointment and Cancel Function
- Loading branch information
Showing
22 changed files
with
541 additions
and
191 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import { Suspense } from "react"; | ||
import { Box, Stack, Typography } from "@mui/material"; | ||
import { getServerSession } from "next-auth"; | ||
import { authOptions } from "@/auth"; | ||
import MyAppointment from "@/components/appointment/MyAppointment"; | ||
|
||
export default async function MyAppointmentView() { | ||
const session = await getServerSession(authOptions); | ||
|
||
if (!session) { | ||
return <p>You must be signed in to make an appointment</p>; | ||
} | ||
|
||
return ( | ||
<Box | ||
sx={{ | ||
width: { xs: 1, sm: 4 / 5, md: 3 / 4, lg: 3 / 5 }, | ||
marginY: { xs: 2, lg: 4 }, | ||
marginX: "auto", | ||
}} | ||
> | ||
<Stack direction="column"> | ||
<Typography | ||
component="h1" | ||
variant="h1" | ||
sx={{ fontSize: { xs: "2rem", sm: "2.5rem", md: "3rem" } }} | ||
> | ||
My Appointments | ||
</Typography> | ||
<Suspense fallback={<p>Loading...</p>}> | ||
<MyAppointment email={session.user.email} /> | ||
</Suspense> | ||
</Stack> | ||
</Box> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
9 changes: 6 additions & 3 deletions
9
client/app/form/page.jsx → client/app/new-appointment/page.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,16 @@ | ||
import Form from "@/components/form/Form"; | ||
import { getServerSession } from "next-auth"; | ||
import { authOptions } from "@/auth"; | ||
import Form from "@/components/form/Form"; | ||
|
||
export default async function FormView() { | ||
const session = await getServerSession(authOptions) | ||
const session = await getServerSession(authOptions); | ||
if (!session) { | ||
return <p>You must be signed in to make an appointment</p>; | ||
} | ||
return ( | ||
<div> | ||
<h1>Form View</h1> | ||
<Form /> | ||
<Form email={session.user.email} /> | ||
</div> | ||
); | ||
} |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
import { | ||
Card, | ||
CardContent, | ||
Divider, | ||
List, | ||
Stack, | ||
Typography, | ||
} from "@mui/material"; | ||
import AppointmentListItem from "./AppointmentListItem"; | ||
import CancelAppointment from "./CancelAppointment"; | ||
|
||
function convertHourTo12HourTime(hour) { | ||
const period = hour >= 12 ? "PM" : "AM"; | ||
const formattedHour = hour % 12 || 12; | ||
return `${formattedHour}:00 ${period}`; | ||
} | ||
|
||
export default function AppointmentDetails({ formData }) { | ||
const { | ||
name, | ||
email, | ||
phone, | ||
address, | ||
status, | ||
date, | ||
timeRange: { earlyTimeHour, lateTimeHour }, | ||
} = formData; | ||
const earlyTime = convertHourTo12HourTime(earlyTimeHour); | ||
const lateTime = convertHourTo12HourTime(lateTimeHour); | ||
const preferredTime = `${earlyTime} - ${lateTime}`; | ||
const showCancelBtn = status === "Pending" || status === "Confirmed"; | ||
|
||
return ( | ||
<Card sx={{ mt: 4, padding: 2 }}> | ||
<CardContent> | ||
<Stack gap={2}> | ||
<Typography | ||
component="h2" | ||
variant="h1" | ||
sx={{ fontSize: { xs: "1.2rem", lg: "1.5rem" } }} | ||
> | ||
Appointment Details | ||
</Typography> | ||
<Divider orientation="horizontal" /> | ||
</Stack> | ||
<List sx={{ marginY: 2 }}> | ||
<Stack gap={4}> | ||
<Stack gap={1}> | ||
<Typography | ||
variant="subtitle2" | ||
sx={{ fontSize: { xs: "0.9rem", lg: "1rem" } }} | ||
> | ||
Contact Info | ||
</Typography> | ||
<Stack gap={1 / 2}> | ||
<AppointmentListItem label="Name" value={name} /> | ||
<AppointmentListItem label="Email" value={email} /> | ||
<AppointmentListItem label="Phone" value={phone} /> | ||
</Stack> | ||
</Stack> | ||
<Stack gap={1}> | ||
<Typography | ||
variant="subtitle2" | ||
sx={{ fontSize: { xs: "0.9rem", lg: "1rem" } }} | ||
> | ||
Address | ||
</Typography> | ||
<Stack gap={1 / 2}> | ||
<AppointmentListItem value={address} /> | ||
</Stack> | ||
</Stack> | ||
<Stack gap={1}> | ||
<Typography | ||
variant="subtitle2" | ||
sx={{ fontSize: { xs: "0.9rem", lg: "1rem" } }} | ||
> | ||
Scheduling | ||
</Typography> | ||
<Stack gap={1 / 2}> | ||
<AppointmentListItem label="Status" value={status} /> | ||
<AppointmentListItem label="Date" value={date || "N/A"} /> | ||
<AppointmentListItem | ||
label="Preferred Time" | ||
value={preferredTime} | ||
/> | ||
</Stack> | ||
</Stack> | ||
</Stack> | ||
</List> | ||
</CardContent> | ||
{showCancelBtn && <CancelAppointment email={email} />} | ||
</Card> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { ListItem, Typography } from "@mui/material"; | ||
|
||
export default function ({ label, value }) { | ||
return ( | ||
<ListItem disablePadding> | ||
<Typography sx={{ fontSize: { xs: "0.9rem", lg: "1rem" } }}> | ||
{label ? `${label}:` : ""} {value} | ||
</Typography> | ||
</ListItem> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
"use client"; | ||
import { useState } from "react"; | ||
import { Box, Button, Modal, Stack, Typography } from "@mui/material"; | ||
import { cancelAppointment } from "@/actions/form"; | ||
import ErrorToast from "../errors/ErrorToast"; | ||
|
||
export default function CancelAppointment({ email }) { | ||
// state | ||
const [modal, setModal] = useState(false); | ||
const [toast, setToast] = useState(false); | ||
const [toastMsg, setToastMsg] = useState(""); | ||
|
||
const handleConfirm = async () => { | ||
const err = await cancelAppointment(email); | ||
if (err) { | ||
setToast(true); | ||
setToastMsg(err.message); | ||
} | ||
setModal(false); | ||
}; | ||
|
||
return ( | ||
<> | ||
{/* ERROR TOAST */} | ||
<ErrorToast | ||
toast={toast} | ||
setToast={setToast} | ||
toastMsg={toastMsg} | ||
setToastMsg={setToastMsg} | ||
/> | ||
|
||
{/* CONFIRMATION MODAL */} | ||
<Modal open={modal} onClose={() => setModal(false)}> | ||
<Box | ||
sx={{ | ||
position: "absolute", | ||
top: "50%", | ||
left: "50%", | ||
transform: "translate(-50%, -50%)", | ||
width: { xs: 9 / 10, sm: 500 }, | ||
bgcolor: "background.paper", | ||
boxShadow: 10, | ||
borderRadius: 2, | ||
p: 4, | ||
}} | ||
> | ||
<Typography> | ||
Are you sure you want to cancel your appointment? | ||
</Typography> | ||
<Stack | ||
gap={2} | ||
direction={{ xs: "column", sm: "row" }} | ||
sx={{ marginTop: 4 }} | ||
> | ||
<Button | ||
variant="outlined" | ||
color="warning" | ||
sx={{ width: { xs: 1, sm: 1 / 2 } }} | ||
onClick={() => setModal(false)} | ||
> | ||
Cancel | ||
</Button> | ||
<Button | ||
variant="contained" | ||
sx={{ width: { xs: 1, sm: 1 / 2 } }} | ||
onClick={handleConfirm} | ||
> | ||
Confirm | ||
</Button> | ||
</Stack> | ||
</Box> | ||
</Modal> | ||
|
||
{/* CANCEL BUTTON */} | ||
<Box> | ||
<Button | ||
variant="outlined" | ||
color="warning" | ||
onClick={() => setModal(true)} | ||
> | ||
Cancel Appointment | ||
</Button> | ||
</Box> | ||
</> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { fetchSingleAppointment } from "@/actions/form"; | ||
import NoAppointment from "./NoAppointment"; | ||
import AppointmentDetails from "./AppointmentDetails"; | ||
|
||
export default async function MyAppointment({ email }) { | ||
const fetchResponse = await fetchSingleAppointment(email); | ||
if (!fetchResponse) { | ||
return <NoAppointment />; | ||
} | ||
return <AppointmentDetails formData={fetchResponse} />; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
"use client"; | ||
import { redirect } from "next/navigation"; | ||
import { Button } from "@mui/material"; | ||
|
||
export default function NewAppointment() { | ||
function handleClick() { | ||
redirect("/new-appointment"); | ||
} | ||
return ( | ||
<Button onClick={handleClick} sx={{ width: "fit-content" }}> | ||
+ New Appointment | ||
</Button> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { Box, Stack, Typography } from "@mui/material"; | ||
import NewAppointment from "./NewAppointment"; | ||
|
||
export default function NoAppointment() { | ||
return ( | ||
<Stack gap={4} sx={{ marginY: { xs: 4, lg: 6 } }}> | ||
<Typography component="p" variant="body1" fontStyle="italic"> | ||
You haven't scheduled any appointments. | ||
</Typography> | ||
<NewAppointment /> | ||
</Stack> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { Alert, Snackbar } from "@mui/material"; | ||
|
||
export default function ErrorToast({ toast, toastMsg, setToast, setToastMsg }) { | ||
const handleToastClose = () => { | ||
setToast(false); | ||
setToastMsg(""); | ||
}; | ||
|
||
return ( | ||
<Snackbar | ||
open={toast} | ||
autoHideDuration={6000} | ||
onClose={handleToastClose} | ||
anchorOrigin={{ vertical: "bottom", horizontal: "right" }} | ||
> | ||
<Alert | ||
onClose={handleToastClose} | ||
severity="error" | ||
variant="filled" | ||
sx={{ width: "100%" }} | ||
> | ||
{toastMsg} | ||
</Alert> | ||
</Snackbar> | ||
); | ||
} |
Oops, something went wrong.