diff --git a/package.json b/package.json
index c646905..a7fd19e 100644
--- a/package.json
+++ b/package.json
@@ -12,12 +12,14 @@
"@clerk/nextjs": "^6.10.2",
"@radix-ui/react-dialog": "^1.1.5",
"@radix-ui/react-dropdown-menu": "^2.1.5",
+ "@radix-ui/react-label": "^2.1.1",
"@radix-ui/react-navigation-menu": "^1.2.4",
"@radix-ui/react-separator": "^1.1.1",
"@radix-ui/react-slot": "^1.1.1",
"@radix-ui/react-tooltip": "^1.1.7",
"@vercel/analytics": "^1.4.1",
"@vercel/speed-insights": "^1.1.0",
+ "axios": "^1.7.9",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"hoyahax-2025": "file:",
diff --git a/src/app/(web)/account/page.jsx b/src/app/(web)/account/page.jsx
new file mode 100644
index 0000000..7a6711f
--- /dev/null
+++ b/src/app/(web)/account/page.jsx
@@ -0,0 +1,157 @@
+"use client";
+import { useState, useEffect } from 'react';
+import axios from 'axios';
+import { Button } from '../../../components/ui/button';
+import { Input } from '../../../components/ui/input';
+import { Label } from '../../../components/ui/label';
+import { Card, CardHeader, CardContent, CardFooter } from '../../../components/ui/card';
+
+const AccountPage = () => {
+ const [user, setUser] = useState(null);
+ const [patients, setPatients] = useState([]);
+ const [selectedPatient, setSelectedPatient] = useState(null);
+ const [medications, setMedications] = useState([]);
+ const [diagnoses, setDiagnoses] = useState([]);
+
+ useEffect(() => {
+ axios.get('/api/user').then(response => {
+ setUser(response.data);
+ if (response.data.role === 'caregiver') {
+ axios.get('/api/patients').then(res => setPatients(res.data));
+ }
+ });
+ }, []);
+
+ const handleRoleChange = async () => {
+ const newRole = user.role === 'patient' ? 'caregiver' : 'patient';
+ await axios.put('/api/user', { role: newRole });
+ setUser({ ...user, role: newRole });
+ if (newRole === 'caregiver') {
+ axios.get('/api/patients').then(res => setPatients(res.data));
+ } else {
+ setPatients([]);
+ setSelectedPatient(null);
+ }
+ };
+
+ const handlePatientSelect = (patient) => {
+ setSelectedPatient(patient);
+ setMedications(patient.medications);
+ setDiagnoses(patient.medicalConditions);
+ };
+
+ const handleMedicationsChange = (index, field, value) => {
+ const updatedMedications = [...medications];
+ updatedMedications[index][field] = value;
+ setMedications(updatedMedications);
+ };
+
+ const handleDiagnosesChange = (e) => {
+ setDiagnoses(e.target.value.split(','));
+ };
+
+ const handleSave = async () => {
+ await axios.put(`/api/patients/${selectedPatient.email}`, {
+ medications,
+ medicalConditions: diagnoses,
+ });
+ alert('Patient data updated successfully');
+ };
+
+ if (!user) return
Loading...
;
+
+ return (
+
+
+
+ Account Page
+
+
+
+
+
+
{user.email}
+
+
+
+
+ {user.role === 'caregiver' && (
+
+
Patients
+
+ {patients.map(patient => (
+ - handlePatientSelect(patient)}
+ className="cursor-pointer hover:bg-gray-200 p-2"
+ >
+ {patient.name}
+
+ ))}
+
+
+ {selectedPatient && (
+
+
+ Edit Patient: {selectedPatient.name}
+
+
+
+
+
+
+
+
+
+
+
+
+ )}
+
+ )}
+
+
+
+ );
+};
+
+export default AccountPage;
\ No newline at end of file
diff --git a/src/app/api/layout.tsx b/src/app/api/layout.tsx
new file mode 100644
index 0000000..a14e64f
--- /dev/null
+++ b/src/app/api/layout.tsx
@@ -0,0 +1,16 @@
+export const metadata = {
+ title: 'Next.js',
+ description: 'Generated by Next.js',
+}
+
+export default function RootLayout({
+ children,
+}: {
+ children: React.ReactNode
+}) {
+ return (
+
+ {children}
+
+ )
+}
diff --git a/src/app/api/patients.js b/src/app/api/patients.js
new file mode 100644
index 0000000..d8fd75b
--- /dev/null
+++ b/src/app/api/patients.js
@@ -0,0 +1,9 @@
+import User from '../../models/User';
+import { connectDB } from '../../lib/utils';
+
+export default async (req, res) => {
+ await connectDB();
+
+ const patients = await User.find({ role: 'patient' });
+ res.json(patients);
+};
\ No newline at end of file
diff --git a/src/app/api/patients/[email].js b/src/app/api/patients/[email].js
new file mode 100644
index 0000000..4e97c58
--- /dev/null
+++ b/src/app/api/patients/[email].js
@@ -0,0 +1,21 @@
+import User from '../../../models/User';
+import connectDB from '../../../lib/utils';
+
+export default async (req, res) => {
+ await connectDB();
+
+ const { email } = req.query;
+ const { medications, medicalConditions } = req.body;
+
+ const patient = await User.findOne({ email });
+
+ if (!patient) {
+ return res.status(404).json({ message: 'Patient not found' });
+ }
+
+ patient.medications = medications;
+ patient.medicalConditions = medicalConditions;
+ await patient.save();
+
+ res.json(patient);
+};
\ No newline at end of file
diff --git a/src/app/api/user.js b/src/app/api/user.js
new file mode 100644
index 0000000..03f6bb1
--- /dev/null
+++ b/src/app/api/user.js
@@ -0,0 +1,29 @@
+import { getAuth } from '@clerk/nextjs/server';
+import User from '../../models/User';
+import { connectDB } from '../../lib/utils';
+
+export default async (req, res) => {
+ await connectDB();
+ const { userId } = getAuth(req);
+
+ if (!userId) {
+ return res.status(401).json({ message: 'Unauthorized' });
+ }
+
+ const user = await User.findOne({ id: userId });
+
+ if (!user) {
+ return res.status(404).json({ message: 'User not found' });
+ }
+
+ if (req.method === 'GET') {
+ res.json(user);
+ } else if (req.method === 'PUT') {
+ const { role } = req.body;
+ user.role = role;
+ await user.save();
+ res.json(user);
+ } else {
+ res.status(405).json({ message: 'Method not allowed' });
+ }
+};
\ No newline at end of file
diff --git a/src/app/api/webhook/route.js b/src/app/api/webhook/route.js
index 3e00237..f059fad 100644
--- a/src/app/api/webhook/route.js
+++ b/src/app/api/webhook/route.js
@@ -1,42 +1,10 @@
import { User } from '../../../models/User';
import { NextResponse } from 'next/server';
import { Webhook } from 'svix';
-import mongoose from "mongoose";
+import { connectDB } from '../../../lib/utils';
const CLERK_WEBHOOK_SECRET = process.env.CLERK_WEBHOOK_SECRET;
-const DATABASE_URL = process.env.MONGO_URI;
-
-let cached = global.mongoose;
-
-if (!cached) {
- cached = global.mongoose = { conn: null, promise: null };
-}
-async function connectDB() {
- if (cached.conn) {
- return cached.conn;
- }
-
- if (!cached.promise) {
- const opts = {
- bufferCommands: false,
- };
-
- try {
- cached.promise = mongoose.connect(DATABASE_URL, opts).then((mongoose) => {
- console.log('MongoDB connected successfully');
- return mongoose;
- });
- } catch (error) {
- console.error('Error connecting to MongoDB:', error.message);
- throw new Error('Error connecting to MongoDB');
- }
- }
-
- cached.conn = await cached.promise;
- return cached.conn;
-}
-
export async function POST(req) {
console.log('Received request:', req);
@@ -106,6 +74,7 @@ export async function POST(req) {
}
user = new User({
+ id,
name,
email,
role: 'patient',
diff --git a/src/components/ui/card.tsx b/src/components/ui/card.tsx
new file mode 100644
index 0000000..cabfbfc
--- /dev/null
+++ b/src/components/ui/card.tsx
@@ -0,0 +1,76 @@
+import * as React from "react"
+
+import { cn } from "@/lib/utils"
+
+const Card = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+Card.displayName = "Card"
+
+const CardHeader = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+CardHeader.displayName = "CardHeader"
+
+const CardTitle = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+CardTitle.displayName = "CardTitle"
+
+const CardDescription = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+CardDescription.displayName = "CardDescription"
+
+const CardContent = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+CardContent.displayName = "CardContent"
+
+const CardFooter = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+CardFooter.displayName = "CardFooter"
+
+export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }
diff --git a/src/components/ui/label.tsx b/src/components/ui/label.tsx
new file mode 100644
index 0000000..5341821
--- /dev/null
+++ b/src/components/ui/label.tsx
@@ -0,0 +1,26 @@
+"use client"
+
+import * as React from "react"
+import * as LabelPrimitive from "@radix-ui/react-label"
+import { cva, type VariantProps } from "class-variance-authority"
+
+import { cn } from "@/lib/utils"
+
+const labelVariants = cva(
+ "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
+)
+
+const Label = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef &
+ VariantProps
+>(({ className, ...props }, ref) => (
+
+))
+Label.displayName = LabelPrimitive.Root.displayName
+
+export { Label }
diff --git a/src/lib/utils.ts b/src/lib/utils.ts
index bd0c391..710c273 100644
--- a/src/lib/utils.ts
+++ b/src/lib/utils.ts
@@ -1,6 +1,46 @@
-import { clsx, type ClassValue } from "clsx"
-import { twMerge } from "tailwind-merge"
+import { clsx, type ClassValue } from "clsx";
+import { twMerge } from "tailwind-merge";
+import mongoose, { Mongoose } from "mongoose";
-export function cn(...inputs: ClassValue[]) {
- return twMerge(clsx(inputs))
+export function cn(...inputs: ClassValue[]): string {
+ return twMerge(clsx(inputs));
}
+
+interface Cached {
+ conn: Mongoose | null;
+ promise: Promise | null;
+}
+
+declare global {
+ var mongoose: Cached;
+}
+
+export async function connectDB(): Promise {
+ const DATABASE_URL = process.env.MONGO_URI as string;
+
+ let cached: Cached = global.mongoose;
+
+ if (!cached) {
+ cached = global.mongoose = { conn: null, promise: null };
+ }
+ if (cached.conn) {
+ return cached.conn;
+ }
+
+ if (!cached.promise) {
+ const opts = {
+ bufferCommands: false,
+ };
+
+ cached.promise = mongoose.connect(DATABASE_URL, opts).then((mongoose) => {
+ console.log('MongoDB connected successfully');
+ return mongoose;
+ }).catch((error) => {
+ console.error('Error connecting to MongoDB:', error.message);
+ throw new Error('Error connecting to MongoDB');
+ });
+ }
+
+ cached.conn = await cached.promise;
+ return cached.conn;
+}
\ No newline at end of file
diff --git a/src/models/User.js b/src/models/User.js
index 5f8a7e9..e5a8cba 100644
--- a/src/models/User.js
+++ b/src/models/User.js
@@ -2,6 +2,11 @@ import { Schema, model, models } from "mongoose";
const UserSchema = new Schema(
{
+ id: {
+ type: String,
+ required: true,
+ unique: true,
+ },
name: {
type: String,
required: true,
diff --git a/tsconfig.json b/tsconfig.json
index 279409d..b7a29c2 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -22,6 +22,6 @@
"@/*": ["./src/*"]
}
},
- "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", "src/app/api/connectDB.js"],
+ "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", "src/app/api/connectDB.js", "src/lib/utils.js", "src/app/(web)/account/page.jsx"],
"exclude": ["node_modules"]
}