AI Health Assistant Functions Overview
AI Health Assistant Functions Overview
ts
import { config } from 'dotenv';
config();
/**
* @fileOverview A flow that answers a user's health-related question.
*
* - answerUserQuery - A function that answers a user's question based on their health data.
* - AnswerUserQueryInput - The input type for the answerUserQuery function.
* - AnswerUserQueryOutput - The return type for the answerUserQuery function.
*/
If the user asks who you are or what your name is, you must respond: "My name is <b>SenAssist</b>, and I
Based on the user's data, provide clear answers to their questions. If their question is related to thei
For very common and non-critical symptoms (like a mild headache or a common cold), you can suggest basic
Here is some context about the user, use it to inform your answer:
- Vitals Data: {{vitalsData}}
- BMI: {{bmi}}
- BMR: {{bmr}}
Keep your answer concise and easy for a layperson to understand. Provide only the answer to the question
IMPORTANT: When you mention a specific vital sign name (e.g., Heart Rate, SpO2), a reading (e.g., 120/80
`,
});
/**
* @fileOverview A health recommendation AI agent.
*
* - generateHealthRecommendations - A function that generates health recommendations based on vital rea
* - GenerateHealthRecommendationsInput - The input type for the generateHealthRecommendations function.
* - GenerateHealthRecommendationsOutput - The return type for the generateHealthRecommendations functio
*/
Analyze the user's data and compare it against these standard health guidelines:
- **Heart Rate**: Normal resting is 60-100 bpm.
- **SpO2**: Normal is 95-100%. Below 92% is a concern.
- **Blood Pressure**: Normal is below 120/80 mmHg.
- **Body Temperature**: Normal is 36.5°C-37.5°C.
- **Blood Sugar (Fasting)**: Normal is 70-100 mg/dL.
User's Vitals:
{{#each readings}}
- **{{type}}**: {{value}} {{unit}}
{{/each}}
User's Metrics:
- **BMI**: {{bmi}}
- **BMR**: {{bmr}}
Based on this data, provide up to 3 specific recommendations.
1. **Prioritize abnormalities**: Only generate a recommendation if a vital sign is outside the normal r
2. **Be specific and actionable**: Instead of "eat healthier," suggest "Consider adding a serving of le
3. **Keep it concise**: Each recommendation's text must be under 140 characters.
4. **Categorize correctly**: Assign 'diet', 'lifestyle', or 'medicine' to each item. For 'medicine', su
5. **Set a timestamp**: Use a human-readable relative timestamp for 'createdAt' (e.g., "Just now").
They have provided the following information about their current state:
- Current Emotion: {{emotion}}
- Trigger: {{trigger}}
- Feels Hungry: {{#if isHungry}}Yes{{else}}No{{/if}}
- Feels Thirsty: {{#if isThirsty}}Yes{{else}}No{{/if}}
Based on this, provide a short, calming, and actionable response. Your response should:
1. Acknowledge their feeling without judgment (e.g., "It's completely understandable to feel {{emotion}
2. Suggest a simple, immediate action to distract them. Examples:
- If thirsty, suggest drinking a large glass of water.
- If hungry, suggest a healthy snack.
- Suggest a 5-minute breathing exercise: "Breathe in for 4 seconds, hold for 4, and exhale for 6."
- Suggest a short walk or changing their environment.
3. Gently challenge the idea that giving in will solve the problem. For example: "Think about this: wil
4. Keep the entire response concise, empathetic, and under 150 words.
/**
* @fileOverview A flow that summarizes a user's vitals.
*
* - provideVitalsSummary - A function that handles the vitals summarization process.
* - ProvideVitalsSummaryInput - The input type for the provideVitalsSummary function.
* - ProvideVitalsSummaryOutput - The return type for the provideVitalsSummary function.
*/
Based on this information, provide a concise summary of the user's current health status. Start by add
IMPORTANT: When you mention a specific vital sign name (e.g., Heart Rate, SpO2), a reading (e.g., 120/
`,
});
// For now, return a static success message to avoid unnecessary LLM calls.
return {
message: "Thank you for your feedback! We've received your message and appreciate you helping us
}
}
);
Explanation not written yet, but this file contributes to the app's functionality.
src/app/[Link]
@tailwind base;
@tailwind components;
@tailwind utilities;
body {
font-family: Arial, Helvetica, sans-serif;
}
@layer base {
:root {
--background: 220 20% 96%;
--foreground: 224 71.4% 4.1%;
--card: 220 20% 100%;
--card-foreground: 224 71.4% 4.1%;
--popover: 220 20% 100%;
--popover-foreground: 224 71.4% 4.1%;
--primary: 240 60% 50%;
--primary-foreground: 0 0% 100%;
--secondary: 220 40% 94%;
--secondary-foreground: 240 60% 30%;
--muted: 220 20% 92%;
--muted-foreground: 220 10% 40%;
--accent: 260 70% 60%;
--accent-foreground: 0 0% 100%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 0 0% 98%;
--border: 220 20% 88%;
--input: 220 20% 91%;
--ring: 240 60% 50%;
--chart-1: 240 50% 55%;
--chart-2: 260 60% 65%;
--chart-3: 280, 70%, 70%;
--chart-4: 210 50% 55%;
--chart-5: 220 40% 60%;
--radius: 0.5rem;
--sidebar-background: 222 47% 11%;
--sidebar-foreground: 210 40% 98%;
--sidebar-primary: 240 5.9% 10%;
--sidebar-primary-foreground: 0 0% 98%;
--sidebar-accent: 240 60% 50%;
--sidebar-accent-foreground: 0 0% 100%;
--sidebar-border: 217 32% 17%;
--sidebar-ring: 240 50% 60%;
}
.dark {
--background: 222 47% 11%;
--foreground: 210 40% 98%;
--card: 222 47% 14%;
--card-foreground: 210 40% 98%;
--popover: 222 47% 11%;
--popover-foreground: 210 40% 98%;
--primary: 240 70% 70%;
--primary-foreground: 240 70% 10%;
--secondary: 220 20% 20%;
--secondary-foreground: 210 40% 98%;
--muted: 217 32% 17%;
--muted-foreground: 215 20% 65%;
--accent: 260 80% 75%;
--accent-foreground: 260 80% 10%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 0 0% 98%;
--border: 217 32% 22%;
--input: 217 32% 17%;
--ring: 240 70% 80%;
--chart-1: 240 60% 60%;
--chart-2: 260 70% 70%;
--chart-3: 280, 80%, 75%;
--chart-4: 210 40% 35%;
--chart-5: 220 30% 30%;
--sidebar-background: 222 47% 9%;
--sidebar-foreground: 210 40% 98%;
--sidebar-primary: 224.3 76.3% 48%;
--sidebar-primary-foreground: 0 0% 100%;
--sidebar-accent: 240 70% 70%;
--sidebar-accent-foreground: 240 70% 10%;
--sidebar-border: 222 47% 12%;
--sidebar-ring: 240 70% 80%;
}
}
@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
}
}
Explanation not written yet, but this file contributes to the app's functionality.
src/app/[Link]
'use client';
// Since this is now a client component, metadata should be handled differently if needed,
// but for now we'll keep it simple. Exporting it from a client component has no effect.
// export const metadata: Metadata = {
// title: 'SentrixAI',
// description: 'AI-Powered Smart Health Assistant',
// };
/**
* The root layout for the authenticated part of the app.
* It handles the user's authentication state and provides the AppContext.
*/
export default function Layout({ children }: { children: ReactNode }) {
const pathname = usePathname();
// If we have a user, provide the app context and render the content.
return (
<DashboardLayout>
<[Link]
key={pathname}
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -20 }}
transition={{ duration: 0.3, ease: 'easeInOut' }}
>
{children}
</[Link]>
</DashboardLayout>
);
}
Explanation not written yet, but this file contributes to the app's functionality.
src/app/(dashboard)/analytics/[Link]
'use client';
import {
Card,
CardHeader,
CardTitle,
CardDescription,
CardContent,
} from '@/components/ui/card';
import { Area, AreaChart, CartesianGrid, XAxis, YAxis } from 'recharts';
import {
ChartContainer,
ChartTooltip,
ChartTooltipContent,
} from '@/components/ui/chart';
import { useAppContext } from '@/context/app-context';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import { useState } from 'react';
return (
<div className="p-4 md:p-6 space-y-6">
<Card>
<CardHeader className="flex-row items-center justify-between">
<div>
<CardTitle>Health Analytics</CardTitle>
<CardDescription>
In-depth analysis of your vital signs over time.
</CardDescription>
</div>
<div className="w-[150px]">
<Select value={timeframe} onValueChange={setTimeframe}>
<SelectTrigger>
<SelectValue placeholder="Select timeframe" />
</SelectTrigger>
<SelectContent>
<SelectItem value="7d">Last 7 Days</SelectItem>
<SelectItem value="30d">Last 30 Days</SelectItem>
<SelectItem value="1y">Last Year</SelectItem>
</SelectContent>
</Select>
</div>
</CardHeader>
</Card>
const chartConfig = {
[[Link]]: {
label: [Link],
color: 'hsl(var(--chart-1))',
},
};
return (
<Card key={[Link]} className="transition-all duration-300 hover:shadow-lg hover:-transla
<CardHeader>
<CardTitle className='capitalize'>{[Link]}</CardTitle>
<CardDescription>
Trend for the last {timeframe === '7d' ? '7 days' : timeframe === '30d' ? '30 days' :
</CardDescription>
</CardHeader>
<CardContent>
<div className="h-[250px] w-full">
<ChartContainer
config={chartConfig}
className="h-full w-full"
>
<AreaChart
accessibilityLayer
data={[Link]}
margin={{
left: -10,
right: 12,
top: 10,
bottom: 10,
}}
>
<defs>
<linearGradient id={`fill-${[Link](/\s+/g, '-')}`} x1="0" y1="0"
<stop
offset="5%"
stopColor="hsl(var(--primary))"
stopOpacity={0.8}
/>
<stop
offset="95%"
stopColor="hsl(var(--primary))"
stopOpacity={0.1}
/>
</linearGradient>
</defs>
<CartesianGrid vertical={false} />
<XAxis
dataKey="time"
tickLine={false}
axisLine={false}
tickMargin={8}
/>
<YAxis
domain={['dataMin - 5', 'dataMax + 5']}
tickLine={false}
axisLine={false}
tickMargin={8}
/>
<ChartTooltip
cursor={true}
content={
<ChartTooltipContent
labelKey="value"
nameKey="time"
indicator="line"
/>
}
/>
<Area
dataKey="value"
type="natural"
fill={`url(#fill-${[Link](/\s+/g, '-')})`}
stroke="hsl(var(--primary))"
stackId="a"
strokeWidth={2}
/>
</AreaChart>
</ChartContainer>
</div>
</CardContent>
</Card>
)
})}
</div>
<Card className="mt-6">
<CardHeader>
<CardTitle>More Analytics Coming Soon</CardTitle>
<CardDescription>
We are working on adding more advanced analytics, including AI-powered trend analysis and he
</CardDescription>
</CardHeader>
<CardContent>
<div className="flex items-center justify-center h-48 border-2 border-dashed rounded-lg">
<p className="text-muted-foreground">Advanced comparisons will be here.</p>
</div>
</CardContent>
</Card>
</div>
);
}
Explanation not written yet, but this file contributes to the app's functionality.
src/app/(dashboard)/chat/[Link]
'use client';
interface ChatMessage {
sender: 'user' | 'ai';
text: string;
timestamp: string;
}
const userContext = {
userId: 'user-123',
bmi: 22.5,
bmr: 1680,
vitalsData: [Link]([Link](v => ({type: [Link], value: [Link], ts: [Link]()}))),
};
const getVitalByName = (name: string) => [Link](v => [Link]() === [Link]())
const vitalDisplayData = [
{ name: 'Heart Rate', icon: Heart, vital: getVitalByName('heart rate') },
{ name: 'SpO2', icon: Gauge, vital: getVitalByName('spo2') },
{ name: 'Temp', icon: Thermometer, vital: getVitalByName('temperature') },
{ name: 'BP', icon: Activity, vital: getVitalByName('blood pressure') },
]
useEffect(() => {
const getInitialSummary = async () => {
try {
setMessages([{
sender: 'ai',
text: "Hello! I'm your AI health assistant. I can analyze your current vitals and provide pe
timestamp: format(new Date(), 'p')
}]);
} catch (error) {
[Link]("Failed to get initial summary:", error);
setMessages([{
sender: 'ai',
text: "Sorry, I'm having trouble getting your health summary. Please try again later.",
timestamp: format(new Date(), 'p')
}]);
} finally {
setIsLoading(false);
}
};
getInitialSummary();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const userMessage: ChatMessage = { sender: 'user', text: query, timestamp: format(new Date(), 'p') }
setMessages(prev => [...prev, userMessage]);
setInput('');
setIsResponding(true);
try {
const response = await answerUserQuery({
...userContext,
userQuery: query,
});
const aiMessage: ChatMessage = { sender: 'ai', text: [Link], timestamp: format(new Date()
setMessages(prev => [...prev, aiMessage]);
} catch (error) {
[Link]("Failed to get AI response:", error);
const errorMessage: ChatMessage = { sender: 'ai', text: "Sorry, I'm having trouble connecting. Ple
setMessages(prev => [...prev, errorMessage]);
} finally {
setIsResponding(false);
}
};
const quickActions = [
{ text: "Analyze my current vitals", icon: BarChart },
{ text: "Health recommendations", icon: Lightbulb },
{ text: "Explain my metrics", icon: Heart },
]
return (
<div className="h-[calc(100vh-4rem)] flex flex-col">
<div className='p-4 md:p-6 border-b'>
<div className="flex items-center gap-3 mb-4">
<Bot className="h-8 w-8 text-primary" />
<div>
<h1 className="text-xl font-bold">SenAssist</h1>
<p className="text-sm text-muted-foreground">AI Health Assistant</p>
</div>
</div>
<div>
<p className="text-sm font-medium mb-2 text-muted-foreground">Your Current Vitals</p>
<div className="flex items-center gap-4 text-sm">
{[Link](({name, icon: Icon, vital}) => (
vital ? (
<div key={name} className="flex items-center gap-2">
<Icon className="h-4 w-4 text-primary" />
<span>{name}: <b>{[Link]} {[Link]}</b></span>
</div>
) : null
))}
</div>
</div>
</div>
<div className="flex-1 overflow-y-auto p-4 md:p-6">
<div className="space-y-6">
{[Link]((message, index) => (
<div key={index} className={`flex items-start gap-3 ${[Link] === 'user' ? 'justify
{[Link] === 'ai' && <AiAvatar />}
<div className={`flex-1 rounded-lg p-3 max-w-xl ${[Link] === 'ai' ? 'bg-muted' :
<p className="text-sm leading-relaxed" dangerouslySetInnerHTML={{ __html: [Link]
<p className={`text-xs mt-2 ${[Link] === 'ai' ? 'text-muted-foreground' : 'te
</div>
</div>
))}
{isResponding && (
<div className="flex items-start gap-3">
<AiAvatar />
<div className="flex-1 rounded-lg bg-muted p-3">
<div className="flex items-center gap-2">
<Loader2 className="h-4 w-4 animate-spin" />
<p className="text-sm text-muted-foreground">Thinking...</p>
</div>
</div>
</div>
)}
</div>
</div>
<div className="p-4 md:p-6 border-t bg-background">
<div className='flex items-center gap-2 mb-3 overflow-x-auto pb-2'>
{[Link](({text, icon: Icon}) => (
<Button
key={text}
variant="outline"
size="sm"
className="shrink-0"
onClick={(e) => handleSendMessage(e, text)}
disabled={isResponding}
>
<Icon className="mr-2 h-4 w-4"/>
{text}
</Button>
))}
</div>
<form onSubmit={handleSendMessage} className="relative w-full">
<Input
placeholder="Ask me about your health, symptoms, or request advice..."
className="pr-12"
value={input}
onChange={(e) => setInput([Link])}
disabled={isLoading || isResponding}
/>
<Button size="icon" className="absolute top-1/2 right-1.5 -translate-y-1/2 h-7 w-7" type="su
<Send className="h-4 w-4" />
<span className="sr-only">Send</span>
</Button>
</form>
</div>
</div>
);
}
Explanation not written yet, but this file contributes to the app's functionality.
src/app/(dashboard)/connect/[Link]
import { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter } from "@/components/ui/c
import { Button } from "@/components/ui/button";
import { Progress } from "@/components/ui/progress";
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
import { Bluetooth, AlertTriangle } from "lucide-react";
const getVital = (name: string): Vital | undefined => [Link](v => [Link] === name);
return (
<div className="p-4 md:p-6 space-y-6">
<div>
<h1 className="text-2xl font-bold font-headline">Hey, {userProfile?.firstName}!</h1>
<p className="text-muted-foreground">
Overall Health Status: <span className="text-green-500 font-bold">Good</span>
</p>
</div>
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
{heartRate && <StatCard vital={heartRate} />}
{spo2 && <StatCard vital={spo2} />}
{bloodSugar && <div className="lg:row-span-2"><StatCard vital={bloodSugar} /></div>}
{calories && <div className="lg:row-span-2"><StatCard vital={calories} /></div>}
import {
Card,
CardHeader,
CardTitle,
CardDescription,
CardContent,
} from '@/components/ui/card';
import { Button } from '@/components/ui/button';
import Link from 'next/link';
import { useParams } from 'next/navigation';
import { useAppContext } from '@/context/app-context';
import { Area, AreaChart, CartesianGrid, XAxis, YAxis } from 'recharts';
import {
ChartContainer,
ChartTooltip,
ChartTooltipContent,
} from '@/components/ui/chart';
import { Loading } from '@/components/loading';
import { ArrowLeft } from 'lucide-react';
if (!vital) {
return <Loading />;
}
const chartConfig = {
[[Link]]: {
label: [Link],
color: 'hsl(var(--chart-1))',
},
};
return (
<div className="p-4 md:p-6 space-y-4">
<Button variant="outline" asChild>
<Link href="/dashboard">
<ArrowLeft className="mr-2" /> Back to Dashboard
</Link>
</Button>
<Card>
<CardHeader>
<CardTitle className="capitalize text-3xl">{[Link]}</CardTitle>
<CardDescription>
Detailed historical data and analysis for {[Link]}.
</CardDescription>
</CardHeader>
<CardContent className="space-y-6">
<div className="text-center bg-muted p-6 rounded-lg">
<p className="text-sm text-muted-foreground">Current Reading</p>
<p className="text-5xl font-bold text-primary">
{[Link]}
<span className="text-lg ml-2 text-muted-foreground">
{[Link]}
</span>
</p>
<p className="text-xs text-muted-foreground mt-1">{[Link]}</p>
</div>
<div>
<h3 className="text-lg font-semibold mb-2">Historical Data</h3>
<div className="h-[400px] w-full">
<ChartContainer
config={chartConfig}
className="h-full w-full"
>
<AreaChart
accessibilityLayer
data={[Link]}
margin={{
left: 12,
right: 12,
top: 10,
bottom: 10,
}}
>
<defs>
<linearGradient id="fill-color" x1="0" y1="0" x2="0" y2="1">
<stop
offset="5%"
stopColor="var(--color-value)"
stopOpacity={0.8}
/>
<stop
offset="95%"
stopColor="var(--color-value)"
stopOpacity={0.1}
/>
</linearGradient>
</defs>
<CartesianGrid vertical={false} />
<XAxis
dataKey="time"
tickLine={false}
axisLine={false}
tickMargin={8}
/>
<YAxis
domain={['dataMin - 5', 'dataMax + 5']}
tickLine={false}
axisLine={false}
tickMargin={8}
/>
<ChartTooltip
cursor={true}
content={
<ChartTooltipContent
labelKey="value"
nameKey="time"
indicator="line"
/>
}
/>
<Area
dataKey="value"
type="natural"
fill="url(#fill-color)"
stroke="var(--color-value)"
stackId="a"
strokeWidth={2}
/>
</AreaChart>
</ChartContainer>
</div>
</div>
</CardContent>
</Card>
</div>
);
}
Explanation not written yet, but this file contributes to the app's functionality.
src/app/(dashboard)/emergency/[Link]
'use client';
return (
<APIProvider apiKey={apiKey}>
<div className="p-4 md:p-6 grid gap-6 grid-cols-1 lg:grid-cols-3 h-[calc(100vh-4rem)]">
<div className="lg:col-span-2 flex flex-col gap-6">
<Card>
<CardHeader>
<CardTitle>Emergency Assistance</CardTitle>
<CardDescription>
Find nearby medical facilities. For emergencies, call your local emergency numbe
</CardDescription>
</CardHeader>
<CardContent>
<form onSubmit={handleSearch} className="flex flex-col sm:flex-row gap-2">
<Input
placeholder="Enter your city, or a facility name..."
value={searchQuery}
onChange={(e) => setSearchQuery([Link])}
/>
<Button type="submit" disabled={isLoading}>
{isLoading ? <Loader2 className="mr-2 h-4 w-4 animate-spin"/> : <Search classN
Search
</Button>
</form>
</CardContent>
</Card>
<Card className="flex-1">
<CardContent className="p-0 h-full">
<Map
defaultCenter={{ lat: 28.6139, lng: 77.2090 }} // Default to New Delhi
defaultZoom={12}
mapId="emergency_map"
className="h-full w-full rounded-lg"
/>
</CardContent>
</Card>
</div>
<div className="lg:col-span-1">
<Card className="sticky top-20 transition-all duration-300 hover:shadow-lg hover:-translat
<CardHeader className="text-center">
<div className="mx-auto bg-primary/10 text-primary p-3 rounded-full w-fit">
<MessageSquare className="h-8 w-8" />
</div>
<CardTitle className="mt-4">Need Instant Help?</CardTitle>
<CardDescription>
If you're unsure about your symptoms or need quick advice, our AI assistant is h
</CardDescription>
</CardHeader>
<CardContent>
<Button size="lg" className="w-full" asChild>
<Link href="/chat">
Ask SenAssist
</Link>
</Button>
<p className="text-xs text-muted-foreground mt-4 text-center">
SenAssist can provide information but is not a substitute for professional med
</p>
</CardContent>
</Card>
</div>
</div>
</APIProvider>
);
}
Explanation not written yet, but this file contributes to the app's functionality.
src/app/(dashboard)/feedback/[Link]
'use client';
setIsLoading(true);
try {
const response = await submitFeedback({
feedbackText,
userId: user?.uid,
});
toast({
title: 'Feedback Submitted!',
description: [Link],
});
setFeedbackText('');
} catch (error) {
[Link]('Failed to submit feedback:', error);
toast({
variant: 'destructive',
title: 'Submission Failed',
description: 'There was a problem submitting your feedback. Please try again.',
});
} finally {
setIsLoading(false);
}
};
return (
<div className="p-4 md:p-6 flex justify-center">
<Card className="w-full max-w-2xl transition-all duration-300 hover:shadow-lg hover:-translate-y-1
<CardHeader>
<CardTitle>Submit Feedback</CardTitle>
<CardDescription>
We'd love to hear your thoughts! What's working well? What could be better?
</CardDescription>
</CardHeader>
<CardContent>
<form onSubmit={handleSubmit} className="space-y-6">
<div className="space-y-2">
<Label htmlFor="feedback-textarea">Your Feedback</Label>
<Textarea
id="feedback-textarea"
placeholder="Please be as detailed as possible..."
value={feedbackText}
onChange={e => setFeedbackText([Link])}
rows={8}
required
disabled={isLoading}
/>
</div>
<Button type="submit" className="w-full" disabled={isLoading}>
{isLoading ? (
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
) : (
<Send className="mr-2 h-4 w-4" />
)}
Submit Feedback
</Button>
</form>
</CardContent>
</Card>
</div>
);
}
Explanation not written yet, but this file contributes to the app's functionality.
src/app/(dashboard)/intake/[Link]
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { TargetTab } from "@/components/tools/target-tab";
import { CaloriesTab } from "@/components/tools/calories-tab";
import { Card, CardHeader, CardTitle, CardDescription, CardContent } from "@/components/ui/card";
updateVitals(vitalType, valueNum);
toast({
title: 'Vital Logged!',
description: `${vitalType} reading of ${vitalValue} has been saved.`,
});
setVitalType('');
setVitalValue('');
};
return (
<div className="p-4 md:p-6 flex justify-center">
<Card className="w-full max-w-md transition-all duration-300 hover:shadow-lg hover:-translate-y-1"
<CardHeader>
<CardTitle>Log a New Vital Reading</CardTitle>
<CardDescription>
Manually enter a new measurement for one of your vital signs.
</CardDescription>
</CardHeader>
<CardContent>
<form onSubmit={handleSubmit} className="space-y-6">
<div className="space-y-2">
<Label htmlFor="vital-type">Vital Sign</Label>
<Select onValueChange={(value: VitalSign) => setVitalType(value)} value={vitalType}>
<SelectTrigger id="vital-type">
<SelectValue placeholder="Select a vital to log..." />
</SelectTrigger>
<SelectContent>
{[Link](vitalName => (
<SelectItem key={vitalName} value={vitalName}>
{vitalName}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
<div className="space-y-2">
<Label htmlFor="vital-value">
Reading {selectedVital ? `(${[Link]})` : ''}
</Label>
<Input
id="vital-value"
type="number"
step="any"
placeholder={selectedVital ? `e.g. ${[Link]}` : 'Enter value'}
value={vitalValue}
onChange={e => setVitalValue([Link])}
required
/>
</div>
<Button type="submit" className="w-full">
<ListPlus className="mr-2 h-4 w-4"/>
Log Reading
</Button>
</form>
</CardContent>
</Card>
</div>
);
}
Explanation not written yet, but this file contributes to the app's functionality.
src/app/(dashboard)/profile/[Link]
'use client';
useEffect(() => {
if (!profile) return;
if ([Link]) {
setAge(differenceInYears(new Date(), [Link]));
} else {
setAge(null);
}
// Calculate BMI
const heightInMeters = heightNum / 100;
const bmi = weightNum / (heightInMeters * heightInMeters);
// Calculate BMR (Harris-Benedict equation)
let bmr;
if ([Link] === 'male') {
bmr = 88.362 + (13.397 * weightNum) + (4.799 * heightNum) - (5.677 * currentAge);
} else if ([Link] === 'female') {
bmr = 447.593 + (9.247 * weightNum) + (3.098 * heightNum) - (4.330 * currentAge);
} else {
// Average for 'other'
const bmrMale = 88.362 + (13.397 * weightNum) + (4.799 * heightNum) - (5.677 * currentAge);
const bmrFemale = 447.593 + (9.247 * weightNum) + (3.098 * heightNum) - (4.330 * currentAge);
bmr = (bmrMale + bmrFemale) / 2;
}
setCalculatedMetrics({
bmi: parseFloat([Link](1)),
bmr: [Link](dailyCalories),
});
};
calculateMetrics();
}, [profile]);
if (!profile) {
return <Loading />
}
return (
<div className="p-4 md:p-6 grid gap-6 lg:grid-cols-3">
<Card className="lg:col-span-2 transition-all duration-300 hover:shadow-lg hover:-translate-y-1">
<CardHeader>
<CardTitle>User Profile</CardTitle>
<CardDescription>
Update your personal information. This helps in calculating accurate BMI and BMR values.
</CardDescription>
</CardHeader>
<CardContent className="space-y-6">
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div className="space-y-2">
<Label htmlFor="firstName">First Name</Label>
<Input id="firstName" placeholder="e.g., John" value={[Link] || ''} onChange={h
</div>
<div className="space-y-2">
<Label htmlFor="lastName">Last Name</Label>
<Input id="lastName" placeholder="e.g., Doe" value={[Link] || ''} onChange={hand
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div className="space-y-2">
<Label>Date of Birth</Label>
<Popover>
<PopoverTrigger asChild>
<Button
variant={"outline"}
className={`w-full justify-start text-left font-normal ${![Link] && "text-mut
>
<CalendarIcon className="mr-2 h-4 w-4" />
{[Link] ? format([Link], "PPP") : <span>Pick a date</span>}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0">
<Calendar
mode="single"
selected={[Link]}
onSelect={handleDobChange}
initialFocus
captionLayout="dropdown-buttons"
fromYear={1920}
toYear={new Date().getFullYear()}
/>
</PopoverContent>
</Popover>
</div>
<div className="space-y-2">
<Label>Age</Label>
<div className="flex h-10 w-full items-center rounded-md border border-input bg-background
{age !== null ? `${age} years old` : 'N/A'}
</div>
</div>
</div>
<div className="space-y-4">
<Label>Lifestyle</Label>
<div className="flex items-center space-x-2">
<Checkbox id="smokes" checked={[Link]} onCheckedChange={(checked) => handleChecked
<label htmlFor="smokes" className="text-sm font-medium leading-none peer-disabled:cursor-n
Do you smoke?
</label>
</div>
<div className="flex items-center space-x-2">
<Checkbox id="drinksAlcohol" checked={[Link]} onCheckedChange={(checked) =>
<label htmlFor="drinksAlcohol" className="text-sm font-medium leading-none peer-disabled:c
Do you drink alcohol?
</label>
</div>
</div>
addHabit(newHabitName);
toast({ title: "New Habit Added!", description: `You've started tracking "${newHabitName}".`});
setNewHabitName('');
setIsAddDialogOpen(false);
}
return (
<>
<AlertDialog open={isWelcomeDialogOpen} onOpenChange={setIsWelcomeDialogOpen}>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>A Note on Your Journey</AlertDialogTitle>
<AlertDialogDescription>
This journey is yours and yours alone. True progress begins with honesty. Be true to yours
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogAction onClick={() => setIsWelcomeDialogOpen(false)}>I Am Ready</AlertDialogActi
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
<Card>
<CardContent className="p-6 flex flex-col items-center text-center">
<p className="mb-4 text-muted-foreground">Start a new rehabilitation goal.</p>
<Dialog open={isAddDialogOpen} onOpenChange={setIsAddDialogOpen}>
<DialogTrigger asChild>
<Button>
<Plus className="mr-2 h-4 w-4" />
Add New Habit
</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Add a New Habit to Track</DialogTitle>
</DialogHeader>
<form onSubmit={handleAddHabit}>
<div className="space-y-4 py-4">
<div className="space-y-2">
<Label htmlFor="habit-name">Habit Name</Label>
<Select value={newHabitName} onValueChange={setNewHabitName}>
<SelectTrigger id="habit-name">
<SelectValue placeholder="Select a habit to start tracking..
</SelectTrigger>
<SelectContent>
{[Link](habitName => (
<SelectItem key={habitName} value={habitName}>{habitName
))}
{[Link] === 0 && (
<div className="p-4 text-sm text-muted-foreground text-c
You are tracking all available habits.
</div>
)}
</SelectContent>
</Select>
</div>
</div>
<DialogFooter>
<DialogClose asChild>
<Button type="button" variant="secondary">Cancel</Button>
</DialogClose>
<Button type="submit" disabled={!newHabitName}>Add Habit</Button>
</DialogFooter>
</form>
</DialogContent>
</Dialog>
</CardContent>
</Card>
</div>
</>
);
}
Explanation not written yet, but this file contributes to the app's functionality.
src/app/(dashboard)/settings/[Link]
'use client';
<Card>
<CardHeader>
<CardTitle>Alert Thresholds</CardTitle>
<CardDescription>
Set the values at which you want to receive alerts for your vitals.
</CardDescription>
</CardHeader>
<CardContent className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
<div className="space-y-2">
<Label htmlFor="hrMax">Heart Rate Max (bpm)</Label>
<Input id="hrMax" type="number" value={[Link]} onChange={handleThresholdChange} />
</div>
<div className="space-y-2">
<Label htmlFor="hrMin">Heart Rate Min (bpm)</Label>
<Input id="hrMin" type="number" value={[Link]} onChange={handleThresholdChange} />
</div>
<div className="space-y-2">
<Label htmlFor="spo2Min">SpO2 Min (%)</Label>
<Input id="spo2Min" type="number" value={thresholds.spo2Min} onChange={handleThresholdChange
</div>
<div className="space-y-2">
<Label htmlFor="tempMax">Temperature Max (°C)</Label>
<Input id="tempMax" type="number" step="0.1" value={[Link]} onChange={handleThre
</div>
<div className="space-y-2">
<Label htmlFor="bpSysMax">BP Systolic Max (mmHg)</Label>
<Input id="bpSysMax" type="number" value={[Link]} onChange={handleThresholdChan
</div>
<div className="space-y-2">
<Label htmlFor="bpDiaMax">BP Diastolic Max (mmHg)</Label>
<Input id="bpDiaMax" type="number" value={[Link]} onChange={handleThresholdChan
</div>
<div className="space-y-2">
<Label htmlFor="ecgMax">ECG Stress Max (/100)</Label>
<Input id="ecgMax" type="number" value={[Link]} onChange={handleThresholdChange}
</div>
<div className="space-y-2">
<Label htmlFor="eyeStrainMax">Eye Strain Max (/100)</Label>
<Input id="eyeStrainMax" type="number" value={[Link]} onChange={handleThres
</div>
</CardContent>
<CardFooter>
<Button onClick={handleSaveThresholds}>Save Thresholds</Button>
</CardFooter>
</Card>
<Card>
<CardHeader>
<CardTitle>Device Registry</CardTitle>
<CardDescription>
Manage your connected ESP32 devices.
</CardDescription>
</CardHeader>
<CardContent>
<div className="space-y-4">
{[Link]((device) => (
<div key={device} className="flex items-center justify-between p-3 bg-muted rounded-lg">
<p className="font-mono text-sm">{device}</p>
<Button variant="destructive" size="sm" onClick={() => handleRemoveDevice(device)}>R
</div>
))}
{[Link] === 0 && (
<p className="text-sm text-muted-foreground text-center py-4">No devices registered.</p>
)}
</div>
</CardContent>
<CardFooter className="border-t pt-6 mt-6">
<div className="flex items-center gap-4 w-full">
<Input
placeholder="Enter new device ID"
className="flex-1"
value={newDevice}
onChange={(e) => setNewDevice([Link])}
/>
<Button onClick={handleAddDevice}>Add Device</Button>
</div>
</CardFooter>
</Card>
</div>
);
}
Explanation not written yet, but this file contributes to the app's functionality.
src/app/(dashboard)/tools/[Link]
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { TargetTab } from "@/components/tools/target-tab";
import { CaloriesTab } from "@/components/tools/calories-tab";
import { Card, CardHeader, CardTitle, CardDescription, CardContent } from "@/components/ui/card";
return (
<div>
<div className="flex justify-between items-center mb-4">
<h4 className="font-semibold text-sm">Upcoming</h4>
<Dialog open={isDialogOpen} onOpenChange={setIsDialogOpen}>
<DialogTrigger asChild>
<Button variant="ghost" size="icon" className="h-7 w-7">
<Plus className="h-4 w-4" />
</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Add New Appointment</DialogTitle>
</DialogHeader>
<form onSubmit={handleAddAppointment}>
<div className="space-y-4 py-4">
<div className="space-y-2">
<Label htmlFor="doctor-name">Doctor's Name</Label>
<Input id="doctor-name" value={doctorName} onChange={(e) => setDoctorNam
</div>
<div className="space-y-2">
<Label htmlFor="specialty">Specialty</Label>
<Input id="specialty" value={specialty} onChange={(e) => setSpecialty(e.
</div>
<div className="space-y-2">
<Label htmlFor="datetime">Date and Time</Label>
<Input id="datetime" type="datetime-local" value={dateTime} onChange={(e
</div>
</div>
<DialogFooter>
<DialogClose asChild>
<Button type="button" variant="secondary">Cancel</Button>
</DialogClose>
<Button type="submit">Add Appointment</Button>
</DialogFooter>
</form>
</DialogContent>
</Dialog>
</div>
<div className="space-y-4">
{[Link] === 0 ? (
<div className="text-center text-sm text-muted-foreground py-4">
No upcoming appointments.
</div>
) : (
[Link]((appointment) => (
<div key={[Link]} className="flex items-center gap-4">
<div className="flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-second
<Calendar className="h-5 w-5 text-secondary-foreground" />
</div>
<div className="flex-1 text-sm">
<p className="font-medium">Dr. {[Link]}</p>
<p className="text-muted-foreground">{[Link]}</p>
<div className="flex items-center gap-2 text-xs text-muted-foreground mt-1">
<Clock className="h-3 w-3" />
<span>{[Link]}</span>
</div>
</div>
<Button variant="outline" size="sm">Details</Button>
</div>
))
)}
</div>
</div>
);
}
Explanation not written yet, but this file contributes to the app's functionality.
src/components/[Link]
import type { ReactNode } from "react"
import {
SidebarProvider,
Sidebar,
SidebarHeader,
SidebarContent,
SidebarFooter,
SidebarInset,
SidebarTrigger,
} from "@/components/ui/sidebar"
import { Button } from "@/components/ui/button"
import { Logo } from "@/components/icons/logo"
import { SidebarNav } from "@/components/sidebar-nav"
import { Header } from "@/components/header"
import { cn } from "@/lib/utils"
interface DashboardLayoutProps {
children: ReactNode
}
interface Habit {
id: string;
name: string;
streak: number;
unit: string;
}
interface HabitCardProps {
habit: Habit;
}
const chartConfig = {
handled: {
label: "Handled",
color: "hsl(var(--chart-1))",
},
succumbed: {
label: "Succumbed",
color: "hsl(var(--destructive))",
},
};
return (
<>
<Card className="transition-all duration-300 hover:shadow-lg hover:-translate-y-1">
<CardHeader>
<CardTitle>{[Link]}</CardTitle>
<CardDescription>Your craving patterns and history.</CardDescription>
</CardHeader>
<CardContent>
<div className="space-y-4">
<div className="h-[200px] w-full">
<ChartContainer config={chartConfig} className="w-full h-full">
<ResponsiveContainer>
<BarChart data={mockCravingHistory} margin={{ top: 20, right: 10, left: -20, bot
<CartesianGrid vertical={false} />
<XAxis dataKey="date" tickLine={false} axisLine={false} tickMargin={8} fontSiz
<YAxis />
<ChartTooltip
content={
<ChartTooltipContent
formatter={(value, name, props) => (
<div>
<p>Status: <span className="font-bold">{[Link]}</spa
<p>Trigger: <span className="font-bold capitalize">{[Link].
<p>Emotion: <span className="font-bold capitalize">{[Link].
</div>
)}
/>
}
/>
<Bar dataKey="count" stackId="a" fill="var(--color-handled)" radius={[4, 4, 0,
</BarChart>
</ResponsiveContainer>
</ChartContainer>
</div>
<Button className="w-full" onClick={() => setIsCravingDialogOpen(true)}>
<BarChartIcon className="mr-2 h-4 w-4" />
Handle Craving
</Button>
</div>
</CardContent>
</Card>
return (
<header className="flex h-16 items-center gap-4 border-b bg-card/70 backdrop-blur-lg px-4 md:px-6 st
<Button
variant="ghost"
size="icon"
className="md:hidden"
onClick={toggleSidebar}
>
<div className="flex h-6 w-6 flex-col justify-around">
<span
className={`h-0.5 w-full transform bg-current transition-transform duration-300 ${
openMobile ? "translate-y-2 rotate-45" : ""
}`}
/>
<span
className={`h-0.5 w-full bg-current transition-opacity duration-300 ${
openMobile ? "opacity-0" : "opacity-100"
}`}
/>
<span
className={`h-0.5 w-full transform bg-current transition-transform duration-300 ${
openMobile ? "-translate-y-2 -rotate-45" : ""
}`}
/>
</div>
<span className="sr-only">Toggle sidebar</span>
</Button>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="secondary" size="icon" className="rounded-full">
<CircleUser className="h-5 w-5" />
<span className="sr-only">Toggle user menu</span>
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuLabel>
<div className="flex flex-col space-y-1">
<p className="text-sm font-medium leading-none">{user?.displayName || user?.email}</p>
<p className="text-xs leading-none text-muted-foreground">
{user?.email || user?.phoneNumber}
</p>
</div>
</DropdownMenuLabel>
{isAdmin && (
<>
<DropdownMenuSeparator />
<div className="px-2 py-1.5 text-xs font-semibold text-primary flex items-center gap-2
<ShieldCheck className="h-4 w-4" /> Admin Privileges
</div>
</>
)}
<DropdownMenuSeparator />
<DropdownMenuItem asChild>
<Link href="/profile">
<User className="mr-2 h-4 w-4" />
<span>Profile</span>
</Link>
</DropdownMenuItem>
<DropdownMenuItem asChild>
<Link href="/tools">
<Target className="mr-2 h-4 w-4" />
<span>Tools</span>
</Link>
</DropdownMenuItem>
<DropdownMenuItem asChild>
<Link href="/settings">
<Settings className="mr-2 h-4 w-4" />
<span>Settings</span>
</Link>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div>
</header>
)
}
Explanation not written yet, but this file contributes to the app's functionality.
src/components/[Link]
import { Loader2 } from "lucide-react";
return (
<div>
<div className="flex justify-between items-center mb-4">
<h4 className="font-semibold text-sm">Reminders</h4>
<Dialog open={isDialogOpen} onOpenChange={setIsDialogOpen}>
<DialogTrigger asChild>
<Button variant="ghost" size="icon" className="h-7 w-7">
<Plus className="h-4 w-4" />
</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Add New Medication</DialogTitle>
</DialogHeader>
<form onSubmit={handleAddMedication}>
<div className="space-y-4 py-4">
<div className="space-y-2">
<Label htmlFor="med-name">Medication Name</Label>
<Input id="med-name" value={medName} onChange={(e) => setMedName([Link]
</div>
<div className="space-y-2">
<Label htmlFor="dosage">Dosage</Label>
<Input id="dosage" value={dosage} onChange={(e) => setDosage([Link]
</div>
<div className="space-y-2">
<Label htmlFor="time">Time</Label>
<Input id="time" type="time" value={time} onChange={(e) => setTime([Link]
</div>
</div>
<DialogFooter>
<DialogClose asChild>
<Button type="button" variant="secondary">Cancel</Button>
</DialogClose>
<Button type="submit">Add Reminder</Button>
</DialogFooter>
</form>
</DialogContent>
</Dialog>
</div>
<div className="space-y-4">
{[Link] === 0 ? (
<div className="text-center text-sm text-muted-foreground py-4">
No medication reminders for now.
</div>
) : [Link]((med) => (
<div key={[Link]} className="flex items-center gap-4">
<div className="flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-primary/10
<Pill className="h-5 w-5 text-primary" />
</div>
<div className="flex-1 text-sm">
<p className="font-medium">{[Link]}</p>
<p className="text-muted-foreground">{[Link]}</p>
</div>
<div className="flex gap-2">
<Button size="sm" onClick={() => handleAction([Link], 'Taken')}>Take</Button>
<Button size="sm" variant="outline" onClick={() => handleAction([Link], 'Snoozed')}>Sn
</div>
</div>
))}
</div>
</div>
);
}
Explanation not written yet, but this file contributes to the app's functionality.
src/components/[Link]
'use client';
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@/components/ui/card"
import { Button } from "@/components/ui/button"
import { generateHealthRecommendations } from "@/ai/flows/generate-health-recommendations"
import { FileText, Lightbulb, HeartHandshake, MessageSquare, Loader2 } from "lucide-react"
import Link from "next/link"
import { cn } from "@/lib/utils"
import { useAppContext } from "@/context/app-context";
import { useEffect, useState } from "react";
import type { Recommendation } from "@/lib/types";
const iconMap = {
diet: Lightbulb,
medicine: FileText,
lifestyle: HeartHandshake,
}
useEffect(() => {
const fetchRecommendations = async () => {
if (!userProfile) return;
setIsLoading(true);
try {
const vitalReadings = [Link](v => ({
type: [Link],
value: [Link],
unit: [Link],
}));
if ([Link]) {
setRecommendations([Link]((item, index) => ({
id: `rec-${index}`,
...item
})));
}
} catch (error) {
[Link]("Failed to generate recommendations:", error);
setRecommendations([]); // Set empty on error
} finally {
setIsLoading(false);
}
};
fetchRecommendations();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [vitals, userProfile]);
return (
<Card className={cn(
"h-full transition-all duration-300 hover:shadow-lg hover:-translate-y-1 flex flex-col",
"bg-gradient-to-br from-primary via-primary to-accent text-primary-foreground"
)}>
<CardHeader>
<CardTitle className="font-headline">Recent Recommendations</CardTitle>
<CardDescription className="text-primary-foreground/80">AI-powered advice based on your vitals.<
</CardHeader>
<CardContent className="flex-1 flex flex-col justify-between">
{isLoading ? (
<div className="flex-1 flex items-center justify-center">
<div className="text-center">
<Loader2 className="h-8 w-8 animate-spin mx-auto mb-2" />
<p className="text-sm">Analyzing your data...</p>
</div>
</div>
) : [Link] > 0 ? (
<div className="space-y-4">
{[Link]((rec) => {
const Icon = iconMap[[Link]]
return (
<div key={[Link]} className="flex items-start gap-4">
<div className="flex h-8 w-8 items-center justify-center rounded-full bg-primary-for
<Icon className="h-4 w-4 text-primary-foreground" />
</div>
<div className="flex-1">
<p className="text-sm font-medium leading-none">
{[Link]}
</p>
<p className="text-sm text-primary-foreground/70">{[Link]}</p>
</div>
</div>
)
})}
</div>
) : (
<div className="flex-1 flex items-center justify-center">
<p className="text-sm text-center">No specific recommendations at the moment. Keep up t
</div>
)}
<Button className="mt-6 w-full" variant="secondary" asChild>
<Link href="/chat">
<MessageSquare className="mr-2 h-4 w-4" />
Ask SenAssist
</Link>
</Button>
</CardContent>
</Card>
)
}
Explanation not written yet, but this file contributes to the app's functionality.
src/components/[Link]
'use client';
const allStats = [
{ name: 'Quit Smoking', willpower: 75, relapse: 10 },
{ name: 'Reduce Alcohol', willpower: 82, relapse: 5 },
]
return (
<Card className="h-full transition-all duration-300 hover:shadow-lg hover:-translate-y-1 flex flex-c
<CardHeader>
<CardTitle className="flex items-center gap-2 font-headline">
<HeartHandshake className="h-5 w-5 text-primary" />
<span>Rehab Dashboard</span>
</CardTitle>
<CardDescription>Your at-a-glance progress.</CardDescription>
</CardHeader>
<CardContent className="flex-grow flex flex-col justify-between">
<div className="space-y-4">
{[Link] > 0 ? [Link](stat => {
const Icon = habitIcons[[Link]] || HeartHandshake;
return (
<div key={[Link]}>
<h4 className="text-sm font-medium flex items-center gap-2 mb-2">
<Icon className="h-4 w-4" />
{[Link]}
</h4>
<div className="space-y-2">
<div className="flex items-center gap-2 text-xs">
<ShieldCheck className="h-4 w-4 text-green-500" />
<p className="text-muted-foreground w-16">Willpower</p>
<Progress value={[Link]} className="flex-1" />
<p className="font-bold w-10 text-right">{[Link]}%</p>
</div>
<div className="flex items-center gap-2 text-xs">
<ShieldAlert className="h-4 w-4 text-red-500" />
<p className="text-muted-foreground w-16">Relapse</p>
<Progress value={[Link]} className="flex-1" />
<p className="font-bold w-10 text-right">{[Link]}%</p>
</div>
</div>
</div>
)
}) : (
<div className="text-center text-sm text-muted-foreground py-6">
No rehab goals started. Visit the rehab page to begin.
</div>
)}
</div>
<Button asChild className="mt-6 w-full">
<Link href="/rehab">
View Full Journey <ArrowRight className="ml-2 h-4 w-4" />
</Link>
</Button>
</CardContent>
</Card>
);
}
Explanation not written yet, but this file contributes to the app's functionality.
src/components/[Link]
'use client';
interface RehabStatsProps {
habits: Habit[];
}
return (
<Card>
<CardHeader>
<CardTitle>Progress Overview</CardTitle>
<CardDescription>Your willpower and relapse statistics.</CardDescription>
</CardHeader>
<CardContent className="space-y-6">
{[Link](stat => (
<div key={[Link]}>
<h3 className="text-sm font-medium mb-2">{[Link]}</h3>
<div className="space-y-4">
<div className="flex items-center gap-2">
<ShieldCheck className="h-5 w-5 text-green-500" />
<p className="text-sm text-muted-foreground w-20">Willpower</p>
<Progress value={[Link]} className="flex-1" />
<p className="text-sm font-bold w-12 text-right">{[Link]}%</p>
</div>
<div className="flex items-center gap-2">
<ShieldAlert className="h-5 w-5 text-red-500" />
<p className="text-sm text-muted-foreground w-20">Relapse Rate</p>
<Progress value={[Link]} className="flex-1" />
<p className="text-sm font-bold w-12 text-right">{[Link]}%</p>
</div>
</div>
</div>
))}
</CardContent>
</Card>
)
}
Explanation not written yet, but this file contributes to the app's functionality.
src/components/[Link]
'use client';
const chartConfig = {
hours: {
label: 'Sleep (hours)',
color: 'hsl(var(--chart-1))',
},
};
return (
<Card className="h-full transition-all duration-300 hover:shadow-lg hover:-translate-y-1 flex flex-c
<CardHeader>
<CardTitle className="flex items-center gap-2 font-headline">
<BedDouble className="h-5 w-5 text-primary" />
Sleep Tracking
</CardTitle>
<CardDescription>Last night you slept for {[Link]} hours.</CardDescription>
</CardHeader>
<CardContent className="flex-1">
<div className="h-[200px] w-full">
<ChartContainer config={chartConfig} className="h-full w-full">
<BarChart accessibilityLayer data={mockSleepData} margin={{ top: 20, right: 10, left: -2
<CartesianGrid vertical={false} />
<XAxis
dataKey="day"
tickLine={false}
axisLine={false}
tickMargin={8}
fontSize={12}
/>
<YAxis
tickLine={false}
axisLine={false}
tickMargin={8}
fontSize={12}
unit="h"
/>
<ChartTooltip
cursor={true}
content={
<ChartTooltipContent
indicator="dot"
/>
}
/>
<Bar
dataKey="hours"
fill="var(--color-hours)"
radius={[4, 4, 0, 0]}
/>
</BarChart>
</ChartContainer>
</div>
</CardContent>
<CardFooter className="mt-auto border-t pt-3 pb-3">
<div className="flex items-start gap-2 text-xs text-muted-foreground">
<MessageCircle className="h-4 w-4 shrink-0 mt-0.5" />
<p>
{getSleepRemark([Link])}
</p>
</div>
</CardFooter>
</Card>
);
}
Explanation not written yet, but this file contributes to the app's functionality.
src/components/[Link]
"use client"
const allNavItems = [
{ href: "/dashboard", icon: LayoutDashboard, label: "Dashboard" },
{ href: "/emergency", icon: AlertTriangle, label: "Emergency", className: "text-red-500 hover:bg-red-5
{ href: "/chat", icon: MessageSquare, label: "SenAssist" },
{ href: "/tools", icon: Target, label: "Tools" },
{ href: "/analytics", icon: BarChart3, label: "Analytics" },
{ href: "/rehab", icon: HeartHandshake, label: "Rehab" },
{ href: "[Link] icon: ShoppingCart, label: "Pharmacy", external: true },
{ href: "/connect", icon: Bluetooth, label: "Connect" },
{ href: "/profile", icon: User, label: "Profile" },
{ href: "/feedback", icon: FilePen, label: "Feedback" },
{ href: "/settings", icon: Settings, label: "Settings" },
]
return (
<SidebarMenu>
{[Link]((item) => {
const isExternal = [Link] || [Link]('[Link]
const linkProps = isExternal ? { target: "_blank", rel: "noopener noreferrer" } : {};
const isEmergencyActive = [Link]([Link]) && [Link] === '/emergency';
return (
<SidebarMenuItem key={[Link]}>
<SidebarMenuButton
asChild
isActive={!isExternal && [Link]([Link])}
tooltip={[Link]}
className={cn(
[Link],
isEmergencyActive && 'bg-red-500/10 text-red-500'
)}
>
<Link href={[Link]} {...linkProps}>
<[Link] />
<span>{[Link]}</span>
{isExternal && 
})}
</SidebarMenu>
)
}
Explanation not written yet, but this file contributes to the app's functionality.
src/components/[Link]
'use client';
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from '@/components/ui/card';
import {
ChartContainer,
ChartTooltip,
ChartTooltipContent,
} from '@/components/ui/chart';
import { Area, AreaChart } from 'recharts';
import type { Vital } from '@/lib/types';
import { cn } from '@/lib/utils';
import {
HeartPulse,
Gauge,
Thermometer,
Activity,
Flame,
BrainCircuit,
Eye,
Scale,
Droplet,
ListPlus,
} from 'lucide-react';
import type { LucideIcon } from 'lucide-react';
import Link from 'next/link';
import { Button } from './ui/button';
import { Input } from './ui/input';
import { useState } from 'react';
import { useToast } from '@/hooks/use-toast';
import { useAppContext } from '@/context/app-context';
interface StatCardProps {
vital: Vital;
}
const chartConfig = {
value: {
label: [Link],
color: 'hsl(var(--chart-1))',
},
};
if (!reading) {
toast({ title: "Please enter a reading.", variant: 'destructive' });
return;
}
const valueNum = parseFloat(reading);
if (isNaN(valueNum) || valueNum <=0) {
toast({
variant: 'destructive',
title: 'Invalid Value',
description: 'Please enter a valid positive number.',
});
return;
}
updateVitals([Link], valueNum);
toast({
title: `${[Link]} Logged!`,
description: `Your reading of ${reading} has been saved.`
});
setReading('');
}
return (
<Card className={cn("transition-all duration-300 hover:shadow-lg hover:-translate-y-1 flex flex-col
<Link href={`/dashboard/${vitalSlug}`} className='flex-grow flex flex-col'>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="font-headline">{[Link]}</CardTitle>
{Icon && <Icon className="h-4 w-4 text-muted-foreground" />}
</CardHeader>
<CardContent className="pb-0">
<div className="text-2xl font-bold">
{[Link]}
<span className="text-xs text-muted-foreground ml-1">
{[Link]}
</span>
</div>
<p
className={cn(
'text-xs text-muted-foreground',
[Link] === 'up' && 'text-green-600',
[Link] === 'down' && 'text-red-600'
)}
>
{[Link]}
</p>
</CardContent>
<CardFooter className="pb-2 flex-grow">
<div className="h-20 w-full">
<ChartContainer config={chartConfig} className="h-full w-full">
<AreaChart
accessibilityLayer
data={[Link]}
margin={{
left: 0,
right: 0,
top: 5,
bottom: 0,
}}
>
<defs>
<linearGradient id="fill-color" x1="0" y1="0" x2="0" y2="1">
<stop
offset="5%"
stopColor="var(--color-value)"
stopOpacity={0.8}
/>
<stop
offset="95%"
stopColor="var(--color-value)"
stopOpacity={0.1}
/>
</linearGradient>
</defs>
<ChartTooltip
cursor={false}
content={<ChartTooltipContent hideLabel hideIndicator />}
/>
<Area
dataKey="value"
type="natural"
fill="url(#fill-color)"
stroke="var(--color-value)"
stackId="a"
/>
</AreaChart>
</ChartContainer>
</div>
</CardFooter>
</Link>
{[Link] === 'Blood Sugar' && (
<CardFooter className='flex-col items-start gap-2 border-t pt-4 mt-auto'>
<p className='text-xs font-medium text-muted-foreground'>Log New Reading</p>
<form onSubmit={handleLogVital} className='w-full flex gap-2'>
<Input
type="number"
placeholder={`e.g. 90 ${[Link]}`}
className='h-9'
value={reading}
onChange={(e) => setReading([Link])}
onClick={(e) => [Link]()}
/>
<Button size="sm" onClick={(e) => [Link]()}>Log</Button>
</form>
</CardFooter>
)}
{[Link] === 'Calories' && (
<CardFooter className='flex-col items-start gap-3 border-t pt-4 mt-auto'>
<div className='w-full text-center'>
<p className="text-sm font-medium">{[Link]()} kcal</p>
<p className="text-xs text-muted-foreground">Remaining</p>
</div>
<Button className='w-full' asChild>
<Link href="/tools">
<ListPlus className="mr-2 h-4 w-4" />
Add a Meal
</Link>
</Button>
</CardFooter>
)}
</Card>
);
}
Explanation not written yet, but this file contributes to the app's functionality.
src/components/[Link]
import { Card, CardHeader, CardTitle, CardContent, CardFooter, CardDescription } from "@/components/ui/c
import { BrainCircuit, AlertTriangle } from "lucide-react";
import { Badge } from "./ui/badge";
return (
<Card className="h-full transition-all duration-300 hover:shadow-lg hover:-translate-y-1 flex flex-c
<CardHeader>
<CardTitle className="flex items-center gap-2 font-headline">
<MapPin className="h-5 w-5 text-primary" />
<span>Surroundings</span>
</CardTitle>
</CardHeader>
<CardContent className="flex-grow">
<div className="grid grid-cols-1 gap-y-4">
<div className="flex items-center gap-3">
<Thermometer className="h-6 w-6 text-red-500" />
<div>
<p className="text-sm text-muted-foreground">Temperature</p>
<p className="font-bold">{[Link]}<span className="text-xs text-muted-fore
</div>
</div>
<div className="flex items-center gap-3">
<Cloudy className="h-6 w-6 text-blue-500" />
<div>
<p className="text-sm text-muted-foreground">Humidity</p>
<p className="font-bold">{[Link]}<span className="text-xs text-muted-foregro
</div>
</div>
<div className="flex items-center gap-3">
<Gauge className="h-6 w-6 text-gray-500" />
<div>
<p className="text-sm text-muted-foreground">Pressure</p>
<p className="font-bold">{[Link]}<span className="text-xs text-muted-foregro
</div>
</div>
<div className="flex items-center gap-3">
<Wind className="h-6 w-6 text-green-500" />
<div>
<p className="text-sm text-muted-foreground">Air Quality</p>
<p className={`font-bold ${getAqiColor(parseInt([Link], 10))}`}>{airQualit
</div>
</div>
</div>
</CardContent>
<CardFooter className="mt-auto border-t pt-3 pb-3">
<div className="flex items-start gap-2 text-xs text-muted-foreground">
<AlertTriangle className="h-4 w-4 shrink-0 mt-0.5" />
<p>
Readings are from BME280 & ENS160 sensors and reflect your immediate environment. If you
</p>
</div>
</CardFooter>
</Card>
);
}
Explanation not written yet, but this file contributes to the app's functionality.
src/components/[Link]
"use client"
useEffect(() => {
const getCameraPermission = async () => {
if (![Link] || ![Link]) {
setHasCameraPermission(false);
return;
}
try {
const stream = await [Link]({ video: true });
setHasCameraPermission(true);
if ([Link]) {
[Link] = stream;
}
} catch (error) {
[Link]('Error accessing camera:', error);
setHasCameraPermission(false);
}
};
getCameraPermission();
return () => {
// Stop camera stream when component unmounts
if ([Link] && [Link]) {
const stream = [Link] as MediaStream;
[Link]().forEach(track => [Link]());
}
}
}, []);
setIsLoading(true);
setResult(null);
try {
const response = await calculateCalories({ photoDataUri: imageSrc });
setResult(response);
} catch (error) {
[Link]('Error calculating calories:', error);
toast({
variant: 'destructive',
title: 'Analysis Failed',
description: 'Could not analyze the image. Please try again.',
});
} finally {
setIsLoading(false);
}
};
return (
<div className="pt-6 grid lg:grid-cols-2 gap-6">
<Card className="transition-all duration-300 hover:shadow-lg hover:-translate-y-1">
<CardHeader>
<CardTitle>AI Calorie Calculator</CardTitle>
<CardDescription>
Use your camera or upload an image to get an AI-powered calorie estimate.
</CardDescription>
</CardHeader>
<CardContent>
<div className="space-y-4">
<div className="relative aspect-video bg-muted rounded-lg overflow-hidden flex items-center
{imageSrc ? (
<img src={imageSrc} alt="Food" className="object-contain h-full w-full" />
) : hasCameraPermission ? (
<video ref={videoRef} autoPlay muted playsInline className="h-full w-full object-cover">
) : (
<div className="text-center text-muted-foreground p-4">
<Camera className="mx-auto h-8 w-8 mb-2" />
<p>Camera not available or permission denied.</p>
<p className="text-xs">Please use the upload option instead.</p>
</div>
)}
{imageSrc && (
<Button variant="destructive" size="icon" className="absolute top-2 right-2 h-7 w-7" on
<X className="h-4 w-4" />
</Button>
)}
</div>
<canvas ref={canvasRef} className="hidden"></canvas>
{hasCameraPermission === false && (
<Alert variant="destructive">
<AlertTitle>Camera Access Denied</AlertTitle>
<AlertDescription>Please enable camera permissions in your browser settings to use t
</Alert>
)}
<div className="grid grid-cols-2 gap-2">
<Button onClick={handleCapture} disabled={!hasCameraPermission || !!imageSrc}>
<Camera className="mr-2 h-4 w-4" /> Capture
</Button>
<Button variant="outline" onClick={() => [Link]?.click()} disabled={!!imageS
<Upload className="mr-2 h-4 w-4" /> Upload
</Button>
<input
type="file"
ref={fileInputRef}
accept="image/*"
className="hidden"
onChange={handleFileUpload}
/>
</div>
<Button className="w-full" onClick={handleAnalyze} disabled={!imageSrc || isLoading}>
{isLoading ? <Loader2 className="mr-2 h-4 w-4 animate-spin" /> : <Sparkles className="mr-
Analyze Image
</Button>
</div>
</CardContent>
<AnimatePresence>
{result && (
<CardFooter as={[Link]} initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} e
<h3 className="font-semibold">Analysis Result</h3>
<div className="w-full space-y-2 text-sm">
<div className="flex justify-between">
<p className="text-muted-foreground">Food:</p>
<p className="font-medium">{[Link]}</p>
</div>
<div className="flex justify-between">
<p className="text-muted-foreground">Serving Size:</p>
<p className="font-medium">{[Link]}</p>
</div>
<div className="flex justify-between">
<p className="text-muted-foreground">Est. Calories:</p>
<p className="font-medium">{[Link]} kcal</p>
</div>
</div>
<Button className="w-full" onClick={handleAddToIntake}>
<Plus className="mr-2 h-4 w-4" /> Add to Daily Intake
</Button>
</CardFooter>
)}
</AnimatePresence>
</Card>
return (
<div className="pt-6 grid gap-6 lg:grid-cols-3">
<Card className="lg:col-span-2 transition-all duration-300 hover:shadow-lg hover:-translate-y-1">
<CardHeader>
<CardTitle>Set Your Target</CardTitle>
<CardDescription>
Define your weight goals to get personalized calorie and activity recommendations.
</CardDescription>
</CardHeader>
<CardContent>
<form onSubmit={handleSubmit} className="space-y-6">
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div className="space-y-2">
<Label htmlFor="current-weight">Current Weight (kg)</Label>
<Input id="current-weight" type="number" placeholder="e.g., 70" value={currentWeight} on
</div>
<div className="space-y-2">
<Label htmlFor="target-weight">Target Weight (kg)</Label>
<Input id="target-weight" type="number" placeholder="e.g., 65" value={targetWeight} onCh
</div>
</div>
<Button type="submit">Calculate Target</Button>
</form>
</CardContent>
</Card>
<div className="lg:col-span-1 space-y-6">
<Card className="transition-all duration-300 hover:shadow-lg hover:-translate-y-1">
<CardHeader>
<CardTitle className="flex items-center gap-2">
<GoalIcon />
Your Daily Target
</CardTitle>
<CardDescription>Based on your goal.</CardDescription>
</CardHeader>
<CardContent className="space-y-6">
<div className="flex justify-between items-center">
<div className="flex items-center gap-3">
<Flame className="h-6 w-6 text-primary" />
<p className="text-muted-foreground">Target Calories</p>
</div>
<AnimatePresence mode="wait">
<motion.p
key={`calories-${[Link]}`}
initial={{ opacity: 0, y: -10 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: 10 }}
transition={{ duration: 0.3 }}
className="text-2xl font-bold"
>
{[Link] > 0 ? [Link]() : 'N/A'}{' '}
{[Link] > 0 && <span className="text-sm text-muted-foreground">kcal<
</motion.p>
</AnimatePresence>
</div>
<div className="flex flex-col gap-2">
<div className="flex items-center gap-3">
<Activity className="h-6 w-6 text-primary" />
<p className="text-muted-foreground">Recommended Activity</p>
</div>
<AnimatePresence mode="wait">
<motion.p
key={`activity-${[Link]}`}
initial={{ opacity: 0, y: -10 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: 10 }}
transition={{ duration: 0.3 }}
className="text-sm font-medium text-right"
>
{[Link]}
</motion.p>
</AnimatePresence>
</div>
</CardContent>
</Card>
</div>
</div>
);
}
Explanation not written yet, but this file contributes to the app's functionality.
src/components/ui/[Link]
"use client"
[Link] = [Link]
const AlertDialogHeader = ({
className,
...props
}: [Link]<HTMLDivElement>) => (
<div
className={cn(
"flex flex-col space-y-2 text-center sm:text-left",
className
)}
{...props}
/>
)
[Link] = "AlertDialogHeader"
const AlertDialogFooter = ({
className,
...props
}: [Link]<HTMLDivElement>) => (
<div
className={cn(
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
className
)}
{...props}
/>
)
[Link] = "AlertDialogFooter"
export {
AlertDialog,
AlertDialogPortal,
AlertDialogOverlay,
AlertDialogTrigger,
AlertDialogContent,
AlertDialogHeader,
AlertDialogFooter,
AlertDialogTitle,
AlertDialogDescription,
AlertDialogAction,
AlertDialogCancel,
}
Explanation not written yet, but this file contributes to the app's functionality.
src/components/ui/[Link]
import * as React from "react"
import { cva, type VariantProps } from "class-variance-authority"
export { AspectRatio }
Explanation not written yet, but this file contributes to the app's functionality.
src/components/ui/[Link]
"use client"
function Calendar({
className,
classNames,
showOutsideDays = true,
...props
}: CalendarProps) {
return (
<DayPicker
showOutsideDays={showOutsideDays}
className={cn("p-3", className)}
classNames={{
months: "flex flex-col sm:flex-row space-y-4 sm:space-x-4 sm:space-y-0",
month: "space-y-4",
caption: "flex justify-between pt-1 relative items-center",
caption_label: "hidden", // hidden
caption_dropdowns: "flex gap-2", // added
nav: "space-x-1 flex items-center",
nav_button: cn(
buttonVariants({ variant: "outline" }),
"h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100"
),
nav_button_previous: "",
nav_button_next: "",
table: "w-full border-collapse space-y-1",
head_row: "flex",
head_cell:
"text-muted-foreground rounded-md w-9 font-normal text-[0.8rem]",
row: "flex w-full mt-2",
cell: "h-9 w-9 text-center text-sm p-0 relative [&:has([aria-selected].day-range-end)]:rounded-r
day: cn(
buttonVariants({ variant: "ghost" }),
"h-9 w-9 p-0 font-normal aria-selected:opacity-100"
),
day_range_end: "day-range-end",
day_selected:
"bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-pr
day_today: "bg-accent text-accent-foreground",
day_outside:
"day-outside text-muted-foreground aria-selected:bg-accent/50 aria-selected:text-muted-foregro
day_disabled: "text-muted-foreground opacity-50",
day_range_middle:
"aria-selected:bg-accent aria-selected:text-accent-foreground",
day_hidden: "invisible",
...classNames,
}}
components={{
IconLeft: ({ ...props }) => <ChevronLeft className="h-4 w-4" />,
IconRight: ({ ...props }) => <ChevronRight className="h-4 w-4" />,
Dropdown: ({ value, onChange, children, ...props }: DropdownProps) => {
const options = [Link](children) as [Link]<[Link]<HTMLO
const selected = [Link]((child) => [Link] === value);
const handleChange = (value: string) => {
const changeEvent = {
target: { value },
} as [Link]<HTMLSelectElement>;
onChange?.(changeEvent);
};
return (
<Select
value={value?.toString()}
onValueChange={(value) => {
handleChange(value);
}}
>
<SelectTrigger className="w-[120px]">
<SelectValue>{selected?.props?.children}</SelectValue>
</SelectTrigger>
<SelectContent>
<ScrollArea className="h-72">
{[Link]((option, id: number) => (
<SelectItem key={`${[Link]}-${id}`} value={[Link]?.toStrin
{[Link]}
</SelectItem>
))}
</ScrollArea>
</SelectContent>
</Select>
);
},
}}
{...props}
/>
)
}
[Link] = "Calendar"
export { Calendar }
Explanation not written yet, but this file contributes to the app's functionality.
src/components/ui/[Link]
import * as React from "react"
type CarouselProps = {
opts?: CarouselOptions
plugins?: CarouselPlugin
orientation?: "horizontal" | "vertical"
setApi?: (api: CarouselApi) => void
}
type CarouselContextProps = {
carouselRef: ReturnType<typeof useEmblaCarousel>[0]
api: ReturnType<typeof useEmblaCarousel>[1]
scrollPrev: () => void
scrollNext: () => void
canScrollPrev: boolean
canScrollNext: boolean
} & CarouselProps
function useCarousel() {
const context = [Link](CarouselContext)
if (!context) {
throw new Error("useCarousel must be used within a <Carousel />")
}
return context
}
setCanScrollPrev([Link]())
setCanScrollNext([Link]())
}, [])
[Link](() => {
if (!api || !setApi) {
return
}
setApi(api)
}, [api, setApi])
[Link](() => {
if (!api) {
return
}
onSelect(api)
[Link]("reInit", onSelect)
[Link]("select", onSelect)
return () => {
api?.off("select", onSelect)
}
}, [api, onSelect])
return (
<[Link]
value={{
carouselRef,
api: api,
opts,
orientation:
orientation || (opts?.axis === "y" ? "vertical" : "horizontal"),
scrollPrev,
scrollNext,
canScrollPrev,
canScrollNext,
}}
>
<div
ref={ref}
onKeyDownCapture={handleKeyDown}
className={cn("relative", className)}
role="region"
aria-roledescription="carousel"
{...props}
>
{children}
</div>
</[Link]>
)
}
)
[Link] = "Carousel"
return (
<div ref={carouselRef} className="overflow-hidden">
<div
ref={ref}
className={cn(
"flex",
orientation === "horizontal" ? "-ml-4" : "-mt-4 flex-col",
className
)}
{...props}
/>
</div>
)
})
[Link] = "CarouselContent"
return (
<div
ref={ref}
role="group"
aria-roledescription="slide"
className={cn(
"min-w-0 shrink-0 grow-0 basis-full",
orientation === "horizontal" ? "pl-4" : "pt-4",
className
)}
{...props}
/>
)
})
[Link] = "CarouselItem"
return (
<Button
ref={ref}
variant={variant}
size={size}
className={cn(
"absolute h-8 w-8 rounded-full",
orientation === "horizontal"
? "-left-12 top-1/2 -translate-y-1/2"
: "-top-12 left-1/2 -translate-x-1/2 rotate-90",
className
)}
disabled={!canScrollPrev}
onClick={scrollPrev}
{...props}
>
<ArrowLeft className="h-4 w-4" />
<span className="sr-only">Previous slide</span>
</Button>
)
})
[Link] = "CarouselPrevious"
return (
<Button
ref={ref}
variant={variant}
size={size}
className={cn(
"absolute h-8 w-8 rounded-full",
orientation === "horizontal"
? "-right-12 top-1/2 -translate-y-1/2"
: "-bottom-12 left-1/2 -translate-x-1/2 rotate-90",
className
)}
disabled={!canScrollNext}
onClick={scrollNext}
{...props}
>
<ArrowRight className="h-4 w-4" />
<span className="sr-only">Next slide</span>
</Button>
)
})
[Link] = "CarouselNext"
export {
type CarouselApi,
Carousel,
CarouselContent,
CarouselItem,
CarouselPrevious,
CarouselNext,
}
Explanation not written yet, but this file contributes to the app's functionality.
src/components/ui/[Link]
"use client"
type ChartContextProps = {
config: ChartConfig
}
function useChart() {
const context = [Link](ChartContext)
if (!context) {
throw new Error("useChart must be used within a <ChartContainer />")
}
return context
}
return (
<[Link] value={{ config }}>
<div
data-chart={chartId}
ref={ref}
className={cn(
"flex aspect-video justify-center text-xs [&_.recharts-cartesian-axis-tick_text]:fill-muted-fo
className
)}
{...props}
>
<ChartStyle id={chartId} config={config} />
<[Link]>
{children}
</[Link]>
</div>
</[Link]>
)
})
[Link] = "Chart"
const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {
const colorConfig = [Link](config).filter(
([, config]) => [Link] || [Link]
)
if (![Link]) {
return null
}
return (
<style
dangerouslySetInnerHTML={{
__html: [Link](THEMES)
.map(
([theme, prefix]) => `
${prefix} [data-chart=${id}] {
${colorConfig
.map(([key, itemConfig]) => {
const color =
[Link]?.[theme as keyof typeof [Link]] ||
[Link]
return color ? ` --color-${key}: ${color};` : null
})
.join("\n")}
}
`
)
.join("\n"),
}}
/>
)
}
if (labelFormatter) {
return (
<div className={cn("font-medium", labelClassName)}>
{labelFormatter(value, payload)}
</div>
)
}
if (!value) {
return null
}
if (!active || !payload?.length) {
return null
}
return (
<div
ref={ref}
className={cn(
"grid min-w-[8rem] items-start gap-1.5 rounded-lg border border-border/50 bg-background px-2.5
className
)}
>
{!nestLabel ? tooltipLabel : null}
<div className="grid gap-1.5">
{[Link]((item, index) => {
const key = `${nameKey || [Link] || [Link] || "value"}`
const itemConfig = getPayloadConfigFromPayload(config, item, key)
const indicatorColor = color || [Link] || [Link]
return (
<div
key={[Link]}
className={cn(
"flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-mu
indicator === "dot" && "items-center"
)}
>
{formatter && item?.value !== undefined && [Link] ? (
formatter([Link], [Link], item, index, [Link])
) : (
<>
{itemConfig?.icon ? (
<[Link] />
) : (
!hideIndicator && (
<div
className={cn(
"shrink-0 rounded-[2px] border-[--color-border] bg-[--color-bg]",
{
"h-2.5 w-2.5": indicator === "dot",
"w-1": indicator === "line",
"w-0 border-[1.5px] border-dashed bg-transparent":
indicator === "dashed",
"my-0.5": nestLabel && indicator === "dashed",
}
)}
style={
{
"--color-bg": indicatorColor,
"--color-border": indicatorColor,
} as [Link]
}
/>
)
)}
<div
className={cn(
"flex flex-1 justify-between leading-none",
nestLabel ? "items-end" : "items-center"
)}
>
<div className="grid gap-1.5">
{nestLabel ? tooltipLabel : null}
<span className="text-muted-foreground">
{itemConfig?.label || [Link]}
</span>
</div>
{[Link] && (
<span className="font-mono font-medium tabular-nums text-foreground">
{[Link]()}
</span>
)}
</div>
</>
)}
</div>
)
})}
</div>
</div>
)
}
)
[Link] = "ChartTooltip"
if (!payload?.length) {
return null
}
return (
<div
ref={ref}
className={cn(
"flex items-center justify-center gap-4",
verticalAlign === "top" ? "pb-3" : "pt-3",
className
)}
>
{[Link]((item) => {
const key = `${nameKey || [Link] || "value"}`
const itemConfig = getPayloadConfigFromPayload(config, item, key)
return (
<div
key={[Link]}
className={cn(
"flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground"
)}
>
{itemConfig?.icon && !hideIcon ? (
<[Link] />
) : (
<div
className="h-2 w-2 shrink-0 rounded-[2px]"
style={{
backgroundColor: [Link],
}}
/>
)}
{itemConfig?.label}
</div>
)
})}
</div>
)
}
)
[Link] = "ChartLegend"
const payloadPayload =
"payload" in payload &&
typeof [Link] === "object" &&
[Link] !== null
? [Link]
: undefined
if (
key in payload &&
typeof payload[key as keyof typeof payload] === "string"
) {
configLabelKey = payload[key as keyof typeof payload] as string
} else if (
payloadPayload &&
key in payloadPayload &&
typeof payloadPayload[key as keyof typeof payloadPayload] === "string"
) {
configLabelKey = payloadPayload[
key as keyof typeof payloadPayload
] as string
}
export {
ChartContainer,
ChartTooltip,
ChartTooltipContent,
ChartLegend,
ChartLegendContent,
ChartStyle,
}
Explanation not written yet, but this file contributes to the app's functionality.
src/components/ui/[Link]
"use client"
export { Checkbox }
Explanation not written yet, but this file contributes to the app's functionality.
src/components/ui/[Link]
"use client"
const DialogHeader = ({
className,
...props
}: [Link]<HTMLDivElement>) => (
<div
className={cn(
"flex flex-col space-y-1.5 text-center sm:text-left",
className
)}
{...props}
/>
)
[Link] = "DialogHeader"
const DialogFooter = ({
className,
...props
}: [Link]<HTMLDivElement>) => (
<div
className={cn(
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
className
)}
{...props}
/>
)
[Link] = "DialogFooter"
export {
Dialog,
DialogPortal,
DialogOverlay,
DialogClose,
DialogTrigger,
DialogContent,
DialogHeader,
DialogFooter,
DialogTitle,
DialogDescription,
}
Explanation not written yet, but this file contributes to the app's functionality.
src/components/ui/[Link]
"use client"
const DropdownMenuShortcut = ({
className,
...props
}: [Link]<HTMLSpanElement>) => {
return (
<span
className={cn("ml-auto text-xs tracking-widest opacity-60", className)}
{...props}
/>
)
}
[Link] = "DropdownMenuShortcut"
export {
DropdownMenu,
DropdownMenuTrigger,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuCheckboxItem,
DropdownMenuRadioItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuShortcut,
DropdownMenuGroup,
DropdownMenuPortal,
DropdownMenuSub,
DropdownMenuSubContent,
DropdownMenuSubTrigger,
DropdownMenuRadioGroup,
}
Explanation not written yet, but this file contributes to the app's functionality.
src/components/ui/[Link]
"use client"
type FormFieldContextValue<
TFieldValues extends FieldValues = FieldValues,
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>
> = {
name: TName
}
if (!fieldContext) {
throw new Error("useFormField should be used within <FormField>")
}
const { id } = itemContext
return {
id,
name: [Link],
formItemId: `${id}-form-item`,
formDescriptionId: `${id}-form-item-description`,
formMessageId: `${id}-form-item-message`,
...fieldState,
}
}
type FormItemContextValue = {
id: string
}
const FormItemContext = [Link]<FormItemContextValue>(
{} as FormItemContextValue
)
return (
<[Link] value={{ id }}>
<div ref={ref} className={cn("space-y-2", className)} {...props} />
</[Link]>
)
})
[Link] = "FormItem"
return (
<Label
ref={ref}
className={cn(error && "text-destructive", className)}
htmlFor={formItemId}
{...props}
/>
)
})
[Link] = "FormLabel"
return (
<Slot
ref={ref}
id={formItemId}
aria-describedby={
!error
? `${formDescriptionId}`
: `${formDescriptionId} ${formMessageId}`
}
aria-invalid={!!error}
{...props}
/>
)
})
[Link] = "FormControl"
return (
<p
ref={ref}
id={formDescriptionId}
className={cn("text-sm text-muted-foreground", className)}
{...props}
/>
)
})
[Link] = "FormDescription"
if (!body) {
return null
}
return (
<p
ref={ref}
id={formMessageId}
className={cn("text-sm font-medium text-destructive", className)}
{...props}
>
{body}
</p>
)
})
[Link] = "FormMessage"
export {
useFormField,
Form,
FormItem,
FormLabel,
FormControl,
FormDescription,
FormMessage,
FormField,
}
Explanation not written yet, but this file contributes to the app's functionality.
src/components/ui/[Link]
import * as React from "react"
export { Input }
Explanation not written yet, but this file contributes to the app's functionality.
src/components/ui/[Link]
"use client"
export { Label }
Explanation not written yet, but this file contributes to the app's functionality.
src/components/ui/[Link]
"use client"
function MenubarMenu({
...props
}: [Link]<typeof [Link]>) {
return <[Link] {...props} />
}
function MenubarGroup({
...props
}: [Link]<typeof [Link]>) {
return <[Link] {...props} />
}
function MenubarPortal({
...props
}: [Link]<typeof [Link]>) {
return <[Link] {...props} />
}
function MenubarRadioGroup({
...props
}: [Link]<typeof [Link]>) {
return <[Link] {...props} />
}
function MenubarSub({
...props
}: [Link]<typeof [Link]>) {
return <[Link] data-slot="menubar-sub" {...props} />
}
const MenubarShortcut = ({
className,
...props
}: [Link]<HTMLSpanElement>) => {
return (
<span
className={cn(
"ml-auto text-xs tracking-widest text-muted-foreground",
className
)}
{...props}
/>
)
}
[Link] = "MenubarShortcut"
export {
Menubar,
MenubarMenu,
MenubarTrigger,
MenubarContent,
MenubarItem,
MenubarSeparator,
MenubarLabel,
MenubarCheckboxItem,
MenubarRadioGroup,
MenubarRadioItem,
MenubarPortal,
MenubarSubContent,
MenubarSubTrigger,
MenubarGroup,
MenubarSub,
MenubarShortcut,
}
Explanation not written yet, but this file contributes to the app's functionality.
src/components/ui/[Link]
"use client"
export { Progress }
Explanation not written yet, but this file contributes to the app's functionality.
src/components/ui/[Link]
"use client"
<[Link]>{children}</[Link]>
</[Link]>
))
[Link] = [Link]
export {
Select,
SelectGroup,
SelectValue,
SelectTrigger,
SelectContent,
SelectLabel,
SelectItem,
SelectSeparator,
SelectScrollUpButton,
SelectScrollDownButton,
}
Explanation not written yet, but this file contributes to the app's functionality.
src/components/ui/[Link]
"use client"
export { Separator }
Explanation not written yet, but this file contributes to the app's functionality.
src/components/ui/[Link]
"use client"
interface SheetContentProps
extends [Link]<typeof [Link]>,
VariantProps<typeof sheetVariants> {}
const SheetHeader = ({
className,
...props
}: [Link]<HTMLDivElement>) => (
<div
className={cn(
"flex flex-col space-y-2 text-center sm:text-left",
className
)}
{...props}
/>
)
[Link] = "SheetHeader"
const SheetFooter = ({
className,
...props
}: [Link]<HTMLDivElement>) => (
<div
className={cn(
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
className
)}
{...props}
/>
)
[Link] = "SheetFooter"
export {
Sheet,
SheetPortal,
SheetOverlay,
SheetTrigger,
SheetClose,
SheetContent,
SheetHeader,
SheetFooter,
SheetTitle,
SheetDescription,
}
Explanation not written yet, but this file contributes to the app's functionality.
src/components/ui/[Link]
"use client"
type SidebarContext = {
state: "expanded" | "collapsed"
open: boolean
setOpen: (open: boolean) => void
openMobile: boolean
setOpenMobile: (open: boolean) => void
isMobile: boolean
toggleSidebar: () => void
}
function useSidebar() {
const context = [Link](SidebarContext)
if (!context) {
throw new Error("useSidebar must be used within a SidebarProvider.")
}
return context
}
[Link]("keydown", handleKeyDown)
return () => [Link]("keydown", handleKeyDown)
}, [toggleSidebar])
return (
<[Link] value={contextValue}>
<TooltipProvider delayDuration={0}>
<div
style={
{
"--sidebar-width": SIDEBAR_WIDTH,
"--sidebar-width-icon": SIDEBAR_WIDTH_ICON,
...style,
} as [Link]
}
className={cn(
"group/sidebar-wrapper flex w-full",
className
)}
ref={ref}
{...props}
>
{children}
</div>
</TooltipProvider>
</[Link]>
)
}
)
[Link] = "SidebarProvider"
if (isMobile) {
return (
<Sheet open={openMobile} onOpenChange={setOpenMobile} {...props}>
<SheetContent
data-sidebar="sidebar"
data-mobile="true"
className="w-[--sidebar-width] bg-sidebar p-0 text-sidebar-foreground [&>button]:hidden"
style={
{
"--sidebar-width": SIDEBAR_WIDTH_MOBILE,
} as [Link]
}
side={side}
>
<div className="flex h-full w-full flex-col">{children}</div>
</SheetContent>
</Sheet>
)
}
return (
<div
ref={ref}
className={cn(
"group peer text-sidebar-foreground transition-all duration-300",
"fixed inset-y-0 z-40 hidden h-screen md:flex",
side === "left" ? "left-0" : "right-0",
state === "expanded" ? "w-[var(--sidebar-width)]" : "w-[var(--sidebar-width-icon)]",
variant === "sidebar" && (side === 'left' ? 'border-r' : 'border-l'),
className
)}
data-state={state}
data-collapsible={collapsible}
data-variant={variant}
data-side={side}
{...props}
>
<div
data-sidebar="sidebar"
className={cn("flex h-full w-full flex-col bg-sidebar",
variant === 'floating' && 'm-2 rounded-lg border shadow-sm'
)}
>
{children}
</div>
</div>
)
}
)
[Link] = "Sidebar"
return (
<Button
ref={ref}
data-sidebar="trigger"
variant="ghost"
size="icon"
className={cn("h-7 w-7", className)}
onClick={(event) => {
onClick?.(event)
toggleSidebar()
}}
{...props}
>
<PanelLeft />
<span className="sr-only">Toggle Sidebar</span>
</Button>
)
})
[Link] = "SidebarTrigger"
return (
<Comp
ref={ref}
data-sidebar="group-action"
className={cn(
"absolute right-3 top-3.5 flex aspect-square w-5 items-center justify-center rounded-md p-0 text
// Increases the hit area of the button on mobile.
"after:absolute after:-inset-2 after:md:hidden",
"group-data-[state=collapsed]:hidden",
className
)}
{...props}
/>
)
})
[Link] = "SidebarGroupAction"
const button = (
<Comp
ref={ref}
data-sidebar="menu-button"
data-size={size}
data-active={isActive}
className={cn(sidebarMenuButtonVariants({ variant, size }), className)}
{...props}
/>
)
if (!tooltip) {
return button
}
return (
<Tooltip>
<TooltipTrigger asChild>{button}</TooltipTrigger>
<TooltipContent
side="right"
align="center"
hidden={state !== "collapsed" || isMobile}
{...tooltip}
/>
</Tooltip>
)
}
)
[Link] = "SidebarMenuButton"
return (
<Comp
ref={ref}
data-sidebar="menu-action"
className={cn(
"absolute right-1 top-1.5 flex aspect-square w-5 items-center justify-center rounded-md p-0 text
// Increases the hit area of the button on mobile.
"after:absolute after:-inset-2 after:md:hidden",
"peer-data-[size=sm]/menu-button:top-1",
"peer-data-[size=default]/menu-button:top-1.5",
"peer-data-[size=lg]/menu-button:top-2.5",
"group-data-[state=collapsed]:hidden",
showOnHover &&
"group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 data-[state=open]:
className
)}
{...props}
/>
)
})
[Link] = "SidebarMenuAction"
return (
<div
ref={ref}
data-sidebar="menu-skeleton"
className={cn("rounded-md h-8 flex gap-2 px-2 items-center", className)}
{...props}
>
{showIcon && (
<Skeleton
className="size-4 rounded-md"
data-sidebar="menu-skeleton-icon"
/>
)}
<Skeleton
className="h-4 flex-1 max-w-[--skeleton-width]"
data-sidebar="menu-skeleton-text"
style={
{
"--skeleton-width": width,
} as [Link]
}
/>
</div>
)
})
[Link] = "SidebarMenuSkeleton"
return (
<Comp
ref={ref}
data-sidebar="menu-sub-button"
data-size={size}
data-active={isActive}
className={cn(
"flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 text-sideba
"data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground",
size === "sm" && "text-xs",
size === "md" && "text-sm",
"group-data-[state=collapsed]:hidden",
className
)}
{...props}
/>
)
})
[Link] = "SidebarMenuSubButton"
export {
Sidebar,
SidebarContent,
SidebarFooter,
SidebarGroup,
SidebarGroupAction,
SidebarGroupContent,
SidebarGroupLabel,
SidebarHeader,
SidebarInput,
SidebarInset,
SidebarMenu,
SidebarMenuAction,
SidebarMenuBadge,
SidebarMenuButton,
SidebarMenuItem,
SidebarMenuSkeleton,
SidebarMenuSub,
SidebarMenuSubButton,
SidebarMenuSubItem,
SidebarProvider,
SidebarRail,
SidebarSeparator,
SidebarTrigger,
useSidebar,
}
Explanation not written yet, but this file contributes to the app's functionality.
src/components/ui/[Link]
import { cn } from "@/lib/utils"
function Skeleton({
className,
...props
}: [Link]<HTMLDivElement>) {
return (
<div
className={cn("animate-pulse rounded-md bg-muted", className)}
{...props}
/>
)
}
export { Skeleton }
Explanation not written yet, but this file contributes to the app's functionality.
src/components/ui/[Link]
"use client"
export { Slider }
Explanation not written yet, but this file contributes to the app's functionality.
src/components/ui/[Link]
"use client"
export { Switch }
Explanation not written yet, but this file contributes to the app's functionality.
src/components/ui/[Link]
import * as React from "react"
export {
Table,
TableHeader,
TableBody,
TableFooter,
TableHead,
TableRow,
TableCell,
TableCaption,
}
Explanation not written yet, but this file contributes to the app's functionality.
src/components/ui/[Link]
"use client"
export {Textarea};
Explanation not written yet, but this file contributes to the app's functionality.
src/components/ui/[Link]
"use client"
return (
<ToastProvider>
{[Link](function ({ id, title, description, action, ...props }) {
return (
<Toast key={id} {...props}>
<div className="grid gap-1">
{title && <ToastTitle>{title}</ToastTitle>}
{description && (
<ToastDescription>{description}</ToastDescription>
)}
</div>
{action}
<ToastClose />
</Toast>
)
})}
<ToastViewport />
</ToastProvider>
)
}
Explanation not written yet, but this file contributes to the app's functionality.
src/components/ui/[Link]
"use client"
export {
type ToastProps,
type ToastActionElement,
ToastProvider,
ToastViewport,
Toast,
ToastTitle,
ToastDescription,
ToastClose,
ToastAction,
}
Explanation not written yet, but this file contributes to the app's functionality.
src/context/[Link]
'use client';
interface AppContextType {
vitals: Vital[];
updateVitals: (name: VitalSign, value: number) => void;
user: Partial<User> | null;
isAdmin: boolean;
userProfile: UserProfile | null;
updateUserProfile: (profile: Partial<UserProfile>) => Promise<void>;
calorieTarget: number;
setCalorieTarget: (target: number) => void;
habits: Habit[];
addHabit: (habitName: string) => void;
}
const mockUser = {
uid: 'mock-user-123',
email: '[Link]@[Link]',
displayName: 'Dev User',
};
useEffect(() => {
// Check session memory for profile and habits
const profileFromSession = [Link]([Link]);
const habitsFromSession = [Link]([Link]);
if (profileFromSession) {
setUserProfile(profileFromSession);
} else {
[Link]([Link], defaultProfile);
setUserProfile(defaultProfile);
}
if (habitsFromSession) {
setHabits(habitsFromSession);
} else {
[Link]([Link], []);
setHabits([]);
}
}, []);
[Link] = [
...[Link],
{ time: 'now', value: currentValue + value }
].slice(-12);
} else {
[Link] = [Link]();
[Link] = [
...[Link],
{ time: 'now', value }
].slice(-12);
}
newVitals[vitalIndex] = updatedVital;
}
return newVitals;
});
};
[Link]([Link], updatedProfile);
setUserProfile(updatedProfile);
};
const value = {
vitals,
updateVitals,
user: mockUser,
isAdmin,
userProfile,
updateUserProfile,
calorieTarget,
setCalorieTarget,
habits,
addHabit,
};
return (
<[Link] value={value}>
{children}
</[Link]>
);
};
[Link](() => {
const mql = [Link](`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)
const onChange = () => {
setIsMobile([Link] < MOBILE_BREAKPOINT)
}
[Link]("change", onChange)
setIsMobile([Link] < MOBILE_BREAKPOINT)
return () => [Link]("change", onChange)
}, [])
return !!isMobile
}
Explanation not written yet, but this file contributes to the app's functionality.
src/hooks/[Link]
"use client"
import type {
ToastActionElement,
ToastProps,
} from "@/components/ui/toast"
const TOAST_LIMIT = 1
const TOAST_REMOVE_DELAY = 1000000
const actionTypes = {
ADD_TOAST: "ADD_TOAST",
UPDATE_TOAST: "UPDATE_TOAST",
DISMISS_TOAST: "DISMISS_TOAST",
REMOVE_TOAST: "REMOVE_TOAST",
} as const
let count = 0
function genId() {
count = (count + 1) % Number.MAX_SAFE_INTEGER
return [Link]()
}
type Action =
| {
type: ActionType["ADD_TOAST"]
toast: ToasterToast
}
| {
type: ActionType["UPDATE_TOAST"]
toast: Partial<ToasterToast>
}
| {
type: ActionType["DISMISS_TOAST"]
toastId?: ToasterToast["id"]
}
| {
type: ActionType["REMOVE_TOAST"]
toastId?: ToasterToast["id"]
}
interface State {
toasts: ToasterToast[]
}
[Link](toastId, timeout)
}
case "UPDATE_TOAST":
return {
...state,
toasts: [Link]((t) =>
[Link] === [Link] ? { ...t, ...[Link] } : t
),
}
case "DISMISS_TOAST": {
const { toastId } = action
return {
...state,
toasts: [Link]((t) =>
[Link] === toastId || toastId === undefined
? {
...t,
open: false,
}
: t
),
}
}
case "REMOVE_TOAST":
if ([Link] === undefined) {
return {
...state,
toasts: [],
}
}
return {
...state,
toasts: [Link]((t) => [Link] !== [Link]),
}
}
}
dispatch({
type: "ADD_TOAST",
toast: {
...props,
id,
open: true,
onOpenChange: (open) => {
if (!open) dismiss()
},
},
})
return {
id: id,
dismiss,
update,
}
}
function useToast() {
const [state, setState] = [Link]<State>(memoryState)
[Link](() => {
[Link](setState)
return () => {
const index = [Link](setState)
if (index > -1) {
[Link](index, 1)
}
}
}, [state])
return {
...state,
toast,
dismiss: (toastId?: string) => dispatch({ type: "DISMISS_TOAST", toastId }),
}
}
if (![Link]) {
[Link]({
credential: [Link](),
});
}
const firebaseConfig = {
projectId: 'vitalsai-q93v6',
appId: '1:43781547281:web:de2908fdcadcdaadef18b0',
storageBucket: '[Link]',
apiKey: 'AIzaSyD_JeJ39cbzXkjCSyy2tyJoavBWQzhkFCY',
authDomain: '[Link]',
measurementId: '',
messagingSenderId: '43781547281',
};
// Initialize Firebase
const app = !getApps().length ? initializeApp(firebaseConfig) : getApp();