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..c3371be
--- /dev/null
+++ b/src/app/(web)/account/page.jsx
@@ -0,0 +1,162 @@
+"use client"
+import { useState, useEffect } from 'react';
+import axios from 'axios';
+import { useUser } from '@clerk/clerk-react';
+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 } = useUser();
+ const [userData, setUserData] = useState(null);
+ const [patients, setPatients] = useState([]);
+ const [selectedPatient, setSelectedPatient] = useState(null);
+ const [medications, setMedications] = useState([]);
+ const [diagnoses, setDiagnoses] = useState([]);
+
+ useEffect(() => {
+ if (user) {
+ axios.get(`/api/user?userId=${user.id}`).then(response => {
+ setUserData(response.data);
+ if (response.data.role === 'caregiver') {
+ axios.get('/api/patients').then(res => setPatients(res.data));
+ }
+ });
+ }
+ }, [user]);
+
+ const handleRoleChange = async () => {
+ const newRole = userData.role === 'patient' ? 'caregiver' : 'patient';
+ await axios.put(`/api/user?userId=${user.id}`, { role: newRole });
+ setUserData({ ...userData, 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 (!userData) return
Loading...
;
+
+ return (
+
+
+
+ Account Page
+
+
+
+
+
{userData.name}
+
+
+
+
{userData.email}
+
+
+
+
{userData.role}
+
+
+
+ {userData.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/(web)/layout.tsx b/src/app/(web)/layout.tsx
index e69d4da..da9e34c 100644
--- a/src/app/(web)/layout.tsx
+++ b/src/app/(web)/layout.tsx
@@ -1,5 +1,6 @@
"use client"
+import { ClerkProvider } from '@clerk/nextjs';
import { Navbar } from '@/components/navbar';
import { Footer } from '@/components/footer';
import { ThemeProvider } from '@/components/theme-provider';
@@ -14,11 +15,13 @@ export default function RootLayout({
return (
-
-
- {children}
-
-
+
+
+
+ {children}
+
+
+
)
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..29ee285
--- /dev/null
+++ b/src/app/api/user.js
@@ -0,0 +1,28 @@
+import User from '../../models/User';
+import { connectDB } from '../../lib/utils';
+
+export default async (req, res) => {
+ await connectDB();
+ const { userId } = req.query;
+
+ 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..2d15e01 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);
@@ -81,7 +49,7 @@ export async function POST(req) {
const eventType = evt.type;
if (eventType === 'user.created') {
- const { first_name, last_name, email_addresses } = evt.data;
+ const { id, first_name, last_name, email_addresses } = evt.data;
const email = email_addresses?.[0]?.email_address || null;
if (!email) {
@@ -106,6 +74,7 @@ export async function POST(req) {
}
user = new User({
+ id,
name,
email,
role: 'patient',
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.js b/src/lib/utils.js
new file mode 100644
index 0000000..5ceeb29
--- /dev/null
+++ b/src/lib/utils.js
@@ -0,0 +1,35 @@
+import { clsx } from "clsx";
+import { twMerge } from "tailwind-merge";
+import mongoose from "mongoose";
+
+export function cn(...inputs) {
+ return twMerge(clsx(inputs));
+}
+
+const cached = global.mongoose || { conn: null, promise: null };
+
+export async function connectDB() {
+ const DATABASE_URL = process.env.MONGO_URI;
+
+ 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;
+ global.mongoose = cached;
+ return cached.conn;
+}
\ No newline at end of file
diff --git a/src/lib/utils.ts b/src/lib/utils.ts
deleted file mode 100644
index bd0c391..0000000
--- a/src/lib/utils.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import { clsx, type ClassValue } from "clsx"
-import { twMerge } from "tailwind-merge"
-
-export function cn(...inputs: ClassValue[]) {
- return twMerge(clsx(inputs))
-}
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"]
}