adrianhajdin / healthcare

Build a healthcare platform that streamlines patient registration, appointment scheduling, and medical records, and learn to implement complex forms and SMS notifications.
https://jsmastery.pro
1.81k stars 432 forks source link

Runtime error : appointment.patient is null #27

Closed Elbanteny closed 1 month ago

Elbanteny commented 1 month ago

Screenshot from 2024-07-18 22-26-12

Screenshot from 2024-07-18 22-31-11

This my columns.tsx code

"use client";

import { ColumnDef } from "@tanstack/react-table";
import Image from "next/image";

import { Doctors } from "@/constants";
import { formatDateTime } from "@/lib/utils";
import { Appointment } from "@/types/appwrite.types";

import { AppointmentModal } from "../AppointmentModal";
import { StatusBadge } from "../StatusBadge";

export const columns: ColumnDef<Appointment>[] = [
    {
        header: "#",
        cell: ({ row }) => {
            return <p className="text-14-medium ">{row.index + 1}</p>;
        },
    },
    {
        accessorKey: "patient",
        header: "Patient",
        cell: ({ row }) => {
            const appointment = row.original;
            return <p className="text-14-medium ">{appointment.patient.name}</p>;
        },
    },
    {
        accessorKey: "status",
        header: "Status",
        cell: ({ row }) => {
            const appointment = row.original;
            return (
                <div className="min-w-[115px]">
                    <StatusBadge status={appointment.status} />
                </div>
            );
        },
    },
    {
        accessorKey: "schedule",
        header: "Appointment",
        cell: ({ row }) => {
            const appointment = row.original;
            return (
                <p className="text-14-regular min-w-[100px]">
                    {formatDateTime(appointment.schedule).dateTime}
                </p>
            );
        },
    },
    {
        accessorKey: "primaryPhysician",
        header: "Doctor",
        cell: ({ row }) => {
            const appointment = row.original;

            const doctor = Doctors.find(
                (doctor) => doctor.name === appointment.primaryPhysician
            );

            return (
                <div className="flex items-center gap-3">
                    <Image
                        src={doctor?.image!}
                        alt="doctor"
                        width={100}
                        height={100}
                        className="size-8"
                    />
                    <p className="whitespace-nowrap">Dr. {doctor?.name}</p>
                </div>
            );
        },
    },
    {
        id: "actions",
        header: () => <div className="pl-4">Actions</div>,
        cell: ({ row }) => {
            const appointment = row.original;

            return (
                <div className="flex gap-1">
                    <AppointmentModal
                        patientId={appointment.patient.$id}
                        userId={appointment.userId}
                        appointment={appointment}
                        type="schedule"
                        title="Schedule Appointment"
                        description="Please confirm the following details to schedule."
                    />
                    <AppointmentModal
                        patientId={appointment.patient.$id}
                        userId={appointment.userId}
                        appointment={appointment}
                        type="cancel"
                        title="Cancel Appointment"
                        description="Are you sure you want to cancel your appointment?"
                    />
                </div>
            );
        },
    },
];

this my page.tsx in admin folder code:

import Image from "next/image";
import Link from "next/link";

import { StatCard } from "@/components/StatCard";
import { columns } from "@/components/table/columns";
import { DataTable } from "@/components/table/DataTable";
import { getRecentAppointmentList } from "@/lib/actions/appointment.actions";

const AdminPage = async () => {
    const appointments = await getRecentAppointmentList();

    return (
        <div className="mx-auto flex max-w-7xl flex-col space-y-14">
            <header className="admin-header">
                <Link href="/" className="cursor-pointer">
                    <Image
                        src="/assets/icons/logo-full.svg"
                        height={32}
                        width={162}
                        alt="logo"
                        className="h-8 w-fit"
                    />
                </Link>

                <p className="text-16-semibold">Admin Dashboard</p>
            </header>

            <main className="admin-main">
                <section className="w-full space-y-4">
                    <h1 className="header">Welcome đź‘‹</h1>
                    <p className="text-dark-700">
                        Start the day with managing new appointments
                    </p>
                </section>

                <section className="admin-stat">
                    <StatCard
                        type="appointments"
                        count={appointments.scheduledCount}
                        label="Scheduled appointments"
                        icon={"/assets/icons/appointments.svg"}
                    />
                    <StatCard
                        type="pending"
                        count={appointments.pendingCount}
                        label="Pending appointments"
                        icon={"/assets/icons/pending.svg"}
                    />
                    <StatCard
                        type="cancelled"
                        count={appointments.cancelledCount}
                        label="Cancelled appointments"
                        icon={"/assets/icons/cancelled.svg"}
                    />
                </section>

                <DataTable columns={columns} data={appointments.documents} />
            </main>
        </div>
    );
};

export default AdminPage;
KyleMacklane commented 1 month ago

To handle the error where patient.name is null, you can add a null check before accessing the name property. This way, if patient is null or undefined, your code will not throw an error. To also handle the possibility that appointment.patient may be null or undefined when rendering the AppointmentModal, you can add a conditional check to ensure that appointment.patient exists before attempting to access its properties. Here's the whole modified code

`"use client";

import { ColumnDef } from "@tanstack/react-table"; import Image from "next/image";

import { Doctors } from "@/constants"; import { formatDateTime } from "@/lib/utils"; import { Appointment } from "@/types/appwrite.types";

import { AppointmentModal } from "../AppointmentModal"; import { StatusBadge } from "../StatusBadge";

export const columns: ColumnDef[] = [ { header: "#", cell: ({ row }) => { return

{row.index + 1}

; }, }, { accessorKey: "patient", header: "Patient", cell: ({ row }) => { const appointment = row.original; const patientName = appointment.patient?.name ?? "Unknown Patient"; return

{patientName}

; }, }, { accessorKey: "status", header: "Status", cell: ({ row }) => { const appointment = row.original; return (

  );
},

}, { accessorKey: "schedule", header: "Appointment", cell: ({ row }) => { const appointment = row.original; return (

{formatDateTime(appointment.schedule).dateTime}

  );
},

}, { accessorKey: "primaryPhysician", header: "Doctor", cell: ({ row }) => { const appointment = row.original;

  const doctor = Doctors.find(
    (doctor) => doctor.name === appointment.primaryPhysician
  );

  return (
    <div className="flex items-center gap-3">
      <Image
        src={doctor?.image!}
        alt="doctor"
        width={100}
        height={100}
        className="size-8"
      />
      <p className="whitespace-nowrap">Dr. {doctor?.name}</p>
    </div>
  );
},

}, { id: "actions", header: () =>

Actions
, cell: ({ row }) => { const appointment = row.original;

  return (
    <div className="flex gap-1">
      {appointment.patient ?(
        <>
      <AppointmentModal
      patientId={appointment.patient.$id}
      userId={appointment.userId}
      appointment={appointment}
      type="schedule"
      title="Schedule Appointment"
      description="Please confirm the following details to schedule."
    />

    <AppointmentModal
      patientId={appointment.patient.$id}
      userId={appointment.userId}
      appointment={appointment}
      type="cancel"
      title="Cancel Appointment"
      description="Are you sure you want to cancel your appointment?"
    />
    </>
      ): (
        <p className="text-14-medium">No patient info</p>
      )

      }

    </div>
  );
},

}, ];`

Changes Made: Patient Column: Added a null check for appointment.patient?.name.

Doctor Column: Added a check to handle cases where the doctor might not be found (doctor ? ... : ...).

Actions Column: Added a check to ensure appointment.patient exists before rendering the AppointmentModal components. These changes will ensure that your code handles cases where some data might be missing, preventing runtime errors.

Elbanteny commented 1 month ago

Thanks sir, its solved!

Elbanteny commented 1 month ago

I just found out, why patient.name is null, the relationship in the database between appointment and patient does not seem to work properly, I have to defined it manually.

![Uploading Screenshot from 2024-07-23 21-55-36.png…]()