frontend tailwind half working without external styling

This commit is contained in:
2025-05-09 21:51:02 +05:30
parent ae99e25228
commit 9a431e63db
42 changed files with 1112 additions and 273 deletions

View File

@@ -1,7 +1,28 @@
import { useState } from "react";
import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog";
import { AppointmentForm } from "./appointment-form";
import { Appointment, InsertAppointment, UpdateAppointment, Patient } from "@shared/schema";
// import { Appointment, InsertAppointment, UpdateAppointment, Patient } from "@repo/db/shared/schemas";
import { AppointmentUncheckedCreateInputObjectSchema, PatientUncheckedCreateInputObjectSchema } from "@repo/db/shared/schemas";
import {z} from "zod";
type Appointment = z.infer<typeof AppointmentUncheckedCreateInputObjectSchema>;
const insertAppointmentSchema = (AppointmentUncheckedCreateInputObjectSchema as unknown as z.ZodObject<any>).omit({
id: true,
createdAt: true,
});
type InsertAppointment = z.infer<typeof insertAppointmentSchema>;
const updateAppointmentSchema = (AppointmentUncheckedCreateInputObjectSchema as unknown as z.ZodObject<any>).omit({
id: true,
createdAt: true,
}).partial();
type UpdateAppointment = z.infer<typeof updateAppointmentSchema>;
const PatientSchema = (PatientUncheckedCreateInputObjectSchema as unknown as z.ZodObject<any>).omit({
appointments: true,
});
type Patient = z.infer<typeof PatientSchema>;
interface AddAppointmentModalProps {
open: boolean;

View File

@@ -1,9 +1,30 @@
import { useState, useEffect } from "react";
import { useEffect } from "react";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import { format } from "date-fns";
import { InsertAppointment, UpdateAppointment, Appointment, Patient } from "@shared/schema";
// import { InsertAppointment, UpdateAppointment, Appointment, Patient } from "@repo/db/shared/schemas";
import { AppointmentUncheckedCreateInputObjectSchema, PatientUncheckedCreateInputObjectSchema } from "@repo/db/shared/schemas";
import {z} from "zod";
type Appointment = z.infer<typeof AppointmentUncheckedCreateInputObjectSchema>;
const insertAppointmentSchema = (AppointmentUncheckedCreateInputObjectSchema as unknown as z.ZodObject<any>).omit({
id: true,
createdAt: true,
});
type InsertAppointment = z.infer<typeof insertAppointmentSchema>;
const updateAppointmentSchema = (AppointmentUncheckedCreateInputObjectSchema as unknown as z.ZodObject<any>).omit({
id: true,
createdAt: true,
}).partial();
type UpdateAppointment = z.infer<typeof updateAppointmentSchema>;
const PatientSchema = (PatientUncheckedCreateInputObjectSchema as unknown as z.ZodObject<any>).omit({
appointments: true,
});
type Patient = z.infer<typeof PatientSchema>;
// Define staff members (should match those in appointments-page.tsx)
const staffMembers = [
@@ -36,7 +57,6 @@ import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover
import { CalendarIcon, Clock } from "lucide-react";
import { cn } from "@/lib/utils";
// Create a schema for appointment validation
const appointmentSchema = z.object({
patientId: z.coerce.number().positive(),
title: z.string().optional(),
@@ -52,7 +72,7 @@ const appointmentSchema = z.object({
type: z.string().min(1, "Appointment type is required"),
notes: z.string().optional(),
status: z.string().default("scheduled"),
staff: z.string().default(staffMembers[0].id),
staff: z.string().default(staffMembers?.[0]?.id ?? "default-id"),
});
export type AppointmentFormValues = z.infer<typeof appointmentSchema>;
@@ -96,8 +116,8 @@ export function AppointmentForm({
patientId: appointment.patientId,
title: appointment.title,
date: new Date(appointment.date),
startTime: appointment.startTime.slice(0, 5), // HH:MM from HH:MM:SS
endTime: appointment.endTime.slice(0, 5), // HH:MM from HH:MM:SS
startTime: typeof appointment.startTime === 'string' ? appointment.startTime.slice(0, 5) : "",
endTime: typeof appointment.endTime === 'string' ? appointment.endTime.slice(0, 5) : "",
type: appointment.type,
notes: appointment.notes || "",
status: appointment.status || "scheduled",
@@ -112,7 +132,7 @@ export function AppointmentForm({
type: parsedStoredData.type || "checkup",
status: parsedStoredData.status || "scheduled",
notes: parsedStoredData.notes || "",
staff: parsedStoredData.staff || staffMembers[0].id,
staff: parsedStoredData.staff || (staffMembers?.[0]?.id ?? "default-id")
}
: {
date: new Date(),
@@ -187,7 +207,7 @@ export function AppointmentForm({
// If there's no staff information in the notes, add it
if (!notes.includes('Appointment with')) {
notes = notes ? `${notes}\nAppointment with ${selectedStaff.name}` : `Appointment with ${selectedStaff.name}`;
notes = notes ? `${notes}\nAppointment with ${selectedStaff?.name}` : `Appointment with ${selectedStaff?.name}`;
}
onSubmit({

View File

@@ -1,6 +1,4 @@
import { useState } from "react";
import { format } from "date-fns";
import { Appointment, Patient } from "@shared/schema";
import {
Table,
TableBody,
@@ -11,13 +9,13 @@ import {
} from "@/components/ui/table";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import {
MoreHorizontal,
Edit,
Trash2,
import {
MoreHorizontal,
Edit,
Trash2,
Eye,
Calendar,
Clock
Clock,
} from "lucide-react";
import {
DropdownMenu,
@@ -27,6 +25,21 @@ import {
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
// import { Appointment, Patient } from "@repo/db/shared/schemas";
import {
AppointmentUncheckedCreateInputObjectSchema,
PatientUncheckedCreateInputObjectSchema,
} from "@repo/db/shared/schemas";
import { z } from "zod";
type Appointment = z.infer<typeof AppointmentUncheckedCreateInputObjectSchema>;
const PatientSchema = (
PatientUncheckedCreateInputObjectSchema as unknown as z.ZodObject<any>
).omit({
appointments: true,
});
type Patient = z.infer<typeof PatientSchema>;
interface AppointmentTableProps {
appointments: Appointment[];
@@ -35,21 +48,34 @@ interface AppointmentTableProps {
onDelete: (id: number) => void;
}
export function AppointmentTable({
appointments,
patients,
onEdit,
onDelete
export function AppointmentTable({
appointments,
patients,
onEdit,
onDelete,
}: AppointmentTableProps) {
// Helper function to get patient name
const getPatientName = (patientId: number) => {
const patient = patients.find(p => p.id === patientId);
return patient ? `${patient.firstName} ${patient.lastName}` : "Unknown Patient";
const patient = patients.find((p) => p.id === patientId);
return patient
? `${patient.firstName} ${patient.lastName}`
: "Unknown Patient";
};
// Helper function to get status badge
const getStatusBadge = (status: string) => {
const statusConfig: Record<string, { variant: "default" | "secondary" | "destructive" | "outline" | "success"; label: string }> = {
const statusConfig: Record<
string,
{
variant:
| "default"
| "secondary"
| "destructive"
| "outline"
| "success";
label: string;
}
> = {
scheduled: { variant: "default", label: "Scheduled" },
confirmed: { variant: "secondary", label: "Confirmed" },
completed: { variant: "success", label: "Completed" },
@@ -57,20 +83,20 @@ export function AppointmentTable({
"no-show": { variant: "outline", label: "No Show" },
};
const config = statusConfig[status] || { variant: "default", label: status };
return (
<Badge variant={config.variant as any}>
{config.label}
</Badge>
);
const config = statusConfig[status] || {
variant: "default",
label: status,
};
return <Badge variant={config.variant as any}>{config.label}</Badge>;
};
// Sort appointments by date and time (newest first)
const sortedAppointments = [...appointments].sort((a, b) => {
const dateComparison = new Date(b.date).getTime() - new Date(a.date).getTime();
const dateComparison =
new Date(b.date).getTime() - new Date(a.date).getTime();
if (dateComparison !== 0) return dateComparison;
return a.startTime.localeCompare(b.startTime);
return a.startTime.toString().localeCompare(b.startTime.toString());
});
return (
@@ -108,15 +134,20 @@ export function AppointmentTable({
<TableCell>
<div className="flex items-center">
<Clock className="mr-2 h-4 w-4 text-muted-foreground" />
{appointment.startTime.slice(0, 5)} - {appointment.endTime.slice(0, 5)}
{appointment.startTime instanceof Date
? appointment.startTime.toISOString().slice(11, 16)
: appointment.startTime.slice(0, 5)}{" "}
-
{appointment.endTime instanceof Date
? appointment.endTime.toISOString().slice(11, 16)
: appointment.endTime.slice(0, 5)}
{/* {appointment.startTime.slice(0, 5)} - {appointment.endTime.slice(0, 5)} */}
</div>
</TableCell>
<TableCell className="capitalize">
{appointment.type.replace('-', ' ')}
</TableCell>
<TableCell>
{getStatusBadge(appointment.status!)}
{appointment.type.replace("-", " ")}
</TableCell>
<TableCell>{getStatusBadge(appointment.status!)}</TableCell>
<TableCell className="text-right">
<DropdownMenu>
<DropdownMenuTrigger asChild>
@@ -132,8 +163,14 @@ export function AppointmentTable({
Edit
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem
onClick={() => onDelete(appointment.id)}
<DropdownMenuItem
onClick={() => {
if (typeof appointment.id === "number") {
onDelete(appointment.id);
} else {
console.error("Invalid appointment ID");
}
}}
className="text-destructive focus:text-destructive"
>
<Trash2 className="mr-2 h-4 w-4" />
@@ -149,4 +186,4 @@ export function AppointmentTable({
</Table>
</div>
);
}
}

View File

@@ -1,21 +1,28 @@
import { useState, useEffect } from "react";
import { Button } from "../ui/button";
import { Input } from "../ui/input";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "../ui/select";
} from "@/components/ui/select";
import { format, parse } from "date-fns";
import { Patient } from "@shared/schema";
import { Card, CardContent, CardHeader, CardTitle } from "../ui/card";
import { Label } from "../ui/label";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Label } from "@/components/ui/label";
import { X, Calendar as CalendarIcon } from "lucide-react";
import { useToast } from "../../hooks/use-toast";
import { Calendar } from "../ui/calendar";
import { Popover, PopoverContent, PopoverTrigger } from "../ui/popover";
import { useToast } from "@/hooks/use-toast";
import { Calendar } from "@/components/ui/calendar";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
// import { Patient } from "@repo/db/shared/schemas";
import { PatientUncheckedCreateInputObjectSchema } from "@repo/db/shared/schemas";
import {z} from "zod";
const PatientSchema = (PatientUncheckedCreateInputObjectSchema as unknown as z.ZodObject<any>).omit({
appointments: true,
});
type Patient = z.infer<typeof PatientSchema>;
interface ClaimFormProps {
patientId: number;

View File

@@ -1,6 +1,13 @@
import { useState, useEffect } from "react";
import { ClaimForm } from "./claim-form";
import { Patient } from "@shared/schema";
// import { Patient } from "@repo/db/shared/schemas";
import { PatientUncheckedCreateInputObjectSchema } from "@repo/db/shared/schemas";
import {z} from "zod";
const PatientSchema = (PatientUncheckedCreateInputObjectSchema as unknown as z.ZodObject<any>).omit({
appointments: true,
});
type Patient = z.infer<typeof PatientSchema>;
interface ClaimModalProps {
open: boolean;

View File

@@ -1,6 +1,5 @@
import { Link, useLocation } from "wouter";
import { Search, LayoutDashboard, Users, Calendar, FileText, Settings } from "lucide-react";
import { Input } from "@/components/ui/input";
import { LayoutDashboard, Users, Calendar, FileText, Settings } from "lucide-react";
import { cn } from "@/lib/utils";
interface SidebarProps {

View File

@@ -1,5 +1,4 @@
import { Bell, Menu, Search } from "lucide-react";
import { Input } from "@/components/ui/input";
import { Bell, Menu} from "lucide-react";
import { Button } from "@/components/ui/button";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { useAuth } from "@/hooks/use-auth";

View File

@@ -9,10 +9,32 @@ import {
DialogFooter,
} from "@/components/ui/dialog";
import { PatientForm } from "./patient-form";
import { InsertPatient, Patient, UpdatePatient } from "@shared/schema";
import { useToast } from "@/hooks/use-toast";
import { X, Calendar } from "lucide-react";
import { useLocation } from "wouter";
// import { InsertPatient, Patient, UpdatePatient } from "@repo/db/shared/schemas";
import { PatientUncheckedCreateInputObjectSchema } from "@repo/db/shared/schemas";
import {z} from "zod";
const PatientSchema = (PatientUncheckedCreateInputObjectSchema as unknown as z.ZodObject<any>).omit({
appointments: true,
});
type Patient = z.infer<typeof PatientSchema>;
const insertPatientSchema = (PatientUncheckedCreateInputObjectSchema as unknown as z.ZodObject<any>).omit({
id: true,
createdAt: true,
});
type InsertPatient = z.infer<typeof insertPatientSchema>;
const updatePatientSchema = (PatientUncheckedCreateInputObjectSchema as unknown as z.ZodObject<any>).omit({
id: true,
createdAt: true,
userId: true,
}).partial();
type UpdatePatient = z.infer<typeof updatePatientSchema>;
interface AddPatientModalProps {
open: boolean;

View File

@@ -1,7 +1,8 @@
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import { insertPatientSchema, InsertPatient, Patient, updatePatientSchema, UpdatePatient } from "@shared/schema";
import { PatientUncheckedCreateInputObjectSchema } from "@repo/db/shared/schemas";
// import { insertPatientSchema, InsertPatient, Patient, updatePatientSchema, UpdatePatient } from "@repo/db/shared/schemas";
import { useAuth } from "@/hooks/use-auth";
import {
Form,
@@ -21,6 +22,26 @@ import {
SelectValue,
} from "@/components/ui/select";
const PatientSchema = (PatientUncheckedCreateInputObjectSchema as unknown as z.ZodObject<any>).omit({
appointments: true,
});
type Patient = z.infer<typeof PatientSchema>;
const insertPatientSchema = (PatientUncheckedCreateInputObjectSchema as unknown as z.ZodObject<any>).omit({
id: true,
createdAt: true,
});
type InsertPatient = z.infer<typeof insertPatientSchema>;
const updatePatientSchema = (PatientUncheckedCreateInputObjectSchema as unknown as z.ZodObject<any>).omit({
id: true,
createdAt: true,
userId: true,
}).partial();
type UpdatePatient = z.infer<typeof updatePatientSchema>;
interface PatientFormProps {
patient?: Patient;
extractedInfo?: {

View File

@@ -1,5 +1,4 @@
import { useState } from "react";
import { Patient } from "@shared/schema";
import {
Table,
TableBody,
@@ -26,6 +25,15 @@ import {
PaginationNext,
PaginationPrevious,
} from "@/components/ui/pagination";
// import { Patient } from "@repo/db/shared/schemas";
import { PatientUncheckedCreateInputObjectSchema } from "@repo/db/shared/schemas";
import {z} from "zod";
const PatientSchema = (PatientUncheckedCreateInputObjectSchema as unknown as z.ZodObject<any>).omit({
appointments: true,
});
type Patient = z.infer<typeof PatientSchema>;
interface PatientTableProps {
patients: Patient[];

View File

@@ -15,6 +15,8 @@ const badgeVariants = cva(
destructive:
"border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
outline: "text-foreground",
success: "border-transparent bg-success text-success-foreground hover:bg-success/80", // ✅ Added success variant
warning: "border-transparent bg-warning text-warning-foreground hover:bg-warning/80", // ✅ Added warning variant
},
},
defaultVariants: {