Update src/app/patients/page.tsx
This commit is contained in:
@@ -1,27 +1,69 @@
|
||||
"use client";
|
||||
|
||||
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
|
||||
import Link from "next/link";
|
||||
import { useState } from "react";
|
||||
import NavbarStyleApple from "@/components/navbar/NavbarStyleApple/NavbarStyleApple";
|
||||
import FeatureCardTwelve from "@/components/sections/feature/FeatureCardTwelve";
|
||||
import MetricCardThree from "@/components/sections/metrics/MetricCardThree";
|
||||
import ContactCenter from "@/components/sections/contact/ContactCenter";
|
||||
import FooterLogoEmphasis from "@/components/sections/footer/FooterLogoEmphasis";
|
||||
import { Search, Users, FileText, Activity, Mail } from "lucide-react";
|
||||
import { Search, Users, Calendar, FileText, Phone, Mail, MapPin, Heart, Activity, Clock } from "lucide-react";
|
||||
|
||||
interface Patient {
|
||||
id: string;
|
||||
name: string;
|
||||
age: number;
|
||||
gender: string;
|
||||
email: string;
|
||||
phone: string;
|
||||
condition: string;
|
||||
lastVisit: string;
|
||||
nextAppointment: string;
|
||||
status: "active" | "inactive" | "pending";
|
||||
avatar: string;
|
||||
}
|
||||
|
||||
const mockPatients: Patient[] = [
|
||||
{
|
||||
id: "1", name: "Emily Rodriguez", age: 34,
|
||||
gender: "Female", email: "emily.rodriguez@email.com", phone: "+1 (555) 123-4567", condition: "Hypertension", lastVisit: "2025-01-15", nextAppointment: "2025-02-15", status: "active", avatar: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3Ab61rTDKmrydpiUl7xdk36wxrL/a-professional-portrait-of-a-female-doct-1772848849712-1b8fd6f3.png"},
|
||||
{
|
||||
id: "2", name: "Michael Thompson", age: 52,
|
||||
gender: "Male", email: "michael.thompson@email.com", phone: "+1 (555) 234-5678", condition: "Diabetes Type 2", lastVisit: "2025-01-10", nextAppointment: "2025-02-10", status: "active", avatar: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3Ab61rTDKmrydpiUl7xdk36wxrL/a-professional-portrait-of-an-older-male-1772848851376-833457fc.png"},
|
||||
{
|
||||
id: "3", name: "Sarah Johnson", age: 28,
|
||||
gender: "Female", email: "sarah.johnson@email.com", phone: "+1 (555) 345-6789", condition: "Asthma", lastVisit: "2025-01-20", nextAppointment: "2025-02-20", status: "active", avatar: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3Ab61rTDKmrydpiUl7xdk36wxrL/a-professional-portrait-of-a-female-heal-1772848850769-375be9a4.png"},
|
||||
{
|
||||
id: "4", name: "James Chen", age: 45,
|
||||
gender: "Male", email: "james.chen@email.com", phone: "+1 (555) 456-7890", condition: "Cardiac Care", lastVisit: "2025-01-12", nextAppointment: "2025-01-29", status: "pending", avatar: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3Ab61rTDKmrydpiUl7xdk36wxrL/a-professional-portrait-of-a-male-nurse--1772848851435-e85b1a73.png"},
|
||||
{
|
||||
id: "5", name: "Lisa Martinez", age: 55,
|
||||
gender: "Female", email: "lisa.martinez@email.com", phone: "+1 (555) 567-8901", condition: "Arthritis", lastVisit: "2024-12-15", nextAppointment: "2025-03-01", status: "inactive", avatar: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3Ab61rTDKmrydpiUl7xdk36wxrL/a-professional-portrait-of-a-female-heal-1772848850769-375be9a4.png"},
|
||||
];
|
||||
|
||||
export default function PatientsPage() {
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const [selectedPatient, setSelectedPatient] = useState<Patient | null>(null);
|
||||
const [filterStatus, setFilterStatus] = useState<string>("all");
|
||||
|
||||
const filteredPatients = mockPatients.filter((patient) => {
|
||||
const matchesSearch =
|
||||
patient.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||
patient.email.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||
patient.phone.includes(searchTerm);
|
||||
const matchesStatus = filterStatus === "all" || patient.status === filterStatus;
|
||||
return matchesSearch && matchesStatus;
|
||||
});
|
||||
|
||||
export default function PatientDirectoryPage() {
|
||||
return (
|
||||
<ThemeProvider
|
||||
defaultButtonVariant="hover-magnetic"
|
||||
defaultTextAnimation="reveal-blur"
|
||||
borderRadius="rounded"
|
||||
contentWidth="small"
|
||||
sizing="largeSizeMediumTitles"
|
||||
contentWidth="medium"
|
||||
sizing="medium"
|
||||
background="circleGradient"
|
||||
cardStyle="glass-depth"
|
||||
primaryButtonStyle="radial-glow"
|
||||
cardStyle="glass-elevated"
|
||||
primaryButtonStyle="gradient"
|
||||
secondaryButtonStyle="glass"
|
||||
headingFontWeight="extrabold"
|
||||
headingFontWeight="normal"
|
||||
>
|
||||
<div id="nav" data-section="nav">
|
||||
<NavbarStyleApple
|
||||
@@ -36,62 +78,217 @@ export default function PatientDirectoryPage() {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="patient-features" data-section="patient-features">
|
||||
<FeatureCardTwelve
|
||||
title="Patient Directory & Search Management"
|
||||
description="Powerful tools to find, manage, and organize patient information efficiently"
|
||||
tag="Patient Management"
|
||||
tagIcon={Search}
|
||||
tagAnimation="slide-up"
|
||||
features={[
|
||||
{
|
||||
id: "search", label: "Search", title: "Advanced Patient Search & Filtering", items: [
|
||||
"Real-time search across patient database", "Filter by multiple criteria (name, ID, condition, status)", "Saved search templates for frequent queries", "Quick access to recently viewed patient records"],
|
||||
},
|
||||
{
|
||||
id: "profiles", label: "Profiles", title: "Comprehensive Patient Profile Management", items: [
|
||||
"Complete demographic and contact information", "Medical history and chronic conditions", "Current medications and allergies", "Emergency contacts and insurance details"],
|
||||
},
|
||||
{
|
||||
id: "organization", label: "Organization", title: "Intelligent Patient Organization System", items: [
|
||||
"Custom patient groups and cohorts", "Risk stratification and priority flags", "Department and care team assignments", "Patient lifecycle tracking from admission to discharge"],
|
||||
},
|
||||
]}
|
||||
animationType="slide-up"
|
||||
textboxLayout="default"
|
||||
useInvertedBackground={true}
|
||||
/>
|
||||
</div>
|
||||
<div className="min-h-screen bg-background pt-24 pb-20">
|
||||
<div className="container mx-auto px-4 md:px-6">
|
||||
{/* Header */}
|
||||
<div className="mb-12">
|
||||
<h1 className="text-4xl md:text-5xl font-bold mb-4">Patient Records Management</h1>
|
||||
<p className="text-lg text-foreground/70">Search and view patient information, medical history, and appointments</p>
|
||||
</div>
|
||||
|
||||
<div id="patient-metrics" data-section="patient-metrics">
|
||||
<MetricCardThree
|
||||
title="Patient Directory Impact"
|
||||
description="Streamline patient management with comprehensive directory capabilities"
|
||||
metrics={[
|
||||
{ id: "1", icon: Users, title: "Active Patients", value: "15,000+" },
|
||||
{ id: "2", icon: Search, title: "Search Time Reduced", value: "85%" },
|
||||
{ id: "3", icon: FileText, title: "Records Accessible", value: "100%" },
|
||||
{ id: "4", icon: Activity, title: "Data Currency", value: "Real-time" },
|
||||
]}
|
||||
animationType="slide-up"
|
||||
textboxLayout="default"
|
||||
useInvertedBackground={false}
|
||||
/>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
|
||||
{/* Left Column - Search and Filter */}
|
||||
<div className="lg:col-span-1">
|
||||
<div className="bg-card rounded-2xl p-6 border border-background-accent/20">
|
||||
{/* Search Box */}
|
||||
<div className="mb-6">
|
||||
<label className="block text-sm font-semibold mb-3">Search Patients</label>
|
||||
<div className="relative">
|
||||
<Search className="absolute left-3 top-3 text-foreground/40" size={20} />
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Name, email, or phone"
|
||||
value={searchTerm}
|
||||
onChange={(e) => setSearchTerm(e.target.value)}
|
||||
className="w-full pl-10 pr-4 py-2 bg-background border border-background-accent/30 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-cta"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="contact" data-section="contact">
|
||||
<ContactCenter
|
||||
tag="Get More Info"
|
||||
tagIcon={Mail}
|
||||
tagAnimation="slide-up"
|
||||
title="Optimize Your Patient Directory Management"
|
||||
description="Learn how our advanced search and organization tools can streamline your patient management workflows and improve care coordination."
|
||||
background={{ variant: "rotated-rays-animated-grid" }}
|
||||
useInvertedBackground={false}
|
||||
inputPlaceholder="Enter your email"
|
||||
buttonText="Get Started"
|
||||
termsText="We respect your privacy. HIPAA-compliant communication. Response within 24 hours."
|
||||
/>
|
||||
{/* Filter by Status */}
|
||||
<div>
|
||||
<label className="block text-sm font-semibold mb-3">Filter by Status</label>
|
||||
<div className="space-y-2">
|
||||
{["all", "active", "pending", "inactive"].map((status) => (
|
||||
<button
|
||||
key={status}
|
||||
onClick={() => setFilterStatus(status)}
|
||||
className={`w-full text-left px-4 py-2 rounded-lg transition-all ${
|
||||
filterStatus === status
|
||||
? "bg-primary-cta text-background"
|
||||
: "bg-background text-foreground hover:bg-background-accent/30"
|
||||
}`}
|
||||
>
|
||||
<span className="capitalize">{status === "all" ? "All Patients" : status}</span>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right Column - Patient List and Detail View */}
|
||||
<div className="lg:col-span-2">
|
||||
{!selectedPatient ? (
|
||||
// Patient List View
|
||||
<div className="space-y-4">
|
||||
{filteredPatients.length > 0 ? (
|
||||
filteredPatients.map((patient) => (
|
||||
<div
|
||||
key={patient.id}
|
||||
onClick={() => setSelectedPatient(patient)}
|
||||
className="bg-card rounded-xl p-4 border border-background-accent/20 cursor-pointer hover:border-primary-cta/50 hover:shadow-lg transition-all"
|
||||
>
|
||||
<div className="flex items-start gap-4">
|
||||
<img
|
||||
src={patient.avatar}
|
||||
alt={patient.name}
|
||||
className="w-12 h-12 rounded-full object-cover"
|
||||
/>
|
||||
<div className="flex-1">
|
||||
<div className="flex items-center justify-between mb-2">
|
||||
<h3 className="text-lg font-semibold">{patient.name}</h3>
|
||||
<span
|
||||
className={`text-xs px-3 py-1 rounded-full ${
|
||||
patient.status === "active"
|
||||
? "bg-green-500/20 text-green-700"
|
||||
: patient.status === "pending"
|
||||
? "bg-yellow-500/20 text-yellow-700"
|
||||
: "bg-gray-500/20 text-gray-700"
|
||||
}`}
|
||||
>
|
||||
{patient.status.charAt(0).toUpperCase() + patient.status.slice(1)}
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-sm text-foreground/60 mb-2">{patient.condition}</p>
|
||||
<div className="flex gap-4 text-sm text-foreground/50">
|
||||
<span>Age: {patient.age}</span>
|
||||
<span>Last Visit: {new Date(patient.lastVisit).toLocaleDateString()}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<div className="text-center py-12 bg-card rounded-xl border border-background-accent/20">
|
||||
<Users size={48} className="mx-auto text-foreground/30 mb-4" />
|
||||
<p className="text-foreground/60">No patients found matching your search</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
// Patient Detail View
|
||||
<div className="bg-card rounded-xl p-6 border border-background-accent/20">
|
||||
<button
|
||||
onClick={() => setSelectedPatient(null)}
|
||||
className="mb-6 px-4 py-2 rounded-lg bg-background-accent/30 text-foreground hover:bg-background-accent/50 transition-all"
|
||||
>
|
||||
← Back to List
|
||||
</button>
|
||||
|
||||
{/* Patient Header */}
|
||||
<div className="flex items-start gap-6 mb-8 pb-8 border-b border-background-accent/20">
|
||||
<img
|
||||
src={selectedPatient.avatar}
|
||||
alt={selectedPatient.name}
|
||||
className="w-20 h-20 rounded-full object-cover"
|
||||
/>
|
||||
<div className="flex-1">
|
||||
<div className="flex items-center justify-between mb-2">
|
||||
<h2 className="text-3xl font-bold">{selectedPatient.name}</h2>
|
||||
<span
|
||||
className={`text-sm px-3 py-1 rounded-full ${
|
||||
selectedPatient.status === "active"
|
||||
? "bg-green-500/20 text-green-700"
|
||||
: selectedPatient.status === "pending"
|
||||
? "bg-yellow-500/20 text-yellow-700"
|
||||
: "bg-gray-500/20 text-gray-700"
|
||||
}`}
|
||||
>
|
||||
{selectedPatient.status.charAt(0).toUpperCase() + selectedPatient.status.slice(1)}
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-lg text-foreground/70 mb-3">{selectedPatient.condition}</p>
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div>
|
||||
<p className="text-sm text-foreground/50">Age</p>
|
||||
<p className="font-semibold">{selectedPatient.age} years old</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm text-foreground/50">Gender</p>
|
||||
<p className="font-semibold">{selectedPatient.gender}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Contact Information */}
|
||||
<div className="mb-8">
|
||||
<h3 className="text-xl font-semibold mb-4">Contact Information</h3>
|
||||
<div className="space-y-3">
|
||||
<div className="flex items-center gap-3">
|
||||
<Mail size={20} className="text-primary-cta" />
|
||||
<div>
|
||||
<p className="text-sm text-foreground/50">Email</p>
|
||||
<p className="font-medium">{selectedPatient.email}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
<Phone size={20} className="text-primary-cta" />
|
||||
<div>
|
||||
<p className="text-sm text-foreground/50">Phone</p>
|
||||
<p className="font-medium">{selectedPatient.phone}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Appointment Information */}
|
||||
<div className="mb-8">
|
||||
<h3 className="text-xl font-semibold mb-4">Appointment Schedule</h3>
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div className="bg-background rounded-lg p-4 border border-background-accent/20">
|
||||
<div className="flex items-center gap-2 mb-2">
|
||||
<Clock size={18} className="text-primary-cta" />
|
||||
<p className="text-sm text-foreground/50">Last Visit</p>
|
||||
</div>
|
||||
<p className="font-semibold">{new Date(selectedPatient.lastVisit).toLocaleDateString()}</p>
|
||||
</div>
|
||||
<div className="bg-background rounded-lg p-4 border border-background-accent/20">
|
||||
<div className="flex items-center gap-2 mb-2">
|
||||
<Calendar size={18} className="text-primary-cta" />
|
||||
<p className="text-sm text-foreground/50">Next Appointment</p>
|
||||
</div>
|
||||
<p className="font-semibold">{new Date(selectedPatient.nextAppointment).toLocaleDateString()}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Medical Information */}
|
||||
<div>
|
||||
<h3 className="text-xl font-semibold mb-4">Medical Information</h3>
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div className="bg-background rounded-lg p-4 border border-background-accent/20 flex items-center gap-3">
|
||||
<Heart size={24} className="text-primary-cta" />
|
||||
<div>
|
||||
<p className="text-sm text-foreground/50">Primary Condition</p>
|
||||
<p className="font-semibold">{selectedPatient.condition}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="bg-background rounded-lg p-4 border border-background-accent/20 flex items-center gap-3">
|
||||
<Activity size={24} className="text-primary-cta" />
|
||||
<div>
|
||||
<p className="text-sm text-foreground/50">Health Status</p>
|
||||
<p className="font-semibold capitalize">{selectedPatient.status}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="footer" data-section="footer">
|
||||
@@ -131,4 +328,4 @@ export default function PatientDirectoryPage() {
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user