Merge remote-tracking branch 'refs/remotes/origin/main'
This commit is contained in:
197
README.md
197
README.md
@@ -1,36 +1,191 @@
|
|||||||
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
|
<!-- Improved compatibility of back to top link: See: https://github.com/othneildrew/Best-README-Template/pull/73 -->
|
||||||
|
<a id="readme-top"></a>
|
||||||
|
<!--
|
||||||
|
*** Thanks for checking out the Best-README-Template. If you have a suggestion
|
||||||
|
*** that would make this better, please fork the repo and create a pull request
|
||||||
|
*** or simply open an issue with the tag "enhancement".
|
||||||
|
*** Don't forget to give the project a star!
|
||||||
|
*** Thanks again! Now go create something AMAZING! :D
|
||||||
|
-->
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- PROJECT SHIELDS -->
|
||||||
|
<!--
|
||||||
|
*** I'm using markdown "reference style" links for readability.
|
||||||
|
*** Reference links are enclosed in brackets [ ] instead of parentheses ( ).
|
||||||
|
*** See the bottom of this document for the declaration of the reference variables
|
||||||
|
*** for contributors-url, forks-url, etc. This is an optional, concise syntax you may use.
|
||||||
|
*** https://www.markdownguide.org/basic-syntax/#reference-style-links
|
||||||
|
-->
|
||||||
|
[![Contributors][contributors-shield]][contributors-url]
|
||||||
|
[![Stargazers][stars-shield]][stars-url]
|
||||||
|
[![Issues][issues-shield]][issues-url]
|
||||||
|
[![Apache License][license-shield]][license-url]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- PROJECT LOGO -->
|
||||||
|
<br />
|
||||||
|
<div align="center">
|
||||||
|
<a href="https://github.com/GamerBoss101/HoyaHax2025">
|
||||||
|
<img src="/public/HoyaHax2025-icon.svg" alt="Logo" width="80" height="80">
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<h3 align="center">PatSafe</h3>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
Bridging the gap between doctors and patients for seamless post-discharge care.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<a href="https://www.patsafe.co">Visit</a>
|
||||||
|
·
|
||||||
|
<a href="https://github.com/GamerBoss101/HoyaHax2025/issues/new?labels=bug&template=bug-report---.md">Report Bug</a>
|
||||||
|
·
|
||||||
|
<a href="https://github.com/GamerBoss101/HoyaHax2025/issues/new?labels=enhancement&template=feature-request---.md">Request Feature</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- ABOUT THE PROJECT -->
|
||||||
|
## About the Project
|
||||||
|
|
||||||
|
PatSafe is a web-based application that connects discharged patients with their doctors for post-discharge care. It features a doctor’s dashboard where they can update patient information, provide medication instructions, and track patient progress. Patients can report their symptoms, recovery status, and medication adherence, which is then updated in real time for their doctor to review. Additionally, PatSafe includes an AI-powered chatbot that allows patients to ask medical questions and report symptoms, helping doctors get insights into the patient’s condition remotely. The chatbot also aids in tracking medication adherence and offering information for diagnoses and prescriptions.
|
||||||
|
|
||||||
|
### How does it work?
|
||||||
|
|
||||||
|
PatSafe was built using **Next.js** and **React.js** for the frontend, while the backend is powered by **MongoDB** and **Clerk** for authentication. The platform utilizes APIs for real-time updates and features such as medication tracking and symptom reporting. We integrated a chatbot powered by **Hugging Face models** for natural language processing, allowing users to interact conversationally and gather helpful medical information.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Built With
|
||||||
|
|
||||||
|
* [![Next.js][Next.js]][Next-url]
|
||||||
|
* [![React][React.js]][React-url]
|
||||||
|
* [![Tailwind][Tailwind]][Tailwind-url]
|
||||||
|
* [![Clerk][Clerk]][Clerk-url]
|
||||||
|
* [![MongoDB][MongoDB]][MongoDB-url]
|
||||||
|
* [![HuggingFace][HuggingFace]][HuggingFace-url]
|
||||||
|
* [![OpenAI][OpenAI]][OpenAI]
|
||||||
|
|
||||||
|
|
||||||
|
<p align="right">(<a href="#readme-top">back to top</a>)</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- GETTING STARTED -->
|
||||||
## Getting Started
|
## Getting Started
|
||||||
|
|
||||||
First, run the development server:
|
Here are the steps to run the project locally if you want to develop your own project.
|
||||||
|
|
||||||
```bash
|
### Prerequisites
|
||||||
npm run dev
|
|
||||||
# or
|
* pnpm
|
||||||
yarn dev
|
```sh
|
||||||
# or
|
pnpm self-update
|
||||||
pnpm dev
|
|
||||||
# or
|
|
||||||
bun dev
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
|
|
||||||
|
|
||||||
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
|
### Installation
|
||||||
|
|
||||||
This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
|
1. Fork the repository and set it up as a project on Vercel or another hosting platform
|
||||||
|
|
||||||
## Learn More
|
2. Install packages
|
||||||
|
```sh
|
||||||
|
pnpm install
|
||||||
|
```
|
||||||
|
|
||||||
To learn more about Next.js, take a look at the following resources:
|
3. You can run the website locally with
|
||||||
|
```sh
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
or, if hosting on Vercel, with
|
||||||
|
```sh
|
||||||
|
vercel dev
|
||||||
|
```
|
||||||
|
|
||||||
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
|
|
||||||
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
|
|
||||||
|
|
||||||
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
|
|
||||||
|
|
||||||
## Deploy on Vercel
|
|
||||||
|
|
||||||
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
|
|
||||||
|
|
||||||
Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- LICENSE -->
|
||||||
|
## License
|
||||||
|
|
||||||
|
Distributed under the Apache 2.0 License. See `LICENSE.txt` for more information.
|
||||||
|
|
||||||
|
|
||||||
|
* [Best README Template](https://github.com/othneildrew/Best-README-Template)
|
||||||
|
|
||||||
|
<p align="right">(<a href="#readme-top">back to top</a>)</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- MARKDOWN LINKS & IMAGES -->
|
||||||
|
<!-- https://www.markdownguide.org/basic-syntax/#reference-style-links -->
|
||||||
|
[contributors-shield]: https://img.shields.io/github/contributors/GamerBoss101/HoyaHax2025.svg?style=for-the-badge
|
||||||
|
[contributors-url]: https://github.com/GamerBoss101/HoyaHax2025/graphs/contributors
|
||||||
|
[forks-shield]: https://img.shields.io/github/forks/GamerBoss101/HoyaHax2025.svg?style=for-the-badge
|
||||||
|
[forks-url]: https://github.com/GamerBoss101/HoyaHax2025/network/members
|
||||||
|
[stars-shield]: https://img.shields.io/github/stars/GamerBoss101/HoyaHax2025.svg?style=for-the-badge
|
||||||
|
[stars-url]: https://github.com/GamerBoss101/HoyaHax2025/stargazers
|
||||||
|
[issues-shield]: https://img.shields.io/github/issues/GamerBoss101/HoyaHax2025.svg?style=for-the-badge
|
||||||
|
[issues-url]: https://github.com/GamerBoss101/HoyaHax2025/issues
|
||||||
|
[license-shield]: https://img.shields.io/github/license/GamerBoss101/HoyaHax2025.svg?style=for-the-badge
|
||||||
|
[license-url]: https://github.com/GamerBoss101/HoyaHax2025/blob/master/LICENSE.txt
|
||||||
|
[linkedin-shield]: https://img.shields.io/badge/LinkedIn-0A66C2.svg?style=for-the-badge&logo=linkedin&logoColor=white
|
||||||
|
[linkedin-url-joseph]: https://linkedin.com/in/joseph-j-helfenbein
|
||||||
|
[product-screenshot]: images/screenshot.png
|
||||||
|
[Next.js]: https://img.shields.io/badge/next.js-000000?style=for-the-badge&logo=nextdotjs&logoColor=white
|
||||||
|
[Next-url]: https://nextjs.org/
|
||||||
|
[React.js]: https://img.shields.io/badge/React.js-20232A?style=for-the-badge&logo=react&logoColor=61DAFB
|
||||||
|
[React-url]: https://reactjs.org/
|
||||||
|
[Vue.js]: https://img.shields.io/badge/Vue.js-35495E?style=for-the-badge&logo=vuedotjs&logoColor=4FC08D
|
||||||
|
[Vue-url]: https://vuejs.org/
|
||||||
|
[Angular.io]: https://img.shields.io/badge/Angular-DD0031?style=for-the-badge&logo=angular&logoColor=white
|
||||||
|
[Angular-url]: https://angular.io/
|
||||||
|
[Svelte.dev]: https://img.shields.io/badge/Svelte-4A4A55?style=for-the-badge&logo=svelte&logoColor=FF3E00
|
||||||
|
[Svelte-url]: https://svelte.dev/
|
||||||
|
[Laravel.com]: https://img.shields.io/badge/Laravel-FF2D20?style=for-the-badge&logo=laravel&logoColor=white
|
||||||
|
[Laravel-url]: https://laravel.com
|
||||||
|
[Bootstrap.com]: https://img.shields.io/badge/Bootstrap-563D7C?style=for-the-badge&logo=bootstrap&logoColor=white
|
||||||
|
[Bootstrap-url]: https://getbootstrap.com
|
||||||
|
[JQuery.com]: https://img.shields.io/badge/jQuery-0769AD?style=for-the-badge&logo=jquery&logoColor=white
|
||||||
|
[JQuery-url]: https://jquery.com
|
||||||
|
[Expo]: https://img.shields.io/badge/expo-000000?style=for-the-badge&logo=expo&logoColor=white
|
||||||
|
[Expo-url]: https://expo.dev/
|
||||||
|
[Flask]: https://img.shields.io/badge/flask-4590A1?logo=flask&style=for-the-badge&logoColor=white
|
||||||
|
[Flask-url]: https://flask.palletsprojects.com/en/3.0.x/
|
||||||
|
[JavaScript]: https://img.shields.io/badge/javascript-yellow?logo=javascript&style=for-the-badge&logoColor=white
|
||||||
|
[JavaScript-url]: https://developer.oracle.com/languages/javascript.html
|
||||||
|
[ThreeJS]: https://img.shields.io/badge/three.js-black?logo=three.js&style=for-the-badge&logoColor=white
|
||||||
|
[ThreeJS-url]: https://threejs.org/
|
||||||
|
[TypeScript]: https://img.shields.io/badge/typescript-3178C6?logo=typescript&style=for-the-badge&logoColor=white
|
||||||
|
[TypeScript-url]: https://www.typescriptlang.org/
|
||||||
|
[Python]: https://img.shields.io/badge/python-3776AB?style=for-the-badge&logo=python&logoColor=white
|
||||||
|
[Python-url]: https://www.python.org/
|
||||||
|
[Amazon-RDS]: https://img.shields.io/badge/amazon%20rds-527FFF?style=for-the-badge&logo=amazon%20rds&logoColor=white
|
||||||
|
[Amazon-RDS-url]: https://aws.amazon.com/rds/
|
||||||
|
[Cloudflare]: https://img.shields.io/badge/cloudflare%20workers-F38020?style=for-the-badge&logo=cloudflare%20workers&logoColor=white
|
||||||
|
[Cloudflare-url]: https://workers.cloudflare.com/
|
||||||
|
[Vercel]: https://img.shields.io/badge/vercel-000000?logo=vercel&style=for-the-badge&logoColor=white
|
||||||
|
[Vercel-url]: https://www.vercel.com/
|
||||||
|
[Supabase]: https://img.shields.io/badge/supabase-3FCF8E?logo=supabase&style=for-the-badge&logoColor=white
|
||||||
|
[Supabase-url]: https://supabase.com/
|
||||||
|
[Clerk]: https://img.shields.io/badge/clerk-6C47FF?logo=clerk&style=for-the-badge&logoColor=white
|
||||||
|
[Clerk-url]: https://clerk.com/
|
||||||
|
[Tailwind]: https://img.shields.io/badge/tailwind%20css-06B6D4?logo=tailwindcss&style=for-the-badge&logoColor=white
|
||||||
|
[Tailwind-url]: https://tailwindcss.com/
|
||||||
|
[MongoDB]: https://img.shields.io/badge/mongodb-47A248?logo=mongodb&style=for-the-badge&logoColor=white
|
||||||
|
[MongoDB-url]: https://www.mongodb.com/
|
||||||
|
[HuggingFace]: https://img.shields.io/badge/huggingface-FFD21E?logo=huggingface&style=for-the-badge&logoColor=white
|
||||||
|
[HuggingFace-url]: https://huggingface.co/
|
||||||
|
[OpenAI]: https://img.shields.io/badge/openai%20api-412991?logo=openai&style=for-the-badge&logoColor=white
|
||||||
|
[OpenAI-url]: [https://huggingface.co/](https://openai.com/)
|
||||||
|
|||||||
@@ -7,17 +7,9 @@ import { Button } from '@/components/ui/button';
|
|||||||
import { Label } from '@/components/ui/label';
|
import { Label } from '@/components/ui/label';
|
||||||
import { Card, CardHeader, CardContent } from '@/components/ui/card';
|
import { Card, CardHeader, CardContent } from '@/components/ui/card';
|
||||||
|
|
||||||
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible"
|
|
||||||
import { ChevronDown } from "lucide-react"
|
|
||||||
|
|
||||||
import { PersonForm } from './PatientForm';
|
|
||||||
|
|
||||||
import { useRouter } from 'next/navigation';
|
|
||||||
|
|
||||||
const AccountPage = () => {
|
const AccountPage = () => {
|
||||||
const { user } = useUser();
|
const { user } = useUser();
|
||||||
const [userData, setUserData] = useState(null);
|
const [userData, setUserData] = useState(null);
|
||||||
const [patients, setPatients] = useState([]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (user) {
|
if (user) {
|
||||||
@@ -72,33 +64,6 @@ const AccountPage = () => {
|
|||||||
<Button onClick={handleRoleChange} className="mb-4">
|
<Button onClick={handleRoleChange} className="mb-4">
|
||||||
Change role to {userData.role === 'patient' ? 'caregiver' : 'patient'}
|
Change role to {userData.role === 'patient' ? 'caregiver' : 'patient'}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
{userData.role === 'caregiver' && (
|
|
||||||
<div>
|
|
||||||
<h2 className="text-xl font-bold mb-4">Patients</h2>
|
|
||||||
<ul className="mb-4">
|
|
||||||
{patients.map(patient => (
|
|
||||||
<Collapsible key={patient.id}>
|
|
||||||
<div className="flex items-center justify-between p-2 bg-gray-100 dark:bg-neutral-800 rounded-t-lg">
|
|
||||||
<div>
|
|
||||||
<h2 className="text-lg font-semibold">{patient.name}</h2>
|
|
||||||
<p className="text-sm text-gray-400">{patient.role}</p>
|
|
||||||
</div>
|
|
||||||
<CollapsibleTrigger asChild>
|
|
||||||
<Button variant="ghost" size="sm">
|
|
||||||
<ChevronDown className="h-4 w-4" />
|
|
||||||
<span className="sr-only">Toggle</span>
|
|
||||||
</Button>
|
|
||||||
</CollapsibleTrigger>
|
|
||||||
</div>
|
|
||||||
<CollapsibleContent className="p-4 border border-t-0 rounded-b-lg">
|
|
||||||
<PersonForm person={patient} />
|
|
||||||
</CollapsibleContent>
|
|
||||||
</Collapsible>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
33
src/app/(panels)/suite/doctor/dashboard/AppList.jsx
Normal file
33
src/app/(panels)/suite/doctor/dashboard/AppList.jsx
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import { Table, TableBody, TableCaption, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"
|
||||||
|
import { Card, CardContent } from "@/components/ui/card"
|
||||||
|
|
||||||
|
export function AppointmentList({ appointments }) {
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<CardContent>
|
||||||
|
<Table>
|
||||||
|
<TableCaption>A list of your upcoming appointments.</TableCaption>
|
||||||
|
<TableHeader>
|
||||||
|
<TableRow>
|
||||||
|
<TableHead className="w-[100px]">ID</TableHead>
|
||||||
|
<TableHead>Date</TableHead>
|
||||||
|
<TableHead>Status</TableHead>
|
||||||
|
</TableRow>
|
||||||
|
</TableHeader>
|
||||||
|
<TableBody>
|
||||||
|
{appointments.map((appointment) => {
|
||||||
|
return (
|
||||||
|
<TableRow key={appointment.id}>
|
||||||
|
<TableCell className="font-medium">{appointment.id}</TableCell>
|
||||||
|
<TableCell>{new Date(appointment.date).toLocaleString()}</TableCell>
|
||||||
|
<TableCell>{appointment.status}</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,12 +1,15 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import { PatientTable } from "./PatientTable"
|
import { PatientTable } from "./PatientTable"
|
||||||
|
import { AppointmentList } from "./AppList"
|
||||||
|
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { useUser } from '@clerk/nextjs';
|
import { useUser } from '@clerk/nextjs';
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
|
||||||
export default function Dashboard() {
|
export default function Dashboard() {
|
||||||
|
|
||||||
@@ -34,11 +37,21 @@ export default function Dashboard() {
|
|||||||
{ id: 3, name: "Sam Johnson", age: 40, lastVisit: "2024-10-05" },
|
{ id: 3, name: "Sam Johnson", age: 40, lastVisit: "2024-10-05" },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
|
const appointments = [
|
||||||
|
{ id: 1, patientId: 1, date: "2025-01-27T09:00:00", status: "Scheduled" },
|
||||||
|
{ id: 2, patientId: 2, date: "2025-01-27T10:30:00", status: "Scheduled" },
|
||||||
|
{ id: 3, patientId: 3, date: "2025-01-27T14:00:00", status: "Scheduled" },
|
||||||
|
{ id: 4, patientId: 4, date: "2025-01-28T11:00:00", status: "Scheduled" },
|
||||||
|
{ id: 5, patientId: 5, date: "2025-01-28T15:30:00", status: "Scheduled" },
|
||||||
|
]
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="container mx-auto">
|
<div className="container mx-auto">
|
||||||
<h1 className="text-3xl font-semibold mb-6">Dashboard</h1>
|
<h1 className="text-3xl font-semibold mb-6">Dashboard</h1>
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
<div className="h-20 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||||
<PatientTable data={patients} />
|
<PatientTable data={patients} />
|
||||||
|
<AppointmentList appointments={appointments} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
76
src/app/(panels)/suite/doctor/patient/page.jsx
Normal file
76
src/app/(panels)/suite/doctor/patient/page.jsx
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
|
||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
|
import { useRouter } from "next/navigation";
|
||||||
|
|
||||||
|
import axios from "axios";
|
||||||
|
import { useUser } from "@clerk/nextjs";
|
||||||
|
import { CardContent } from "@/components/ui/card";
|
||||||
|
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { ChevronDown } from "lucide-react";
|
||||||
|
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible";
|
||||||
|
import PersonForm from "@/components/PersonForm";
|
||||||
|
import { Card } from "@/components/ui/card";
|
||||||
|
|
||||||
|
|
||||||
|
export default function Dashboard() {
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
const { user } = useUser();
|
||||||
|
const [userData, setUserData] = useState(null);
|
||||||
|
const [patients, setPatients] = useState([]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (user) {
|
||||||
|
axios.get(`/api/user?userId=${user.id}`).then(response => {
|
||||||
|
setUserData(response.data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [user]);
|
||||||
|
|
||||||
|
if (userData) {
|
||||||
|
if (userData.role != "caregiver") {
|
||||||
|
router.push("/suite/patient/dashboard");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="container mx-auto">
|
||||||
|
<h1 className="text-3xl font-semibold mb-6">Patients</h1>
|
||||||
|
<div className="h-20 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||||
|
<Card>
|
||||||
|
<CardContent>
|
||||||
|
{userData.role === 'caregiver' && (
|
||||||
|
<div>
|
||||||
|
<ul className="mb-4">
|
||||||
|
{patients.map(patient => (
|
||||||
|
<Collapsible key={patient.id}>
|
||||||
|
<div className="flex items-center justify-between p-2 bg-gray-100 dark:bg-neutral-800 rounded-t-lg">
|
||||||
|
<div>
|
||||||
|
<h2 className="text-lg font-semibold">{patient.name}</h2>
|
||||||
|
<p className="text-sm text-gray-400">{patient.role}</p>
|
||||||
|
</div>
|
||||||
|
<CollapsibleTrigger asChild>
|
||||||
|
<Button variant="ghost" size="sm">
|
||||||
|
<ChevronDown className="h-4 w-4" />
|
||||||
|
<span className="sr-only">Toggle</span>
|
||||||
|
</Button>
|
||||||
|
</CollapsibleTrigger>
|
||||||
|
</div>
|
||||||
|
<CollapsibleContent className="p-4 border border-t-0 rounded-b-lg">
|
||||||
|
<PersonForm person={patient} />
|
||||||
|
</CollapsibleContent>
|
||||||
|
</Collapsible>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,9 +1,20 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
//import Hero1 from '@/components/Hero1'
|
//import Hero1 from '@/components/Hero1'
|
||||||
//IMPORT THE HERO1 FUNCTION TO MAKE THE TRANSCRIBE PAGE LOOK BETTER
|
//IMPORT THE HERO1 FUNCTION TO MAKE THE TRANSCRIBE PAGE LOOK BETTER
|
||||||
import React, { useState, useRef } from "react";
|
import React, { useState, useRef } from "react";
|
||||||
// import axios from "axios";
|
// import axios from "axios";
|
||||||
|
|
||||||
|
import { AlertCircle } from "lucide-react"
|
||||||
|
|
||||||
|
import {
|
||||||
|
Alert,
|
||||||
|
AlertDescription,
|
||||||
|
AlertTitle,
|
||||||
|
} from "@/components/ui/alert"
|
||||||
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
|
|
||||||
const AudioTranscriber: React.FC = () => {
|
const AudioTranscriber: React.FC = () => {
|
||||||
const [file, setFile] = useState<File | null>(null);
|
const [file, setFile] = useState<File | null>(null);
|
||||||
const [transcription, setTranscription] = useState<string | null>(null);
|
const [transcription, setTranscription] = useState<string | null>(null);
|
||||||
@@ -32,7 +43,6 @@ const AudioTranscriber: React.FC = () => {
|
|||||||
|
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append("file", audioFile);
|
formData.append("file", audioFile);
|
||||||
console.log(audioFile);
|
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
setError(null); // Clear previous errors
|
setError(null); // Clear previous errors
|
||||||
try {
|
try {
|
||||||
@@ -44,8 +54,9 @@ const AudioTranscriber: React.FC = () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
console.log("! response:", response);
|
||||||
response = await response.json();
|
response = await response.json();
|
||||||
console.log("Transcription response:", response);
|
console.log("@ response:", response);
|
||||||
|
|
||||||
// if (response.data && response.data.transcription) {
|
// if (response.data && response.data.transcription) {
|
||||||
// setTranscription(response.data.transcription);
|
// setTranscription(response.data.transcription);
|
||||||
@@ -107,49 +118,56 @@ const AudioTranscriber: React.FC = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<section className="mx-auto my-auto bg-white dark:bg-neutral-950 h-screen w-1/2">
|
||||||
<h1>
|
<h1 className="text-4xl font-bold text-center mb-8">
|
||||||
<center>
|
<center>
|
||||||
Audio Transcription
|
Audio Transcription
|
||||||
</center>
|
</center>
|
||||||
</h1>
|
</h1>
|
||||||
|
<br />
|
||||||
<div>
|
<div>
|
||||||
<h2>Upload or Record Audio</h2>
|
<h2>Upload or Record Audio</h2>
|
||||||
|
|
||||||
<input type="file" accept="audio/*" onChange={handleFileChange} />
|
<Input type="file" accept="audio/*" onChange={handleFileChange} />
|
||||||
<button onClick={() => file && handleTranscription(file)} disabled={loading || !file}>
|
<Button className="my-4" onClick={() => file && handleTranscription(file)} disabled={loading || !file}>
|
||||||
{loading ? "Transcribing..." : "Transcribe"}
|
{loading ? "Transcribing..." : "Transcribe"}
|
||||||
</button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<h2>Record Audio</h2>
|
<h2>Record Audio</h2>
|
||||||
{!recording ? (
|
{!recording ? (
|
||||||
<button onClick={startRecording}>Start Recording</button>
|
<Button onClick={startRecording}>Start Recording</Button>
|
||||||
) : (
|
) : (
|
||||||
<button onClick={stopRecording} disabled={!recording}>
|
<Button onClick={stopRecording} disabled={!recording}>Stop Recording</Button>
|
||||||
Stop Recording
|
|
||||||
</button>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<Card className="mt-4 bg-neutral-200 dark:bg-neutral-800">
|
||||||
<h2>Transcription:</h2>
|
<CardHeader>
|
||||||
{loading ? (
|
<CardTitle>Transcription Result</CardTitle>
|
||||||
<p>Processing transcription...</p>
|
</CardHeader>
|
||||||
) : transcription ? (
|
<CardContent>
|
||||||
<p>{transcription}</p>
|
<CardContent>
|
||||||
) : (
|
{loading
|
||||||
<p>No transcription available yet.</p>
|
? "Processing transcription..."
|
||||||
)}
|
: transcription
|
||||||
</div>
|
? "Your transcription is ready"
|
||||||
|
: "No transcription available yet"}
|
||||||
|
</CardContent>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
{error && (
|
{error && (
|
||||||
<div style={{ color: "red" }}>
|
<Alert variant="destructive">
|
||||||
|
<AlertCircle className="h-4 w-4" />
|
||||||
|
<AlertTitle>Error</AlertTitle>
|
||||||
|
<AlertDescription>
|
||||||
<strong>Error:</strong> {error}
|
<strong>Error:</strong> {error}
|
||||||
</div>
|
</AlertDescription>
|
||||||
|
</Alert>
|
||||||
)}
|
)}
|
||||||
</div>
|
</section>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,6 @@
|
|||||||
"@/*": ["./src/*"]
|
"@/*": ["./src/*"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"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", "src/app/(panels)/suite/patient/account/page.jsx", "src/app/(panels)/suite/patient/dashboard/MedicationTable.jsx", "src/app/(panels)/suite/patient/dashboard/page.jsx", "src/app/api/transcribe/route.js", "src/components/ui/calendar.jsx", "src/app/(web)/page.jsx", "src/app/(web)/transcribe/page.jsx", "src/app/(web)/login/page.jsx", "src/app/(panels)/suite/layout.jsx", "src/app/(panels)/suite/doctor/dashboard/page.jsx", "src/app/(panels)/suite/patient/chat/page.jsx", "src/app/api/chat/route.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", "src/app/(panels)/suite/patient/account/page.jsx", "src/app/(panels)/suite/patient/dashboard/MedicationTable.jsx", "src/app/(panels)/suite/patient/dashboard/page.jsx", "src/app/api/transcribe/route.js", "src/components/ui/calendar.jsx", "src/app/(web)/page.jsx", "src/app/(web)/transcribe/page.jsx", "src/app/(web)/login/page.jsx", "src/app/(panels)/suite/layout.jsx", "src/app/(panels)/suite/doctor/dashboard/page.jsx", "src/app/(panels)/suite/patient/chat/page.jsx", "src/app/(panels)/suite/doctor/dashboard/AppList.jsx", "src/app/(panels)/suite/doctor/patient/page.jsx"],
|
||||||
"exclude": ["node_modules"]
|
"exclude": ["node_modules"]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user