Modern React/Next.js web application providing an intuitive interface for healthcare professionals to assess cardiovascular disease risk using AI-powered predictions.
- Professional healthcare-focused design
- Comprehensive patient assessment form
- Real-time risk calculation and visualization
- Example patient data for testing
- Responsive design for all devices
- Shadcn/UI component library
- Tailwind CSS for styling
- Accessibility-compliant interface
- TypeScript for type safety
- ESLint for code quality
- Performance optimized
- SEO optimized
frontend/
βββ src/
β βββ app/ # Next.js app directory
β β βββ page.tsx # Main assessment page
β β βββ layout.tsx # Root layout
β β βββ globals.css # Global styles
β βββ components/
β β βββ CVDAssessmentForm.tsx # Main form component
β β βββ PredictionResult.tsx # Results display
β β βββ ui/ # Reusable UI components
β β βββ button.tsx
β β βββ card.tsx
β β βββ form.tsx
β β βββ input.tsx
β β βββ select.tsx
β βββ lib/
β βββ utils.ts # Utility functions
βββ public/ # Static assets
βββ package.json # Dependencies
βββ next.config.ts # Next.js configuration
βββ tailwind.config.ts # Tailwind configuration
βββ tsconfig.json # TypeScript configuration
βββ README.md # This file
- Node.js 20.9+
- pnpm 10.x
cd frontend
pnpm installpnpm devVisit http://localhost:3000 to view the application.
pnpm build
pnpm startMain form component handling patient data input and validation.
Features:
- Comprehensive medical form with validation
- Auto-calculation of derived metrics (BMI, ratios)
- Example data loading for testing
- Real-time field validation
- Professional medical interface
Key Sections:
- Demographics (age, sex, height, weight)
- Vital Signs (blood pressure, heart rate)
- Laboratory Values (cholesterol, glucose)
- Risk Factors (smoking, diabetes, family history)
- Additional Measurements (waist circumference)
Results display component showing risk assessment.
Features:
- Risk level visualization (Low/Intermediate/High)
- Confidence scores and probabilities
- Clinical recommendations
- Model accuracy information
- Printable results format
Update API endpoints in components:
// CVDAssessmentForm.tsx
const API_BASE_URL =
process.env.NEXT_PUBLIC_API_BASE_URL || "https://cvdapi.imurad.me";
const response = await fetch(`${API_BASE_URL}/api/predict`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(patientData),
});Create .env.local:
NEXT_PUBLIC_API_BASE_URL=https://cvdapi.imurad.me
NEXT_PUBLIC_APP_NAME="CVD Risk Assessment"
NEXT_PUBLIC_MODEL_VERSION="1.0"Built with Shadcn/UI for professional appearance:
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Select } from "@/components/ui/select";
import { Card } from "@/components/ui/card";Tailwind CSS classes for responsive design:
<div className="min-h-screen bg-gradient-to-br from-blue-50 to-indigo-100 p-4">
<div className="max-w-4xl mx-auto">
<Card className="shadow-lg">{/* Content */}</Card>
</div>
</div>- Mobile: < 768px
- Tablet: 768px - 1024px
- Desktop: > 1024px
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{/* Form fields */}
</div>const validateAge = (age: number) => {
if (age < 18 || age > 100) {
return "Age must be between 18 and 100";
}
return null;
};
const validateBP = (systolic: number, diastolic: number) => {
if (systolic <= diastolic) {
return "Systolic must be greater than diastolic";
}
return null;
};All clinical fields are marked as required:
<Input
type="number"
required
min="18"
max="100"
value={formData.Age}
onChange={(e) => handleInputChange("Age", e.target.value)}
/>Not configured in this repo yet.
Not configured in this repo yet.
// __tests__/CVDAssessmentForm.test.tsx
import { render, screen } from "@testing-library/react";
import CVDAssessmentForm from "@/components/CVDAssessmentForm";
test("renders assessment form", () => {
render(<CVDAssessmentForm onSubmit={jest.fn()} />);
expect(screen.getByText("Patient Assessment Form")).toBeInTheDocument();
});// Lazy load heavy components
const PredictionResult = dynamic(() => import("./PredictionResult"), {
loading: () => <div>Loading...</div>,
});import Image from "next/image";
<Image
src="/medical-icon.svg"
alt="Medical Icon"
width={64}
height={64}
priority
/>;pnpm add -g vercel
vercelFROM node:20-alpine
WORKDIR /app
RUN corepack enable
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile --prod
COPY . .
RUN pnpm build
EXPOSE 3000
CMD ["pnpm", "start"]# Production environment variables
NEXT_PUBLIC_API_BASE_URL=https://cvdapi.imurad.me
NEXT_PUBLIC_GA_ID=G-XXXXXXXXXX
NODE_ENV=production- Patient Input: Enter comprehensive medical data
- Validation: Real-time field validation and checks
- Prediction: Submit for AI risk assessment
- Results: View risk level and recommendations
- Action: Use results for clinical decision making
- π’ LOW RISK: Routine monitoring recommended
- π‘ INTERMEDIATE: Enhanced screening suggested
- π΄ HIGH RISK: Immediate clinical intervention
Quick testing with realistic patient scenarios:
- Low risk: Young, healthy patient profile
- High risk: Multiple risk factors present
{
"next": "^14.0.0",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"typescript": "^5.0.0"
}{
"@radix-ui/react-select": "^2.0.0",
"tailwindcss": "^3.3.0",
"class-variance-authority": "^0.7.0",
"clsx": "^2.0.0",
"tailwind-merge": "^2.0.0"
}{
"eslint": "^8.0.0",
"eslint-config-next": "^14.0.0",
"@types/react": "^18.0.0",
"@types/node": "^20.0.0"
}- Semantic HTML structure
- Proper ARIA labels
- Keyboard navigation support
- Screen reader compatibility
- Color contrast compliance
<Label htmlFor="age" className="sr-only">
Patient Age
</Label>
<Input
id="age"
aria-describedby="age-help"
aria-required="true"
type="number"
/>π― Professional healthcare interface for clinical CVD risk assessment!