"use client"; import { motion } from "framer-motion"; import { Cell, Legend, Line, LineChart, Pie, PieChart, ResponsiveContainer, Tooltip, XAxis, YAxis, } from "recharts"; import { FormEvent, useEffect, useMemo, useState } from "react"; type Mood = "happy" | "neutral" | "sad" | "angry"; type MoodScore = 4 | 3 | 2 | 1; type Energy = 1 | 2 | 3 | 4 | 5; type MoodEntry = { id: string; date: string; mood: Mood; mood_score: MoodScore; energy: Energy; }; const STORAGE_KEY = "mood-tracker-entries"; const moodConfig: Record< Mood, { label: string; icon: string; score: MoodScore; color: string } > = { happy: { label: "Mutlu", icon: "😊", score: 4, color: "#2f7d63" }, neutral: { label: "Nötr", icon: "😐", score: 3, color: "#4f7fbf" }, sad: { label: "Üzgün", icon: "😔", score: 2, color: "#e3aa38" }, angry: { label: "Sinirli", icon: "😠", score: 1, color: "#d8644a" }, }; const moodOptions = Object.entries(moodConfig) as Array< [Mood, (typeof moodConfig)[Mood]] >; const today = () => new Date().toISOString().slice(0, 10); const createId = () => typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : `${Date.now()}-${Math.random().toString(16).slice(2)}`; export default function Home() { const [entries, setEntries] = useState([]); const [date, setDate] = useState(today); const [mood, setMood] = useState("happy"); const [energy, setEnergy] = useState(3); const [message, setMessage] = useState(""); const [isLoaded, setIsLoaded] = useState(false); useEffect(() => { const rawEntries = window.localStorage.getItem(STORAGE_KEY); if (!rawEntries) { setIsLoaded(true); return; } try { const parsedEntries = JSON.parse(rawEntries) as MoodEntry[]; if (Array.isArray(parsedEntries)) { setEntries(sortEntries(parsedEntries)); } } catch { window.localStorage.removeItem(STORAGE_KEY); } finally { setIsLoaded(true); } }, []); useEffect(() => { if (!isLoaded) { return; } window.localStorage.setItem(STORAGE_KEY, JSON.stringify(entries)); }, [entries, isLoaded]); const lineData = useMemo( () => entries.map((entry) => ({ date: formatShortDate(entry.date), mood: entry.mood_score, energy: entry.energy, })), [entries], ); const pieData = useMemo( () => moodOptions .map(([key, config]) => ({ name: config.label, value: entries.filter((entry) => entry.mood === key).length, color: config.color, })) .filter((item) => item.value > 0), [entries], ); const insights = useMemo(() => buildInsights(entries), [entries]); function handleSubmit(event: FormEvent) { event.preventDefault(); if (!date) { setMessage("Lütfen tarih seç."); return; } if (!mood) { setMessage("Lütfen ruh halini seç."); return; } if (energy < 1 || energy > 5) { setMessage("Enerji seviyesi 1 ile 5 arasında olmalı."); return; } const moodScore = moodConfig[mood].score; setEntries((currentEntries) => { const existingEntry = currentEntries.find((entry) => entry.date === date); const nextEntry: MoodEntry = { id: existingEntry?.id ?? createId(), date, mood, mood_score: moodScore, energy, }; const nextEntries = existingEntry ? currentEntries.map((entry) => entry.date === date ? nextEntry : entry, ) : [...currentEntries, nextEntry]; return sortEntries(nextEntries); }); setMessage("Kayıt kaydedildi. Dashboard güncellendi."); } return (

Mood Tracker

Günlük ruh hali dashboard'u

{entries.length} kayıt

Bugünün kaydı

Aynı tarih tekrar kaydedilirse eski kayıt güncellenir.

setDate(event.target.value)} className="mt-2 w-full rounded-md border border-ink/15 bg-mist px-3 py-2 outline-none transition focus:border-leaf focus:ring-2 focus:ring-leaf/20" />
Ruh hali
{moodOptions.map(([key, config]) => ( ))}
setEnergy(Number(event.target.value) as Energy)} className="mt-3 w-full accent-leaf" />
1 2 3 4 5
{message ? (

{message}

) : null}
{entries.length > 0 ? ( ) : ( )}
{pieData.length > 0 ? ( {pieData.map((item) => ( ))} ) : ( )} {insights.length > 0 ? (
    {insights.map((insight) => (
  • {insight}
  • ))}
) : ( )}
); } function ChartCard({ title, children, }: { title: string; children: React.ReactNode; }) { return (

{title}

{children}
); } function EmptyState({ text }: { text: string }) { return (
{text}
); } function sortEntries(entries: MoodEntry[]) { return [...entries].sort((a, b) => a.date.localeCompare(b.date)); } function formatShortDate(date: string) { return new Intl.DateTimeFormat("tr-TR", { day: "2-digit", month: "short", }).format(new Date(`${date}T00:00:00`)); } function buildInsights(entries: MoodEntry[]) { if (entries.length === 0) { return []; } const latestSeven = [...entries] .sort((a, b) => b.date.localeCompare(a.date)) .slice(0, 7); const moodAverage = average(latestSeven.map((entry) => entry.mood_score)); const energyAverage = average(latestSeven.map((entry) => entry.energy)); const mostFrequentMood = getMostFrequentMood(entries); const insights = [ moodAverage >= 3 ? "Son 7 kayıtta genel ruh halin pozitif görünüyor." : "Son 7 kayıtta ruh hali ortalaman düşük görünüyor.", ]; if (energyAverage < 3) { insights.push("Enerji seviyen son kayıtlarda düşük seyrediyor."); } else { insights.push("Enerji seviyen son kayıtlarda dengeli görünüyor."); } if (mostFrequentMood) { insights.push( `En sık görülen ruh halin: ${moodConfig[mostFrequentMood].label}.`, ); } return insights; } function average(values: number[]) { return values.reduce((total, value) => total + value, 0) / values.length; } function getMostFrequentMood(entries: MoodEntry[]) { const counts = entries.reduce>( (currentCounts, entry) => { currentCounts[entry.mood] += 1; return currentCounts; }, { happy: 0, neutral: 0, sad: 0, angry: 0 }, ); return moodOptions.reduce((winner, [moodKey]) => { if (!winner || counts[moodKey] > counts[winner]) { return moodKey; } return winner; }, null); }