Create a React + Vite homework tracker app for two kids at ASCS (American School of Creativity Science). The app is called "ASCS Homework Tracker". Kids are Abdulla (Grade 2) and Salama (KG 1). Use the file structure and code below.

{
  "name": "ascs-homework-tracker",
  "version": "1.0.0",
  "private": true,
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview"
  },
  "dependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "lucide-react": "^0.383.0"
  },
  "devDependencies": {
    "@vitejs/plugin-react": "^4.2.0",
    "vite": "^5.0.0"
  }
}
export const KIDS = [
  {
    id: "abdulla",
    name: "Abdulla",
    grade: "Grade 2",
    emoji: "🦁",
    color: "#1D9E75",
    light: "#E1F5EE",
    dark: "#0F6E56",
  },
  {
    id: "salama",
    name: "Salama",
    grade: "KG 1",
    emoji: "🦋",
    color: "#D4537E",
    light: "#FBEAF0",
    dark: "#993556",
  },
];

export const SUBJECTS = {
  abdulla: ["Math", "English", "Arabic", "Science", "Islamic Studies", "Art", "PE"],
  salama: ["Phonics", "Math", "Arabic", "Islamic Studies", "Art", "PE", "Story Time"],
};

export const STATUSES = [
  { id: "new", label: "New", bg: "#E6F1FB", text: "#185FA5", dot: "#378ADD" },
  { id: "inprogress", label: "In Progress", bg: "#FAEEDA", text: "#854F0B", dot: "#EF9F27" },
  { id: "completed", label: "Done ✓", bg: "#EAF3DE", text: "#3B6D11", dot: "#639922" },
];

export const SOURCES = [
  "Teacher Portal",
  "Class WhatsApp",
  "Notebook",
  "Email",
  "Verbal (Teacher)",
  "School App",
  "Printed Sheet",
];

export const SUBJECT_ICONS = {
  Math: "🔢",
  English: "📖",
  Phonics: "📖",
  Arabic: "✍",
  Science: "🔬",
  Art: "🎨",
  PE: "⚽",
  "Islamic Studies": "🌙",
  "Story Time": "📚",
};

export const DAYS = ["Mon", "Tue", "Wed", "Thu", "Fri"];

export const SAMPLE_TASKS = {
  abdulla: [
    {
      id: 1,
      subject: "Math",
      title: "Addition worksheet p.12",
      status: "inprogress",
      source: "Notebook",
      type: "homework",
    },
    {
      id: 2,
      subject: "English",
      title: "Read pages 10–15 and answer questions",
      status: "new",
      source: "Teacher Portal",
      type: "homework",
    },
    {
      id: 3,
      subject: "Science",
      title: "Solar System Poster",
      status: "new",
      source: "Class WhatsApp",
      type: "project",
    },
  ],
  salama: [
    {
      id: 1,
      subject: "Phonics",
      title: "Letter B practice sheet",
      status: "completed",
      source: "Notebook",
      type: "homework",
    },
    {
      id: 2,
      subject: "Math",
      title: "Count to 20 worksheet",
      status: "new",
      source: "School App",
      type: "homework",
    },
    {
      id: 3,
      subject: "Art",
      title: "My Family Drawing",
      status: "inprogress",
      source: "Verbal (Teacher)",
      type: "project",
    },
  ],
};
import { useState, useEffect } from "react";
import { SAMPLE_TASKS } from "../data/constants";

function getWeekDates() {
  const today = new Date();
  const day = today.getDay();
  const monday = new Date(today);
  monday.setDate(today.getDate() - ((day + 6) % 7));
  return Array.from({ length: 5 }, (_, i) => {
    const d = new Date(monday);
    d.setDate(monday.getDate() + i);
    return d;
  });
}

// Assign default due dates spread across the week for sample tasks
function seedTasks() {
  const week = getWeekDates();
  return {
    abdulla: SAMPLE_TASKS.abdulla.map((t, i) => ({
      ...t,
      due: week[i + 1]?.toISOString().split("T")[0] || week[2].toISOString().split("T")[0],
    })),
    salama: SAMPLE_TASKS.salama.map((t, i) => ({
      ...t,
      due: week[i]?.toISOString().split("T")[0] || week[0].toISOString().split("T")[0],
    })),
  };
}

export function useTasks() {
  const [tasks, setTasks] = useState(() => {
    try {
      const saved = localStorage.getItem("ascs_tasks");
      return saved ? JSON.parse(saved) : seedTasks();
    } catch {
      return seedTasks();
    }
  });

  useEffect(() => {
    localStorage.setItem("ascs_tasks", JSON.stringify(tasks));
  }, [tasks]);

  function addTask(kidId, task) {
    setTasks((prev) => ({
      ...prev,
      [kidId]: [...prev[kidId], { ...task, id: Date.now() }],
    }));
  }

  function updateStatus(kidId, taskId, status) {
    setTasks((prev) => ({
      ...prev,
      [kidId]: prev[kidId].map((t) => (t.id === taskId ? { ...t, status } : t)),
    }));
  }

  function removeTask(kidId, taskId) {
    setTasks((prev) => ({
      ...prev,
      [kidId]: prev[kidId].filter((t) => t.id !== taskId),
    }));
  }

  return { tasks, addTask, updateStatus, removeTask };
}
import { useState } from "react";
import { KIDS, DAYS, STATUSES, SUBJECTS, SOURCES, SUBJECT_ICONS } from "./data/constants";
import { useTasks } from "./hooks/useTasks";
import "./App.css";

function getWeekDates() {
  const today = new Date();
  const monday = new Date(today);
  monday.setDate(today.getDate() - ((today.getDay() + 6) % 7));
  return Array.from({ length: 5 }, (_, i) => {
    const d = new Date(monday);
    d.setDate(monday.getDate() + i);
    return d;
  });
}

const EMPTY_FORM = { subject: "", title: "", status: "new", due: "", source: "Notebook", type: "homework" };

export default function App() {
  const [activeKid, setActiveKid] = useState("abdulla");
  const [activeDay, setActiveDay] = useState(() => {
    const d = new Date().getDay();
    return d >= 1 && d <= 5 ? d - 1 : 0;
  });
  const [activeTab, setActiveTab] = useState("homework");
  const [showForm, setShowForm] = useState(false);
  const [form, setForm] = useState(EMPTY_FORM);

  const { tasks, addTask, updateStatus, removeTask } = useTasks();
  const weekDates = getWeekDates();
  const today = new Date();
  const kid = KIDS.find((k) => k.id === activeKid);
  const kidTasks = tasks[activeKid] || [];
  const filtered = kidTasks.filter((t) => t.type === activeTab);
  const dayTasks = kidTasks.filter(
    (t) => new Date(t.due).toDateString() === weekDates[activeDay]?.toDateString()
  );

  const stats = {
    new: kidTasks.filter((t) => t.status === "new").length,
    inprogress: kidTasks.filter((t) => t.status === "inprogress").length,
    completed: kidTasks.filter((t) => t.status === "completed").length,
  };

  function handleAddTask() {
    if (!form.title || !form.subject || !form.due) return;
    addTask(activeKid, form);
    setForm(EMPTY_FORM);
    setShowForm(false);
    setActiveTab(form.type);
  }

  return (

      {/* Header */}
      <header className="header" style={{ background: `linear-gradient(135deg, ${kid.color} 0%, #185FA5 100%)` }}>

ASCS

American School of Creativity Science

Homework Tracker 📚

          {today.toLocaleDateString("en-US", { weekday: "long", year: "numeric", month: "long", day: "numeric" })}

      {/* Kid Switcher */}

        {KIDS.map((k) => (
          <button
            key={k.id}
            className={`kid-btn ${activeKid === k.id ? "active" : ""}`}
            style={{
              borderColor: activeKid === k.id ? k.color : "transparent",
              background: activeKid === k.id ? k.light : "#f5f5f5",
            }}
            onClick={() => setActiveKid(k.id)}
          >
            {k.emoji}
            {k.name}
            {k.grade}

              {STATUSES.map((s) => {
                const cnt = (tasks[k.id] || []).filter((t) => t.status === s.id).length;
                return cnt > 0 ? (
                  {cnt}
                ) : null;
              })}

          </button>
        ))}

      {/* Weekly Calendar */}

📅 This Week

          {weekDates.map((d, i) => {
            const isToday = d.toDateString() === today.toDateString();
            const hasTasks = kidTasks.filter((t) => new Date(t.due).toDateString() === d.toDateString()).length;
            return (
              <button
                key={i}
                className={`day-btn ${activeDay === i ? "active" : ""} ${isToday ? "today" : ""}`}
                style={{
                  borderColor: activeDay === i ? kid.color : isToday ? kid.color + "66" : "#e5e5e5",
                  background: activeDay === i ? kid.color : isToday ? kid.light : "white",
                }}
                onClick={() => setActiveDay(i)}
              >
                {DAYS[i]}
                {d.getDate()}
                {hasTasks > 0 && (

                )}
              </button>
            );
          })}

        {dayTasks.length > 0 && (

            Due {weekDates[activeDay]?.toLocaleDateString("en-US", { weekday: "short", month: "short", day: "numeric" })}:{" "}
            {dayTasks.map((t) => t.title).join(" • ")}

        )}

      {/* Stats */}

        {STATUSES.map((s) => (

            {stats[s.id]}
            {s.label}

        ))}

      {/* Tabs + Add button */}

        {["homework", "project"].map((tab) => (
          <button key={tab} className={`tab-btn ${activeTab === tab ? "active" : ""}`}
            style={{ background: activeTab === tab ? kid.color : "#f0f0f0", color: activeTab === tab ? "white" : "#666" }}
            onClick={() => setActiveTab(tab)}>
            {tab === "homework" ? "📝 Homework" : "🎨 Projects"}
          </button>
        ))}
        <button className="add-btn" style={{ background: kid.color }}
          onClick={() => { setForm({ ...EMPTY_FORM, type: activeTab }); setShowForm(true); }}>
          + Add
        </button>

      {/* Add Form */}
      {showForm && (

            ➕ New {form.type === "homework" ? "Homework" : "Project"} for {kid.name}

            <select value={form.subject} onChange={(e) => setForm((f) => ({ ...f, subject: e.target.value }))}>
              <option value="">📚 Select Subject</option>
              {SUBJECTS[activeKid].map((s) => <option key={s}>{s}</option>)}
            </select>
            <select value={form.status} onChange={(e) => setForm((f) => ({ ...f, status: e.target.value }))}>
              {STATUSES.map((s) => <option key={s.id} value={s.id}>{s.label}</option>)}
            </select>
            <input className="full-span" placeholder="Assignment title / description..."
              value={form.title} onChange={(e) => setForm((f) => ({ ...f, title: e.target.value }))} />
            <input type="date" value={form.due} onChange={(e) => setForm((f) => ({ ...f, due: e.target.value }))} />
            <select value={form.source} onChange={(e) => setForm((f) => ({ ...f, source: e.target.value }))}>
              {SOURCES.map((s) => <option key={s}>{s}</option>)}
            </select>
            <select value={form.type} onChange={(e) => setForm((f) => ({ ...f, type: e.target.value }))}>
              <option value="homework">Homework</option>
              <option value="project">Project</option>
            </select>

            <button className="save-btn" style={{ background: kid.color }} onClick={handleAddTask}>Save ✓</button>
            <button className="cancel-btn" onClick={() => setShowForm(false)}>Cancel</button>

      )}

      {/* Task List */}

        {filtered.length === 0 && (

{activeTab === "homework" ? "🎉" : "🌟"}

No {activeTab}s yet!

Tap + Add to add one

        )}
        {filtered.map((task) => {
          const st = STATUSES.find((s) => s.id === task.status);
          const dueDate = new Date(task.due);
          const isOverdue = dueDate < today && task.status !== "completed";
          return (
            <div key={task.id} className={`task-card ${isOverdue ? "overdue" : ""}`}>

                {SUBJECT_ICONS[task.subject] || "📚"}

{task.title}

                  {task.subject}
                  {st.label}

                    {isOverdue ? "⚠ " : "📅 "}
                    {dueDate.toLocaleDateString("en-US", { month: "short", day: "numeric" })}

                  via {task.source}

                <select value={task.status}
                  style={{ borderColor: kid.color, color: kid.dark }}
                  onChange={(e) => updateStatus(activeKid, task.id, e.target.value)}>
                  {STATUSES.map((s) => <option key={s.id} value={s.id}>{s.label}</option>)}
                </select>
                <button className="remove-btn" onClick={() => removeTask(activeKid, task.id)}>✕</button>

          );
        })}

      ASCS Homework Tracker • Made with ❤ for Abdulla & Salama

  );
}
* { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: system-ui, -apple-system, sans-serif; background: #f8f9fb; min-height: 100vh; }

.app { max-width: 820px; margin: 0 auto; padding: 16px; }

/* Header */
.header { border-radius: 16px; padding: 18px 20px; color: white; margin-bottom: 20px; }
.header-logo { display: flex; align-items: center; gap: 12px; margin-bottom: 6px; }
.logo-box { width: 48px; height: 48px; background: rgba(255,255,255,0.2); border-radius: 12px; display: flex; align-items: center; justify-content: center; font-size: 15px; font-weight: 800; letter-spacing: -0.5px; flex-shrink: 0; }
.school-name { font-size: 15px; font-weight: 700; }
.app-subtitle { font-size: 12px; opacity: 0.85; }
.header-date { font-size: 12px; opacity: 0.75; }

/* Kid Switcher */
.kid-switcher { display: flex; gap: 12px; margin-bottom: 20px; }
.kid-btn { flex: 1; padding: 14px 10px; border-radius: 14px; border: 2px solid transparent; cursor: pointer; text-align: center; transition: all 0.2s; }
.kid-btn.active { box-shadow: 0 2px 12px rgba(0,0,0,0.1); }
.kid-emoji { display: block; font-size: 30px; margin-bottom: 4px; }
.kid-name { display: block; font-size: 16px; font-weight: 700; }
.kid-grade { display: block; font-size: 12px; color: #666; margin-bottom: 6px; }
.kid-badges { display: flex; justify-content: center; gap: 4px; flex-wrap: wrap; }

/* Calendar */
.calendar-section { margin-bottom: 20px; }
.section-label { font-size: 13px; font-weight: 600; color: #555; margin-bottom: 8px; }
.calendar-row { display: flex; gap: 6px; }
.day-btn { flex: 1; padding: 8px 4px; border-radius: 12px; border: 2px solid; cursor: pointer; text-align: center; background: white; }
.day-name { display: block; font-size: 11px; font-weight: 600; }
.day-num { display: block; font-size: 17px; font-weight: 700; }
.day-dot { display: block; width: 6px; height: 6px; border-radius: 50%; margin: 3px auto 0; }
.day-summary { margin-top: 10px; padding: 10px 14px; border-radius: 10px; font-size: 13px; line-height: 1.5; }

/* Stats */
.stats-row { display: flex; gap: 10px; margin-bottom: 20px; }
.stat-card { flex: 1; padding: 12px 8px; border-radius: 12px; text-align: center; }
.stat-num { display: block; font-size: 26px; font-weight: 700; }
.stat-label { display: block; font-size: 11px; font-weight: 600; margin-top: 2px; }

/* Tabs */
.tab-row { display: flex; gap: 8px; align-items: center; margin-bottom: 16px; }
.tab-btn { padding: 9px 18px; border-radius: 20px; border: none; cursor: pointer; font-weight: 600; font-size: 13px; }
.add-btn { margin-left: auto; padding: 9px 18px; border-radius: 20px; border: none; cursor: pointer; font-weight: 700; font-size: 13px; color: white; }

/* Form */
.form-card { background: white; border: 2px solid; border-radius: 14px; padding: 16px; margin-bottom: 16px; }
.form-title { font-size: 14px; font-weight: 700; margin-bottom: 12px; }
.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.form-grid select, .form-grid input { padding: 9px 10px; border-radius: 8px; border: 1.5px solid #ddd; font-size: 13px; width: 100%; }
.full-span { grid-column: 1 / -1; }
.form-actions { display: flex; gap: 8px; margin-top: 12px; }
.save-btn { flex: 1; padding: 10px; border-radius: 10px; border: none; color: white; font-weight: 700; cursor: pointer; font-size: 14px; }
.cancel-btn { padding: 10px 18px; border-radius: 10px; border: 1.5px solid #ddd; background: white; cursor: pointer; font-size: 14px; }

/* Task List */
.task-list { display: flex; flex-direction: column; gap: 10px; }
.task-card { background: white; border-radius: 14px; border: 1.5px solid #e8e8e8; padding: 12px 14px; display: flex; align-items: flex-start; gap: 12px; }
.task-card.overdue { border-color: #F09595; }
.task-icon { width: 42px; height: 42px; border-radius: 10px; display: flex; align-items: center; justify-content: center; font-size: 20px; flex-shrink: 0; }
.task-body { flex: 1; min-width: 0; }
.task-title { font-weight: 700; font-size: 14px; color: #222; margin-bottom: 5px; }
.task-meta { display: flex; flex-wrap: wrap; gap: 5px; align-items: center; }
.badge { font-size: 11px; padding: 2px 8px; border-radius: 20px; font-weight: 600; }
.task-due { font-size: 11px; }
.task-source { font-size: 11px; color: #aaa; }
.task-actions { display: flex; flex-direction: column; gap: 5px; flex-shrink: 0; }
.task-actions select { font-size: 11px; padding: 5px 6px; border-radius: 8px; border: 1.5px solid; background: white; cursor: pointer; }
.remove-btn { font-size: 11px; padding: 4px 8px; border-radius: 8px; border: 1px solid #eee; background: white; color: #E24B4A; cursor: pointer; }

/* Empty State */
.empty-state { text-align: center; padding: 32px 20px; border-radius: 14px; }
.empty-emoji { font-size: 40px; margin-bottom: 8px; }
.empty-title { font-size: 16px; font-weight: 700; }
.empty-sub { font-size: 13px; opacity: 0.75; margin-top: 4px; }

/* Footer */
.footer { text-align: center; margin-top: 24px; padding: 12px; font-size: 12px; color: #bbb; }

/* Responsive */
@media (max-width: 480px) {
  .form-grid { grid-template-columns: 1fr; }
  .full-span { grid-column: 1; }
  .school-name { font-size: 13px; }
}
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App.jsx";

ReactDOM.createRoot(document.getElementById("root")).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);
<!DOCTYPE html>

    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>ASCS Homework Tracker</title>
    <link rel="icon" type="image/svg+xml" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>📚</text></svg>" />

import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App.jsx";

ReactDOM.createRoot(document.getElementById("root")).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);
<!DOCTYPE html>

    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>ASCS Homework Tracker</title>
    <link rel="icon" type="image/svg+xml" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>📚</text></svg>" />

Mobily friendly
Best UI UX


## plugin:context7:context7
Use this server to fetch current documentation whenever the user asks about a library, framework, SDK, API, CLI tool, or cloud service -- even well-known ones like React, Next.js, Prisma, Express, Tailwind, Django, or Spring Boot. This includes API syntax, configuration, version migration, library-specific debugging, setup instructions, and CLI tool usage. Use even when you think you know the answer -- your training data may not reflect recent changes. Prefer this over web search for library docs.

Do not use for: refactoring, writing scripts from scratch, debugging business logic, code review, or general programming concepts.


Bash

mkdir -p /Users/khalidbinkalban/ascs-homework-tracker/src/data /Users/khalidbinkalban/ascs-homework-tracker/src/hooks && ls /Users/khalidbinkalban/ascs-homework-tracker


src


Write

{
  "name": "ascs-homework-tracker",
  "version": "1.0.0",
  "private": true,
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview"
  },
  "dependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "lucide-react": "^0.383.0"
  },
  "devDependencies": {
    "@vitejs/plugin-react": "^4.2.0",
    "vite": "^5.0.0"
  }
}


File created successfully at: /Users/khalidbinkalban/ascs-homework-tracker/package.json


import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";

export default defineConfig({
  plugins: [react()],
});


File created successfully at: /Users/khalidbinkalban/ascs-homework-tracker/vite.config.js

import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";

export default defineConfig({
  plugins: [react()],
});


<!DOCTYPE html>

    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>ASCS Homework Tracker</title>
    <link rel="icon" type="image/svg+xml" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>📚</text></svg>" />


File created successfully at: /Users/khalidbinkalban/ascs-homework-tracker/index.html

<!DOCTYPE html>

    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>ASCS Homework Tracker</title>
    <link rel="icon" type="image/svg+xml" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>📚</text></svg>" />


import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App.jsx";

ReactDOM.createRoot(document.getElementById("root")).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);


File created successfully at: /Users/khalidbinkalban/ascs-homework-tracker/src/main.jsx

import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App.jsx";

ReactDOM.createRoot(document.getElementById("root")).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);


export const KIDS = [
  {
    id: "abdulla",
    name: "Abdulla",
    grade: "Grade 2",
    emoji: "🦁",
    color: "#1D9E75",
    light: "#E1F5EE",
    dark: "#0F6E56",
  },
  {
    id: "salama",
    name: "Salama",
    grade: "KG 1",
    emoji: "🦋",
    color: "#D4537E",
    light: "#FBEAF0",
    dark: "#993556",
  },
];

export const SUBJECTS = {
  abdulla: ["Math", "English", "Arabic", "Science", "Islamic Studies", "Art", "PE"],
  salama: ["Phonics", "Math", "Arabic", "Islamic Studies", "Art", "PE", "Story Time"],
};

export const STATUSES = [
  { id: "new", label: "New", bg: "#E6F1FB", text: "#185FA5", dot: "#378ADD" },
  { id: "inprogress", label: "In Progress", bg: "#FAEEDA", text: "#854F0B", dot: "#EF9F27" },
  { id: "completed", label: "Done ✓", bg: "#EAF3DE", text: "#3B6D11", dot: "#639922" },
];

export const SOURCES = [
  "Teacher Portal",
  "Class WhatsApp",
  "Notebook",
  "Email",
  "Verbal (Teacher)",
  "School App",
  "Printed Sheet",
];

export const SUBJECT_ICONS = {
  Math: "🔢",
  English: "📖",
  Phonics: "📖",
  Arabic: "✍",
  Science: "🔬",
  Art: "🎨",
  PE: "⚽",
  "Islamic Studies": "🌙",
  "Story Time": "📚",
};

export const DAYS = ["Mon", "Tue", "Wed", "Thu", "Fri"];

export const SAMPLE_TASKS = {
  abdulla: [
    {
      id: 1,
      subject: "Math",
      title: "Addition worksheet p.12",
      status: "inprogress",
      source: "Notebook",
      type: "homework",
    },
    {
      id: 2,
      subject: "English",
      title: "Read pages 10–15 and answer questions",
      status: "new",
      source: "Teacher Portal",
      type: "homework",
    },
    {
      id: 3,
      subject: "Science",
      title: "Solar System Poster",
      status: "new",
      source: "Class WhatsApp",
      type: "project",
    },
  ],
  salama: [
    {
      id: 1,
      subject: "Phonics",
      title: "Letter B practice sheet",
      status: "completed",
      source: "Notebook",
      type: "homework",
    },
    {
      id: 2,
      subject: "Math",
      title: "Count to 20 worksheet",
      status: "new",
      source: "School App",
      type: "homework",
    },
    {
      id: 3,
      subject: "Art",
      title: "My Family Drawing",
      status: "inprogress",
      source: "Verbal (Teacher)",
      type: "project",
    },
  ],
};


File created successfully at: /Users/khalidbinkalban/ascs-homework-tracker/src/data/constants.js

export const KIDS = [
  {
    id: "abdulla",
    name: "Abdulla",
    grade: "Grade 2",
    emoji: "🦁",
    color: "#1D9E75",
    light: "#E1F5EE",
    dark: "#0F6E56",
  },
  {
    id: "salama",
    name: "Salama",
    grade: "KG 1",
    emoji: "🦋",
    color: "#D4537E",
    light: "#FBEAF0",
    dark: "#993556",
  },
];

export const SUBJECTS = {
  abdulla: ["Math", "English", "Arabic", "Science", "Islamic Studies", "Art", "PE"],
  salama: ["Phonics", "Math", "Arabic", "Islamic Studies", "Art", "PE", "Story Time"],
};

export const STATUSES = [
  { id: "new", label: "New", bg: "#E6F1FB", text: "#185FA5", dot: "#378ADD" },
  { id: "inprogress", label: "In Progress", bg: "#FAEEDA", text: "#854F0B", dot: "#EF9F27" },
  { id: "completed", label: "Done ✓", bg: "#EAF3DE", text: "#3B6D11", dot: "#639922" },
];

export const SOURCES = [
  "Teacher Portal",
  "Class WhatsApp",
  "Notebook",
  "Email",
  "Verbal (Teacher)",
  "School App",
  "Printed Sheet",
];

export const SUBJECT_ICONS = {
  Math: "🔢",
  English: "📖",
  Phonics: "📖",
  Arabic: "✍",
  Science: "🔬",
  Art: "🎨",
  PE: "⚽",
  "Islamic Studies": "🌙",
  "Story Time": "📚",
};

export const DAYS = ["Mon", "Tue", "Wed", "Thu", "Fri"];

export const SAMPLE_TASKS = {
  abdulla: [
    {
      id: 1,
      subject: "Math",
      title: "Addition worksheet p.12",
      status: "inprogress",
      source: "Notebook",
      type: "homework",
    },
    {
      id: 2,
      subject: "English",
      title: "Read pages 10–15 and answer questions",
      status: "new",
      source: "Teacher Portal",
      type: "homework",
    },
    {
      id: 3,
      subject: "Science",
      title: "Solar System Poster",
      status: "new",
      source: "Class WhatsApp",
      type: "project",
    },
  ],
  salama: [
    {
      id: 1,
      subject: "Phonics",
      title: "Letter B practice sheet",
      status: "completed",
      source: "Notebook",
      type: "homework",
    },
    {
      id: 2,
      subject: "Math",
      title: "Count to 20 worksheet",
      status: "new",
      source: "School App",
      type: "homework",
    },
    {
      id: 3,
      subject: "Art",
      title: "My Family Drawing",
      status: "inprogress",
      source: "Verbal (Teacher)",
      type: "project",
    },
  ],
};


import { useState, useEffect } from "react";
import { SAMPLE_TASKS } from "../data/constants";

function getWeekDates() {
  const today = new Date();
  const day = today.getDay();
  const monday = new Date(today);
  monday.setDate(today.getDate() - ((day + 6) % 7));
  return Array.from({ length: 5 }, (_, i) => {
    const d = new Date(monday);
    d.setDate(monday.getDate() + i);
    return d;
  });
}

function seedTasks() {
  const week = getWeekDates();
  return {
    abdulla: SAMPLE_TASKS.abdulla.map((t, i) => ({
      ...t,
      due: week[i + 1]?.toISOString().split("T")[0] || week[2].toISOString().split("T")[0],
    })),
    salama: SAMPLE_TASKS.salama.map((t, i) => ({
      ...t,
      due: week[i]?.toISOString().split("T")[0] || week[0].toISOString().split("T")[0],
    })),
  };
}

export function useTasks() {
  const [tasks, setTasks] = useState(() => {
    try {
      const saved = localStorage.getItem("ascs_tasks");
      return saved ? JSON.parse(saved) : seedTasks();
    } catch {
      return seedTasks();
    }
  });

  useEffect(() => {
    localStorage.setItem("ascs_tasks", JSON.stringify(tasks));
  }, [tasks]);

  function addTask(kidId, task) {
    setTasks((prev) => ({
      ...prev,
      [kidId]: [...prev[kidId], { ...task, id: Date.now() }],
    }));
  }

  function updateStatus(kidId, taskId, status) {
    setTasks((prev) => ({
      ...prev,
      [kidId]: prev[kidId].map((t) => (t.id === taskId ? { ...t, status } : t)),
    }));
  }

  function removeTask(kidId, taskId) {
    setTasks((prev) => ({
      ...prev,
      [kidId]: prev[kidId].filter((t) => t.id !== taskId),
    }));
  }

  return { tasks, addTask, updateStatus, removeTask };
}


File created successfully at: /Users/khalidbinkalban/ascs-homework-tracker/src/hooks/useTasks.js

import { useState, useEffect } from "react";
import { SAMPLE_TASKS } from "../data/constants";

function getWeekDates() {
  const today = new Date();
  const day = today.getDay();
  const monday = new Date(today);
  monday.setDate(today.getDate() - ((day + 6) % 7));
  return Array.from({ length: 5 }, (_, i) => {
    const d = new Date(monday);
    d.setDate(monday.getDate() + i);
    return d;
  });
}

function seedTasks() {
  const week = getWeekDates();
  return {
    abdulla: SAMPLE_TASKS.abdulla.map((t, i) => ({
      ...t,
      due: week[i + 1]?.toISOString().split("T")[0] || week[2].toISOString().split("T")[0],
    })),
    salama: SAMPLE_TASKS.salama.map((t, i) => ({
      ...t,
      due: week[i]?.toISOString().split("T")[0] || week[0].toISOString().split("T")[0],
    })),
  };
}

export function useTasks() {
  const [tasks, setTasks] = useState(() => {
    try {
      const saved = localStorage.getItem("ascs_tasks");
      return saved ? JSON.parse(saved) : seedTasks();
    } catch {
      return seedTasks();
    }
  });

  useEffect(() => {
    localStorage.setItem("ascs_tasks", JSON.stringify(tasks));
  }, [tasks]);

  function addTask(kidId, task) {
    setTasks((prev) => ({
      ...prev,
      [kidId]: [...prev[kidId], { ...task, id: Date.now() }],
    }));
  }

  function updateStatus(kidId, taskId, status) {
    setTasks((prev) => ({
      ...prev,
      [kidId]: prev[kidId].map((t) => (t.id === taskId ? { ...t, status } : t)),
    }));
  }

  function removeTask(kidId, taskId) {
    setTasks((prev) => ({
      ...prev,
      [kidId]: prev[kidId].filter((t) => t.id !== taskId),
    }));
  }

  return { tasks, addTask, updateStatus, removeTask };
}


Now I'll create the enhanced App.jsx and App.css with best-in-class mobile-first UI/UX improvements:


import { useState } from "react";
import { KIDS, DAYS, STATUSES, SUBJECTS, SOURCES, SUBJECT_ICONS } from "./data/constants";
import { useTasks } from "./hooks/useTasks";
import "./App.css";

function getWeekDates() {
  const today = new Date();
  const monday = new Date(today);
  monday.setDate(today.getDate() - ((today.getDay() + 6) % 7));
  return Array.from({ length: 5 }, (_, i) => {
    const d = new Date(monday);
    d.setDate(monday.getDate() + i);
    return d;
  });
}

const EMPTY_FORM = {
  subject: "",
  title: "",
  status: "new",
  due: "",
  source: "Notebook",
  type: "homework",
};

export default function App() {
  const [activeKid, setActiveKid] = useState("abdulla");
  const [activeDay, setActiveDay] = useState(() => {
    const d = new Date().getDay();
    return d >= 1 && d <= 5 ? d - 1 : 0;
  });
  const [activeTab, setActiveTab] = useState("homework");
  const [showForm, setShowForm] = useState(false);
  const [form, setForm] = useState(EMPTY_FORM);
  const [editingId, setEditingId] = useState(null);

  const { tasks, addTask, updateStatus, removeTask, updateTask } = useTasks();
  const weekDates = getWeekDates();
  const today = new Date();
  const kid = KIDS.find((k) => k.id === activeKid);
  const kidTasks = tasks[activeKid] || [];
  const filtered = kidTasks.filter((t) => t.type === activeTab);
  const dayTasks = kidTasks.filter(
    (t) => new Date(t.due + "T00:00:00").toDateString() === weekDates[activeDay]?.toDateString()
  );

  const stats = {
    new: kidTasks.filter((t) => t.status === "new").length,
    inprogress: kidTasks.filter((t) => t.status === "inprogress").length,
    completed: kidTasks.filter((t) => t.status === "completed").length,
  };

  const totalDone = kidTasks.filter((t) => t.status === "completed").length;
  const progressPct = kidTasks.length > 0 ? Math.round((totalDone / kidTasks.length) * 100) : 0;

  function handleAddTask() {
    if (!form.title || !form.subject || !form.due) return;
    addTask(activeKid, form);
    setForm(EMPTY_FORM);
    setShowForm(false);
    setActiveTab(form.type);
  }

  function openForm() {
    setForm({ ...EMPTY_FORM, type: activeTab });
    setShowForm(true);
    setEditingId(null);
    setTimeout(() => {
      document.querySelector(".form-card")?.scrollIntoView({ behavior: "smooth", block: "nearest" });
    }, 100);
  }

  const todayStr = today.toLocaleDateString("en-US", {
    weekday: "long",
    year: "numeric",
    month: "long",
    day: "numeric",
  });

  return (

      {/* Header */}
      <header
        className="header"
        style={{
          background: `linear-gradient(135deg, ${kid.color} 0%, #185FA5 100%)`,
        }}
      >

ASCS

American School of Creativity Science

Homework Tracker 📚

{todayStr}

        {/* Progress bar in header */}

            {kid.name}'s Overall Progress
            {progressPct}%

            <div
              className="progress-fill"
              style={{ width: `${progressPct}%` }}
            />

      {/* Kid Switcher */}

        {KIDS.map((k) => {
          const kTasks = tasks[k.id] || [];
          const kDone = kTasks.filter((t) => t.status === "completed").length;
          const kPct = kTasks.length > 0 ? Math.round((kDone / kTasks.length) * 100) : 0;
          return (
            <button
              key={k.id}
              className={`kid-btn ${activeKid === k.id ? "active" : ""}`}
              style={{
                borderColor: activeKid === k.id ? k.color : "transparent",
                background: activeKid === k.id ? k.light : "#f5f7fa",
              }}
              onClick={() => setActiveKid(k.id)}
            >
              {k.emoji}

                {k.name}

              {k.grade}

                <div
                  className="kid-mini-fill"
                  style={{
                    width: `${kPct}%`,
                    background: k.color,
                  }}
                />

                {STATUSES.map((s) => {
                  const cnt = kTasks.filter((t) => t.status === s.id).length;
                  return cnt > 0 ? (

                      {cnt}

                  ) : null;
                })}

            </button>
          );
        })}

      {/* Weekly Calendar */}

📅 This Week

          {weekDates.map((d, i) => {
            const isToday = d.toDateString() === today.toDateString();
            const dayTaskCount = kidTasks.filter(
              (t) => new Date(t.due + "T00:00:00").toDateString() === d.toDateString()
            ).length;
            const doneCount = kidTasks.filter(
              (t) =>
                new Date(t.due + "T00:00:00").toDateString() === d.toDateString() &&
                t.status === "completed"
            ).length;
            return (
              <button
                key={i}
                className={`day-btn ${activeDay === i ? "active" : ""} ${isToday ? "today" : ""}`}
                style={{
                  borderColor:
                    activeDay === i
                      ? kid.color
                      : isToday
                      ? kid.color + "66"
                      : "#e5e8f0",
                  background:
                    activeDay === i ? kid.color : isToday ? kid.light : "white",
                }}
                onClick={() => setActiveDay(i)}
              >

                  {DAYS[i]}

                  {d.getDate()}

                {dayTaskCount > 0 && (

                    {doneCount}/{dayTaskCount}

                )}
              </button>
            );
          })}

        {dayTasks.length > 0 && (
          <div
            className="day-summary"
            style={{ background: kid.light, borderLeft: `3px solid ${kid.color}` }}
          >

              Due{" "}
              {weekDates[activeDay]?.toLocaleDateString("en-US", {
                weekday: "short",
                month: "short",
                day: "numeric",
              })}
              :

              {dayTasks.map((t) => {
                const st = STATUSES.find((s) => s.id === t.status);
                return (

                    {SUBJECT_ICONS[t.subject] || "📚"} {t.title.length > 28 ? t.title.slice(0, 28) + "…" : t.title}

                );
              })}

        )}

      {/* Stats */}

        {STATUSES.map((s) => (
          <div
            key={s.id}
            className="stat-card"
            style={{ background: s.bg, borderTop: `3px solid ${s.dot}` }}
          >

              {stats[s.id]}

              {s.label}

        ))}

      {/* Tabs + Add button */}

        {["homework", "project"].map((tab) => (
          <button
            key={tab}
            className={`tab-btn ${activeTab === tab ? "active" : ""}`}
            style={{
              background: activeTab === tab ? kid.color : "#f0f2f5",
              color: activeTab === tab ? "white" : "#666",
              boxShadow: activeTab === tab ? `0 4px 14px ${kid.color}44` : "none",
            }}
            onClick={() => setActiveTab(tab)}
          >
            {tab === "homework" ? "📝 Homework" : "🎨 Projects"}

              {kidTasks.filter((t) => t.type === tab).length}

          </button>
        ))}
        <button
          className="add-btn"
          style={{
            background: kid.color,
            boxShadow: `0 4px 14px ${kid.color}66`,
          }}
          onClick={openForm}
        >
          +
          Add
        </button>

      {/* Add Form */}
      {showForm && (

              ➕ New {form.type === "homework" ? "Homework" : "Project"} for {kid.name} {kid.emoji}

            <button className="form-close" onClick={() => setShowForm(false)}>
              ✕
            </button>

              Subject
              <select
                value={form.subject}
                onChange={(e) => setForm((f) => ({ ...f, subject: e.target.value }))}
                style={{ borderColor: form.subject ? kid.color : "#ddd" }}
              >
                <option value="">Select subject…</option>
                {SUBJECTS[activeKid].map((s) => (
                  <option key={s}>
                    {SUBJECT_ICONS[s]} {s}
                  </option>
                ))}
              </select>

              Status
              <select
                value={form.status}
                onChange={(e) => setForm((f) => ({ ...f, status: e.target.value }))}
                style={{ borderColor: kid.color }}
              >
                {STATUSES.map((s) => (
                  <option key={s.id} value={s.id}>
                    {s.label}
                  </option>
                ))}
              </select>

              Assignment description
              <input
                placeholder="e.g. Read chapter 3 and answer questions…"
                value={form.title}
                onChange={(e) => setForm((f) => ({ ...f, title: e.target.value }))}
                style={{ borderColor: form.title ? kid.color : "#ddd" }}
              />

              Due Date
              <input
                type="date"
                value={form.due}
                onChange={(e) => setForm((f) => ({ ...f, due: e.target.value }))}
                style={{ borderColor: form.due ? kid.color : "#ddd" }}
              />

              Source
              <select
                value={form.source}
                onChange={(e) => setForm((f) => ({ ...f, source: e.target.value }))}
                style={{ borderColor: kid.color }}
              >
                {SOURCES.map((s) => (
                  <option key={s}>{s}</option>
                ))}
              </select>

              Type

                {["homework", "project"].map((t) => (
                  <button
                    key={t}
                    className={`type-opt ${form.type === t ? "selected" : ""}`}
                    style={{
                      background: form.type === t ? kid.color : "transparent",
                      color: form.type === t ? "white" : "#666",
                      borderColor: form.type === t ? kid.color : "#ddd",
                    }}
                    onClick={() => setForm((f) => ({ ...f, type: t }))}
                    type="button"
                  >
                    {t === "homework" ? "📝 Homework" : "🎨 Project"}
                  </button>
                ))}

            <button
              className="save-btn"
              style={{
                background:
                  form.title && form.subject && form.due ? kid.color : "#ccc",
                boxShadow:
                  form.title && form.subject && form.due
                    ? `0 4px 14px ${kid.color}55`
                    : "none",
              }}
              onClick={handleAddTask}
              disabled={!form.title || !form.subject || !form.due}
            >
              Save Assignment ✓
            </button>
            <button className="cancel-btn" onClick={() => setShowForm(false)}>
              Cancel
            </button>

      )}

      {/* Task List */}

        {filtered.length === 0 ? (

              {activeTab === "homework" ? "🎉" : "🌟"}

              No {activeTab}s yet!

Tap + Add to add one

            <button
              className="empty-add-btn"
              style={{ background: kid.color, boxShadow: `0 4px 14px ${kid.color}55` }}
              onClick={openForm}
            >
              + Add {activeTab === "homework" ? "Homework" : "Project"}
            </button>

        ) : (
          filtered.map((task) => {
            const st = STATUSES.find((s) => s.id === task.status);
            const dueDate = new Date(task.due + "T00:00:00");
            const isOverdue =
              dueDate < today && task.status !== "completed";
            const isDueToday = dueDate.toDateString() === today.toDateString();
            return (
              <div
                key={task.id}
                className={`task-card ${isOverdue ? "overdue" : ""} ${task.status === "completed" ? "done" : ""}`}
                style={{
                  borderLeft: `4px solid ${isOverdue ? "#E24B4A" : task.status === "completed" ? "#639922" : kid.color}`,
                }}
              >

                  {SUBJECT_ICONS[task.subject] || "📚"}

                    {task.title}

                      {task.subject}

                      {st.label}

                      {isOverdue ? "⚠ " : isDueToday ? "🔔 " : "📅 "}
                      {isOverdue
                        ? "Overdue · "
                        : isDueToday
                        ? "Today · "
                        : ""}
                      {dueDate.toLocaleDateString("en-US", {
                        month: "short",
                        day: "numeric",
                      })}

                    via {task.source}

                  <select
                    value={task.status}
                    style={{ borderColor: kid.color + "88", color: kid.dark }}
                    onChange={(e) =>
                      updateStatus(activeKid, task.id, e.target.value)
                    }
                  >
                    {STATUSES.map((s) => (
                      <option key={s.id} value={s.id}>
                        {s.label}
                      </option>
                    ))}
                  </select>
                  <button
                    className="remove-btn"
                    onClick={() => removeTask(activeKid, task.id)}
                    title="Remove task"
                  >
                    ✕
                  </button>

            );
          })
        )}

        ASCS Homework Tracker
        •
        Made with ❤ for Abdulla & Salama

  );
}


File created successfully at: /Users/khalidbinkalban/ascs-homework-tracker/src/App.jsx

import { useState } from "react";
import { KIDS, DAYS, STATUSES, SUBJECTS, SOURCES, SUBJECT_ICONS } from "./data/constants";
import { useTasks } from "./hooks/useTasks";
import "./App.css";

function getWeekDates() {
  const today = new Date();
  const monday = new Date(today);
  monday.setDate(today.getDate() - ((today.getDay() + 6) % 7));
  return Array.from({ length: 5 }, (_, i) => {
    const d = new Date(monday);
    d.setDate(monday.getDate() + i);
    return d;
  });
}

const EMPTY_FORM = {
  subject: "",
  title: "",
  status: "new",
  due: "",
  source: "Notebook",
  type: "homework",
};

export default function App() {
  const [activeKid, setActiveKid] = useState("abdulla");
  const [activeDay, setActiveDay] = useState(() => {
    const d = new Date().getDay();
    return d >= 1 && d <= 5 ? d - 1 : 0;
  });
  const [activeTab, setActiveTab] = useState("homework");
  const [showForm, setShowForm] = useState(false);
  const [form, setForm] = useState(EMPTY_FORM);
  const [editingId, setEditingId] = useState(null);

  const { tasks, addTask, updateStatus, removeTask, updateTask } = useTasks();
  const weekDates = getWeekDates();
  const today = new Date();
  const kid = KIDS.find((k) => k.id === activeKid);
  const kidTasks = tasks[activeKid] || [];
  const filtered = kidTasks.filter((t) => t.type === activeTab);
  const dayTasks = kidTasks.filter(
    (t) => new Date(t.due + "T00:00:00").toDateString() === weekDates[activeDay]?.toDateString()
  );

  const stats = {
    new: kidTasks.filter((t) => t.status === "new").length,
    inprogress: kidTasks.filter((t) => t.status === "inprogress").length,
    completed: kidTasks.filter((t) => t.status === "completed").length,
  };

  const totalDone = kidTasks.filter((t) => t.status === "completed").length;
  const progressPct = kidTasks.length > 0 ? Math.round((totalDone / kidTasks.length) * 100) : 0;

  function handleAddTask() {
    if (!form.title || !form.subject || !form.due) return;
    addTask(activeKid, form);
    setForm(EMPTY_FORM);
    setShowForm(false);
    setActiveTab(form.type);
  }

  function openForm() {
    setForm({ ...EMPTY_FORM, type: activeTab });
    setShowForm(true);
    setEditingId(null);
    setTimeout(() => {
      document.querySelector(".form-card")?.scrollIntoView({ behavior: "smooth", block: "nearest" });
    }, 100);
  }

  const todayStr = today.toLocaleDateString("en-US", {
    weekday: "long",
    year: "numeric",
    month: "long",
    day: "numeric",
  });

  return (

      {/* Header */}
      <header
        className="header"
        style={{
          background: `linear-gradient(135deg, ${kid.color} 0%, #185FA5 100%)`,
        }}
      >

ASCS

American School of Creativity Science

Homework Tracker 📚

{todayStr}

        {/* Progress bar in header */}

            {kid.name}'s Overall Progress
            {progressPct}%

            <div
              className="progress-fill"
              style={{ width: `${progressPct}%` }}
            />

      {/* Kid Switcher */}

        {KIDS.map((k) => {
          const kTasks = tasks[k.id] || [];
          const kDone = kTasks.filter((t) => t.status === "completed").length;
          const kPct = kTasks.length > 0 ? Math.round((kDone / kTasks.length) * 100) : 0;
          return (
            <button
              key={k.id}
              className={`kid-btn ${activeKid === k.id ? "active" : ""}`}
              style={{
                borderColor: activeKid === k.id ? k.color : "transparent",
                background: activeKid === k.id ? k.light : "#f5f7fa",
              }}
              onClick={() => setActiveKid(k.id)}
            >
              {k.emoji}

                {k.name}

              {k.grade}

                <div
                  className="kid-mini-fill"
                  style={{
                    width: `${kPct}%`,
                    background: k.color,
                  }}
                />

                {STATUSES.map((s) => {
                  const cnt = kTasks.filter((t) => t.status === s.id).length;
                  return cnt > 0 ? (

                      {cnt}

                  ) : null;
                })}

            </button>
          );
        })}

      {/* Weekly Calendar */}

📅 This Week

          {weekDates.map((d, i) => {
            const isToday = d.toDateString() === today.toDateString();
            const dayTaskCount = kidTasks.filter(
              (t) => new Date(t.due + "T00:00:00").toDateString() === d.toDateString()
            ).length;
            const doneCount = kidTasks.filter(
              (t) =>
                new Date(t.due + "T00:00:00").toDateString() === d.toDateString() &&
                t.status === "completed"
            ).length;
            return (
              <button
                key={i}
                className={`day-btn ${activeDay === i ? "active" : ""} ${isToday ? "today" : ""}`}
                style={{
                  borderColor:
                    activeDay === i
                      ? kid.color
                      : isToday
                      ? kid.color + "66"
                      : "#e5e8f0",
                  background:
                    activeDay === i ? kid.color : isToday ? kid.light : "white",
                }}
                onClick={() => setActiveDay(i)}
              >

                  {DAYS[i]}

                  {d.getDate()}

                {dayTaskCount > 0 && (

                    {doneCount}/{dayTaskCount}

                )}
              </button>
            );
          })}

        {dayTasks.length > 0 && (
          <div
            className="day-summary"
            style={{ background: kid.light, borderLeft: `3px solid ${kid.color}` }}
          >

              Due{" "}
              {weekDates[activeDay]?.toLocaleDateString("en-US", {
                weekday: "short",
                month: "short",
                day: "numeric",
              })}
              :

              {dayTasks.map((t) => {
                const st = STATUSES.find((s) => s.id === t.status);
                return (

                    {SUBJECT_ICONS[t.subject] || "📚"} {t.title.length > 28 ? t.title.slice(0, 28) + "…" : t.title}

                );
              })}

        )}

      {/* Stats */}

        {STATUSES.map((s) => (
          <div
            key={s.id}
            className="stat-card"
            style={{ background: s.bg, borderTop: `3px solid ${s.dot}` }}
          >

              {stats[s.id]}

              {s.label}

        ))}

      {/* Tabs + Add button */}

        {["homework", "project"].map((tab) => (
          <button
            key={tab}
            className={`tab-btn ${activeTab === tab ? "active" : ""}`}
            style={{
              background: activeTab === tab ? kid.color : "#f0f2f5",
              color: activeTab === tab ? "white" : "#666",
              boxShadow: activeTab === tab ? `0 4px 14px ${kid.color}44` : "none",
            }}
            onClick={() => setActiveTab(tab)}
          >
            {tab === "homework" ? "📝 Homework" : "🎨 Projects"}

              {kidTasks.filter((t) => t.type === tab).length}

          </button>
        ))}
        <button
          className="add-btn"
          style={{
            background: kid.color,
            boxShadow: `0 4px 14px ${kid.color}66`,
          }}
          onClick={openForm}
        >
          +
          Add
        </button>

      {/* Add Form */}
      {showForm && (

              ➕ New {form.type === "homework" ? "Homework" : "Project"} for {kid.name} {kid.emoji}

            <button className="form-close" onClick={() => setShowForm(false)}>
              ✕
            </button>

              Subject
              <select
                value={form.subject}
                onChange={(e) => setForm((f) => ({ ...f, subject: e.target.value }))}
                style={{ borderColor: form.subject ? kid.color : "#ddd" }}
              >
                <option value="">Select subject…</option>
                {SUBJECTS[activeKid].map((s) => (
                  <option key={s}>
                    {SUBJECT_ICONS[s]} {s}
                  </option>
                ))}
              </select>

              Status
              <select
                value={form.status}
                onChange={(e) => setForm((f) => ({ ...f, status: e.target.value }))}
                style={{ borderColor: kid.color }}
              >
                {STATUSES.map((s) => (
                  <option key={s.id} value={s.id}>
                    {s.label}
                  </option>
                ))}
              </select>

              Assignment description
              <input
                placeholder="e.g. Read chapter 3 and answer questions…"
                value={form.title}
                onChange={(e) => setForm((f) => ({ ...f, title: e.target.value }))}
                style={{ borderColor: form.title ? kid.color : "#ddd" }}
              />

              Due Date
              <input
                type="date"
                value={form.due}
                onChange={(e) => setForm((f) => ({ ...f, due: e.target.value }))}
                style={{ borderColor: form.due ? kid.color : "#ddd" }}
              />

              Source
              <select
                value={form.source}
                onChange={(e) => setForm((f) => ({ ...f, source: e.target.value }))}
                style={{ borderColor: kid.color }}
              >
                {SOURCES.map((s) => (
                  <option key={s}>{s}</option>
                ))}
              </select>

              Type

                {["homework", "project"].map((t) => (
                  <button
                    key={t}
                    className={`type-opt ${form.type === t ? "selected" : ""}`}
                    style={{
                      background: form.type === t ? kid.color : "transparent",
                      color: form.type === t ? "white" : "#666",
                      borderColor: form.type === t ? kid.color : "#ddd",
                    }}
                    onClick={() => setForm((f) => ({ ...f, type: t }))}
                    type="button"
                  >
                    {t === "homework" ? "📝 Homework" : "🎨 Project"}
                  </button>
                ))}

            <button
              className="save-btn"
              style={{
                background:
                  form.title && form.subject && form.due ? kid.color : "#ccc",
                boxShadow:
                  form.title && form.subject && form.due
                    ? `0 4px 14px ${kid.color}55`
                    : "none",
              }}
              onClick={handleAddTask}
              disabled={!form.title || !form.subject || !form.due}
            >
              Save Assignment ✓
            </button>
            <button className="cancel-btn" onClick={() => setShowForm(false)}>
              Cancel
            </button>

      )}

      {/* Task List */}

        {filtered.length === 0 ? (

              {activeTab === "homework" ? "🎉" : "🌟"}

              No {activeTab}s yet!

Tap + Add to add one

            <button
              className="empty-add-btn"
              style={{ background: kid.color, boxShadow: `0 4px 14px ${kid.color}55` }}
              onClick={openForm}
            >
              + Add {activeTab === "homework" ? "Homework" : "Project"}
            </button>

        ) : (
          filtered.map((task) => {
            const st = STATUSES.find((s) => s.id === task.status);
            const dueDate = new Date(task.due + "T00:00:00");
            const isOverdue =
              dueDate < today && task.status !== "completed";
            const isDueToday = dueDate.toDateString() === today.toDateString();
            return (
              <div
                key={task.id}
                className={`task-card ${isOverdue ? "overdue" : ""} ${task.status === "completed" ? "done" : ""}`}
                style={{
                  borderLeft: `4px solid ${isOverdue ? "#E24B4A" : task.status === "completed" ? "#639922" : kid.color}`,
                }}
              >

                  {SUBJECT_ICONS[task.subject] || "📚"}

                    {task.title}

                      {task.subject}

                      {st.label}

                      {isOverdue ? "⚠ " : isDueToday ? "🔔 " : "📅 "}
                      {isOverdue
                        ? "Overdue · "
                        : isDueToday
                        ? "Today · "
                        : ""}
                      {dueDate.toLocaleDateString("en-US", {
                        month: "short",
                        day: "numeric",
                      })}

                    via {task.source}

                  <select
                    value={task.status}
                    style={{ borderColor: kid.color + "88", color: kid.dark }}
                    onChange={(e) =>
                      updateStatus(activeKid, task.id, e.target.value)
                    }
                  >
                    {STATUSES.map((s) => (
                      <option key={s.id} value={s.id}>
                        {s.label}
                      </option>
                    ))}
                  </select>
                  <button
                    className="remove-btn"
                    onClick={() => removeTask(activeKid, task.id)}
                    title="Remove task"
                  >
                    ✕
                  </button>

            );
          })
        )}

        ASCS Homework Tracker
        •
        Made with ❤ for Abdulla & Salama

  );
}


*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  -webkit-tap-highlight-color: transparent;
}

body {
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  background: #f0f2f7;
  min-height: 100vh;
  -webkit-font-smoothing: antialiased;
}

.app {
  max-width: 860px;
  margin: 0 auto;
  padding: 14px 14px 32px;
}

/* ─── Header ─── */
.header {
  border-radius: 20px;
  padding: 18px 20px 16px;
  color: white;
  margin-bottom: 16px;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.18);
}

.header-top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 14px;
}

.header-logo {
  display: flex;
  align-items: center;
  gap: 12px;
}

.logo-box {
  width: 50px;
  height: 50px;
  background: rgba(255, 255, 255, 0.2);
  backdrop-filter: blur(6px);
  border-radius: 14px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  font-weight: 900;
  letter-spacing: -0.5px;
  flex-shrink: 0;
  border: 1.5px solid rgba(255, 255, 255, 0.3);
}

.school-name {
  font-size: 14px;
  font-weight: 700;
  line-height: 1.3;
}

.app-subtitle {
  font-size: 12px;
  opacity: 0.85;
  margin-top: 2px;
}

.header-date {
  font-size: 11px;
  opacity: 0.75;
  white-space: nowrap;
  padding-top: 4px;
}

.header-progress {
  background: rgba(255, 255, 255, 0.15);
  border-radius: 10px;
  padding: 10px 12px;
}

.progress-label {
  display: flex;
  justify-content: space-between;
  font-size: 11px;
  font-weight: 600;
  opacity: 0.9;
  margin-bottom: 6px;
}

.progress-pct {
  font-weight: 800;
}

.progress-track {
  height: 7px;
  background: rgba(255, 255, 255, 0.25);
  border-radius: 99px;
  overflow: hidden;
}

.progress-fill {
  height: 100%;
  background: rgba(255, 255, 255, 0.9);
  border-radius: 99px;
  transition: width 0.5s cubic-bezier(0.4, 0, 0.2, 1);
  min-width: 4px;
}

/* ─── Kid Switcher ─── */
.kid-switcher {
  display: flex;
  gap: 12px;
  margin-bottom: 16px;
}

.kid-btn {
  flex: 1;
  padding: 14px 10px 12px;
  border-radius: 18px;
  border: 2px solid transparent;
  cursor: pointer;
  text-align: center;
  transition: all 0.22s cubic-bezier(0.4, 0, 0.2, 1);
  background: white;
}

.kid-btn.active {
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.12);
  transform: translateY(-1px);
}

.kid-emoji {
  display: block;
  font-size: 32px;
  margin-bottom: 5px;
  line-height: 1;
}

.kid-name {
  display: block;
  font-size: 16px;
  font-weight: 800;
  letter-spacing: -0.3px;
}

.kid-grade {
  display: block;
  font-size: 11px;
  color: #888;
  margin-bottom: 8px;
}

.kid-mini-progress {
  height: 4px;
  background: #e8e8e8;
  border-radius: 99px;
  overflow: hidden;
  margin-bottom: 8px;
  width: 70%;
  margin-left: auto;
  margin-right: auto;
}

.kid-mini-fill {
  height: 100%;
  border-radius: 99px;
  transition: width 0.5s ease;
  min-width: 3px;
}

.kid-badges {
  display: flex;
  justify-content: center;
  gap: 4px;
  flex-wrap: wrap;
}

/* ─── Calendar ─── */
.calendar-section {
  margin-bottom: 16px;
}

.section-label {
  font-size: 12px;
  font-weight: 700;
  color: #888;
  text-transform: uppercase;
  letter-spacing: 0.6px;
  margin-bottom: 8px;
}

.calendar-row {
  display: flex;
  gap: 6px;
}

.day-btn {
  flex: 1;
  padding: 9px 4px 7px;
  border-radius: 14px;
  border: 2px solid;
  cursor: pointer;
  text-align: center;
  background: white;
  transition: all 0.2s ease;
  min-width: 0;
}

.day-btn.active {
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
  transform: translateY(-1px);
}

.day-name {
  display: block;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.3px;
  text-transform: uppercase;
  margin-bottom: 3px;
}

.day-num {
  display: block;
  font-size: 18px;
  font-weight: 800;
  line-height: 1;
  margin-bottom: 4px;
}

.day-count {
  display: inline-block;
  font-size: 9px;
  font-weight: 700;
  padding: 2px 5px;
  border-radius: 99px;
}

.day-summary {
  margin-top: 10px;
  padding: 10px 14px;
  border-radius: 12px;
  background: white;
  border: 1px solid #eee;
}

.day-summary-label {
  display: block;
  font-size: 11px;
  font-weight: 700;
  margin-bottom: 6px;
}

.day-summary-tasks {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
}

.day-task-chip {
  font-size: 11px;
  padding: 3px 9px;
  border-radius: 20px;
  font-weight: 600;
}

/* ─── Stats ─── */
.stats-row {
  display: flex;
  gap: 10px;
  margin-bottom: 16px;
}

.stat-card {
  flex: 1;
  padding: 12px 8px;
  border-radius: 14px;
  text-align: center;
  background: white;
  border-top: 3px solid;
  position: relative;
  overflow: hidden;
}

.stat-dot {
  display: block;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  margin: 0 auto 4px;
}

.stat-num {
  display: block;
  font-size: 28px;
  font-weight: 800;
  line-height: 1;
  margin-bottom: 3px;
}

.stat-label {
  display: block;
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.4px;
}

/* ─── Tabs + Add ─── */
.tab-row {
  display: flex;
  gap: 8px;
  align-items: center;
  margin-bottom: 14px;
}

.tab-btn {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 10px 16px;
  border-radius: 22px;
  border: none;
  cursor: pointer;
  font-weight: 700;
  font-size: 13px;
  transition: all 0.2s ease;
}

.tab-count {
  display: inline-block;
  font-size: 11px;
  font-weight: 800;
  padding: 2px 7px;
  border-radius: 99px;
}

.add-btn {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 10px 18px;
  border-radius: 22px;
  border: none;
  cursor: pointer;
  font-weight: 800;
  font-size: 14px;
  color: white;
  transition: all 0.2s ease;
}

.add-btn:active {
  transform: scale(0.96);
}

.add-icon {
  font-size: 18px;
  line-height: 1;
  margin-top: -1px;
}

.add-label {
  font-size: 13px;
}

/* ─── Form ─── */
.form-card {
  background: white;
  border: 1.5px solid;
  border-radius: 18px;
  padding: 18px;
  margin-bottom: 16px;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.08);
}

.form-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 14px;
}

.form-title {
  font-size: 14px;
  font-weight: 800;
}

.form-close {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 1.5px solid #eee;
  background: #f5f5f5;
  cursor: pointer;
  font-size: 12px;
  color: #888;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.form-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}

.form-field {
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.form-field.full-span {
  grid-column: 1 / -1;
}

.form-label {
  font-size: 11px;
  font-weight: 700;
  color: #777;
  text-transform: uppercase;
  letter-spacing: 0.4px;
}

.form-field select,
.form-field input {
  padding: 10px 12px;
  border-radius: 10px;
  border: 1.5px solid #ddd;
  font-size: 13px;
  width: 100%;
  background: white;
  transition: border-color 0.2s;
  outline: none;
  color: #222;
  -webkit-appearance: none;
  appearance: none;
}

.form-field select:focus,
.form-field input:focus {
  border-color: #888;
}

.type-toggle {
  display: flex;
  gap: 8px;
}

.type-opt {
  flex: 1;
  padding: 10px;
  border-radius: 10px;
  border: 1.5px solid;
  cursor: pointer;
  font-size: 13px;
  font-weight: 600;
  transition: all 0.2s ease;
  text-align: center;
}

.form-actions {
  display: flex;
  gap: 8px;
  margin-top: 14px;
}

.save-btn {
  flex: 1;
  padding: 12px;
  border-radius: 12px;
  border: none;
  color: white;
  font-weight: 800;
  cursor: pointer;
  font-size: 14px;
  transition: all 0.2s ease;
}

.save-btn:disabled {
  cursor: not-allowed;
  opacity: 0.7;
}

.cancel-btn {
  padding: 12px 20px;
  border-radius: 12px;
  border: 1.5px solid #e0e0e0;
  background: white;
  cursor: pointer;
  font-size: 14px;
  font-weight: 600;
  color: #666;
}

/* ─── Task List ─── */
.task-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.task-card {
  background: white;
  border-radius: 16px;
  border: 1.5px solid #eaecf0;
  border-left: 4px solid;
  padding: 13px 14px;
  display: flex;
  align-items: flex-start;
  gap: 12px;
  transition: all 0.2s ease;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.04);
}

.task-card:active {
  transform: scale(0.99);
}

.task-card.overdue {
  background: #fff8f8;
  border-color: #F09595;
}

.task-card.done {
  opacity: 0.7;
}

.task-icon {
  width: 44px;
  height: 44px;
  border-radius: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 22px;
  flex-shrink: 0;
}

.task-body {
  flex: 1;
  min-width: 0;
}

.task-title {
  font-weight: 700;
  font-size: 14px;
  color: #1a1a1a;
  margin-bottom: 6px;
  line-height: 1.35;
  transition: color 0.2s;
}

.task-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  align-items: center;
}

.badge {
  font-size: 10px;
  padding: 3px 8px;
  border-radius: 20px;
  font-weight: 700;
  display: inline-flex;
  align-items: center;
  gap: 4px;
}

.badge-dot {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  flex-shrink: 0;
}

.task-due {
  font-size: 11px;
  font-weight: 500;
}

.task-source {
  font-size: 10px;
  color: #bbb;
  font-weight: 500;
}

.task-actions {
  display: flex;
  flex-direction: column;
  gap: 5px;
  flex-shrink: 0;
  align-items: flex-end;
}

.task-actions select {
  font-size: 11px;
  padding: 6px 7px;
  border-radius: 9px;
  border: 1.5px solid;
  background: white;
  cursor: pointer;
  outline: none;
  color: inherit;
  max-width: 110px;
  -webkit-appearance: none;
  appearance: none;
}

.remove-btn {
  font-size: 10px;
  padding: 5px 9px;
  border-radius: 8px;
  border: 1px solid #eee;
  background: white;
  color: #E24B4A;
  cursor: pointer;
  font-weight: 700;
  transition: all 0.15s;
}

.remove-btn:hover {
  background: #fff0f0;
  border-color: #E24B4A;
}

/* ─── Empty State ─── */
.empty-state {
  text-align: center;
  padding: 36px 20px;
  border-radius: 18px;
  border: 2px dashed;
}

.empty-emoji {
  font-size: 44px;
  margin-bottom: 10px;
  display: block;
}

.empty-title {
  font-size: 18px;
  font-weight: 800;
  margin-bottom: 4px;
}

.empty-sub {
  font-size: 13px;
  color: #aaa;
  margin-bottom: 16px;
}

.empty-add-btn {
  display: inline-block;
  padding: 11px 24px;
  border-radius: 22px;
  border: none;
  color: white;
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
  transition: all 0.2s ease;
}

.empty-add-btn:active {
  transform: scale(0.97);
}

/* ─── Footer ─── */
.footer {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin-top: 28px;
  padding: 12px;
  font-size: 12px;
  color: #ccc;
}

.footer-dot {
  opacity: 0.5;
}

/* ─── Responsive ─── */
@media (max-width: 520px) {
  .app {
    padding: 10px 10px 28px;
  }

  .header {
    padding: 15px 16px 14px;
    border-radius: 16px;
  }

  .school-name {
    font-size: 12px;
  }

  .logo-box {
    width: 44px;
    height: 44px;
    font-size: 12px;
    border-radius: 12px;
  }

  .kid-switcher {
    gap: 8px;
  }

  .kid-btn {
    padding: 12px 8px 10px;
    border-radius: 14px;
  }

  .kid-emoji {
    font-size: 28px;
  }

  .kid-name {
    font-size: 14px;
  }

  .calendar-row {
    gap: 5px;
  }

  .day-btn {
    border-radius: 12px;
    padding: 8px 2px 6px;
  }

  .day-num {
    font-size: 16px;
  }

  .form-grid {
    grid-template-columns: 1fr;
  }

  .form-field.full-span {
    grid-column: 1;
  }

  .type-toggle {
    flex-direction: row;
  }

  .stats-row {
    gap: 7px;
  }

  .stat-num {
    font-size: 24px;
  }

  .task-card {
    padding: 11px 12px;
    gap: 10px;
  }

  .task-icon {
    width: 38px;
    height: 38px;
    font-size: 19px;
    border-radius: 10px;
  }

  .task-title {
    font-size: 13px;
  }

  .tab-btn {
    padding: 9px 12px;
    font-size: 12px;
  }

  .add-btn {
    padding: 9px 14px;
  }

  .task-actions select {
    max-width: 95px;
    font-size: 10px;
  }
}

@media (max-width: 380px) {
  .header-date {
    display: none;
  }

  .school-name {
    font-size: 11px;
  }
}


File created successfully at: /Users/khalidbinkalban/ascs-homework-tracker/src/App.css

*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  -webkit-tap-highlight-color: transparent;
}

body {
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  background: #f0f2f7;
  min-height: 100vh;
  -webkit-font-smoothing: antialiased;
}

.app {
  max-width: 860px;
  margin: 0 auto;
  padding: 14px 14px 32px;
}

/* ─── Header ─── */
.header {
  border-radius: 20px;
  padding: 18px 20px 16px;
  color: white;
  margin-bottom: 16px;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.18);
}

.header-top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 14px;
}

.header-logo {
  display: flex;
  align-items: center;
  gap: 12px;
}

.logo-box {
  width: 50px;
  height: 50px;
  background: rgba(255, 255, 255, 0.2);
  backdrop-filter: blur(6px);
  border-radius: 14px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  font-weight: 900;
  letter-spacing: -0.5px;
  flex-shrink: 0;
  border: 1.5px solid rgba(255, 255, 255, 0.3);
}

.school-name {
  font-size: 14px;
  font-weight: 700;
  line-height: 1.3;
}

.app-subtitle {
  font-size: 12px;
  opacity: 0.85;
  margin-top: 2px;
}

.header-date {
  font-size: 11px;
  opacity: 0.75;
  white-space: nowrap;
  padding-top: 4px;
}

.header-progress {
  background: rgba(255, 255, 255, 0.15);
  border-radius: 10px;
  padding: 10px 12px;
}

.progress-label {
  display: flex;
  justify-content: space-between;
  font-size: 11px;
  font-weight: 600;
  opacity: 0.9;
  margin-bottom: 6px;
}

.progress-pct {
  font-weight: 800;
}

.progress-track {
  height: 7px;
  background: rgba(255, 255, 255, 0.25);
  border-radius: 99px;
  overflow: hidden;
}

.progress-fill {
  height: 100%;
  background: rgba(255, 255, 255, 0.9);
  border-radius: 99px;
  transition: width 0.5s cubic-bezier(0.4, 0, 0.2, 1);
  min-width: 4px;
}

/* ─── Kid Switcher ─── */
.kid-switcher {
  display: flex;
  gap: 12px;
  margin-bottom: 16px;
}

.kid-btn {
  flex: 1;
  padding: 14px 10px 12px;
  border-radius: 18px;
  border: 2px solid transparent;
  cursor: pointer;
  text-align: center;
  transition: all 0.22s cubic-bezier(0.4, 0, 0.2, 1);
  background: white;
}

.kid-btn.active {
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.12);
  transform: translateY(-1px);
}

.kid-emoji {
  display: block;
  font-size: 32px;
  margin-bottom: 5px;
  line-height: 1;
}

.kid-name {
  display: block;
  font-size: 16px;
  font-weight: 800;
  letter-spacing: -0.3px;
}

.kid-grade {
  display: block;
  font-size: 11px;
  color: #888;
  margin-bottom: 8px;
}

.kid-mini-progress {
  height: 4px;
  background: #e8e8e8;
  border-radius: 99px;
  overflow: hidden;
  margin-bottom: 8px;
  width: 70%;
  margin-left: auto;
  margin-right: auto;
}

.kid-mini-fill {
  height: 100%;
  border-radius: 99px;
  transition: width 0.5s ease;
  min-width: 3px;
}

.kid-badges {
  display: flex;
  justify-content: center;
  gap: 4px;
  flex-wrap: wrap;
}

/* ─── Calendar ─── */
.calendar-section {
  margin-bottom: 16px;
}

.section-label {
  font-size: 12px;
  font-weight: 700;
  color: #888;
  text-transform: uppercase;
  letter-spacing: 0.6px;
  margin-bottom: 8px;
}

.calendar-row {
  display: flex;
  gap: 6px;
}

.day-btn {
  flex: 1;
  padding: 9px 4px 7px;
  border-radius: 14px;
  border: 2px solid;
  cursor: pointer;
  text-align: center;
  background: white;
  transition: all 0.2s ease;
  min-width: 0;
}

.day-btn.active {
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
  transform: translateY(-1px);
}

.day-name {
  display: block;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.3px;
  text-transform: uppercase;
  margin-bottom: 3px;
}

.day-num {
  display: block;
  font-size: 18px;
  font-weight: 800;
  line-height: 1;
  margin-bottom: 4px;
}

.day-count {
  display: inline-block;
  font-size: 9px;
  font-weight: 700;
  padding: 2px 5px;
  border-radius: 99px;
}

.day-summary {
  margin-top: 10px;
  padding: 10px 14px;
  border-radius: 12px;
  background: white;
  border: 1px solid #eee;
}

.day-summary-label {
  display: block;
  font-size: 11px;
  font-weight: 700;
  margin-bottom: 6px;
}

.day-summary-tasks {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
}

.day-task-chip {
  font-size: 11px;
  padding: 3px 9px;
  border-radius: 20px;
  font-weight: 600;
}

/* ─── Stats ─── */
.stats-row {
  display: flex;
  gap: 10px;
  margin-bottom: 16px;
}

.stat-card {
  flex: 1;
  padding: 12px 8px;
  border-radius: 14px;
  text-align: center;
  background: white;
  border-top: 3px solid;
  position: relative;
  overflow: hidden;
}

.stat-dot {
  display: block;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  margin: 0 auto 4px;
}

.stat-num {
  display: block;
  font-size: 28px;
  font-weight: 800;
  line-height: 1;
  margin-bottom: 3px;
}

.stat-label {
  display: block;
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.4px;
}

/* ─── Tabs + Add ─── */
.tab-row {
  display: flex;
  gap: 8px;
  align-items: center;
  margin-bottom: 14px;
}

.tab-btn {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 10px 16px;
  border-radius: 22px;
  border: none;
  cursor: pointer;
  font-weight: 700;
  font-size: 13px;
  transition: all 0.2s ease;
}

.tab-count {
  display: inline-block;
  font-size: 11px;
  font-weight: 800;
  padding: 2px 7px;
  border-radius: 99px;
}

.add-btn {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 10px 18px;
  border-radius: 22px;
  border: none;
  cursor: pointer;
  font-weight: 800;
  font-size: 14px;
  color: white;
  transition: all 0.2s ease;
}

.add-btn:active {
  transform: scale(0.96);
}

.add-icon {
  font-size: 18px;
  line-height: 1;
  margin-top: -1px;
}

.add-label {
  font-size: 13px;
}

/* ─── Form ─── */
.form-card {
  background: white;
  border: 1.5px solid;
  border-radius: 18px;
  padding: 18px;
  margin-bottom: 16px;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.08);
}

.form-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 14px;
}

.form-title {
  font-size: 14px;
  font-weight: 800;
}

.form-close {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 1.5px solid #eee;
  background: #f5f5f5;
  cursor: pointer;
  font-size: 12px;
  color: #888;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.form-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}

.form-field {
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.form-field.full-span {
  grid-column: 1 / -1;
}

.form-label {
  font-size: 11px;
  font-weight: 700;
  color: #777;
  text-transform: uppercase;
  letter-spacing: 0.4px;
}

.form-field select,
.form-field input {
  padding: 10px 12px;
  border-radius: 10px;
  border: 1.5px solid #ddd;
  font-size: 13px;
  width: 100%;
  background: white;
  transition: border-color 0.2s;
  outline: none;
  color: #222;
  -webkit-appearance: none;
  appearance: none;
}

.form-field select:focus,
.form-field input:focus {
  border-color: #888;
}

.type-toggle {
  display: flex;
  gap: 8px;
}

.type-opt {
  flex: 1;
  padding: 10px;
  border-radius: 10px;
  border: 1.5px solid;
  cursor: pointer;
  font-size: 13px;
  font-weight: 600;
  transition: all 0.2s ease;
  text-align: center;
}

.form-actions {
  display: flex;
  gap: 8px;
  margin-top: 14px;
}

.save-btn {
  flex: 1;
  padding: 12px;
  border-radius: 12px;
  border: none;
  color: white;
  font-weight: 800;
  cursor: pointer;
  font-size: 14px;
  transition: all 0.2s ease;
}

.save-btn:disabled {
  cursor: not-allowed;
  opacity: 0.7;
}

.cancel-btn {
  padding: 12px 20px;
  border-radius: 12px;
  border: 1.5px solid #e0e0e0;
  background: white;
  cursor: pointer;
  font-size: 14px;
  font-weight: 600;
  color: #666;
}

/* ─── Task List ─── */
.task-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.task-card {
  background: white;
  border-radius: 16px;
  border: 1.5px solid #eaecf0;
  border-left: 4px solid;
  padding: 13px 14px;
  display: flex;
  align-items: flex-start;
  gap: 12px;
  transition: all 0.2s ease;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.04);
}

.task-card:active {
  transform: scale(0.99);
}

.task-card.overdue {
  background: #fff8f8;
  border-color: #F09595;
}

.task-card.done {
  opacity: 0.7;
}

.task-icon {
  width: 44px;
  height: 44px;
  border-radius: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 22px;
  flex-shrink: 0;
}

.task-body {
  flex: 1;
  min-width: 0;
}

.task-title {
  font-weight: 700;
  font-size: 14px;
  color: #1a1a1a;
  margin-bottom: 6px;
  line-height: 1.35;
  transition: color 0.2s;
}

.task-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  align-items: center;
}

.badge {
  font-size: 10px;
  padding: 3px 8px;
  border-radius: 20px;
  font-weight: 700;
  display: inline-flex;
  align-items: center;
  gap: 4px;
}

.badge-dot {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  flex-shrink: 0;
}

.task-due {
  font-size: 11px;
  font-weight: 500;
}

.task-source {
  font-size: 10px;
  color: #bbb;
  font-weight: 500;
}

.task-actions {
  display: flex;
  flex-direction: column;
  gap: 5px;
  flex-shrink: 0;
  align-items: flex-end;
}

.task-actions select {
  font-size: 11px;
  padding: 6px 7px;
  border-radius: 9px;
  border: 1.5px solid;
  background: white;
  cursor: pointer;
  outline: none;
  color: inherit;
  max-width: 110px;
  -webkit-appearance: none;
  appearance: none;
}

.remove-btn {
  font-size: 10px;
  padding: 5px 9px;
  border-radius: 8px;
  border: 1px solid #eee;
  background: white;
  color: #E24B4A;
  cursor: pointer;
  font-weight: 700;
  transition: all 0.15s;
}

.remove-btn:hover {
  background: #fff0f0;
  border-color: #E24B4A;
}

/* ─── Empty State ─── */
.empty-state {
  text-align: center;
  padding: 36px 20px;
  border-radius: 18px;
  border: 2px dashed;
}

.empty-emoji {
  font-size: 44px;
  margin-bottom: 10px;
  display: block;
}

.empty-title {
  font-size: 18px;
  font-weight: 800;
  margin-bottom: 4px;
}

.empty-sub {
  font-size: 13px;
  color: #aaa;
  margin-bottom: 16px;
}

.empty-add-btn {
  display: inline-block;
  padding: 11px 24px;
  border-radius: 22px;
  border: none;
  color: white;
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
  transition: all 0.2s ease;
}

.empty-add-btn:active {
  transform: scale(0.97);
}

/* ─── Footer ─── */
.footer {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin-top: 28px;
  padding: 12px;
  font-size: 12px;
  color: #ccc;
}

.footer-dot {
  opacity: 0.5;
}

/* ─── Responsive ─── */
@media (max-width: 520px) {
  .app {
    padding: 10px 10px 28px;
  }

  .header {
    padding: 15px 16px 14px;
    border-radius: 16px;
  }

  .school-name {
    font-size: 12px;
  }

  .logo-box {
    width: 44px;
    height: 44px;
    font-size: 12px;
    border-radius: 12px;
  }

  .kid-switcher {
    gap: 8px;
  }

  .kid-btn {
    padding: 12px 8px 10px;
    border-radius: 14px;
  }

  .kid-emoji {
    font-size: 28px;
  }

  .kid-name {
    font-size: 14px;
  }

  .calendar-row {
    gap: 5px;
  }

  .day-btn {
    border-radius: 12px;
    padding: 8px 2px 6px;
  }

  .day-num {
    font-size: 16px;
  }

  .form-grid {
    grid-template-columns: 1fr;
  }

  .form-field.full-span {
    grid-column: 1;
  }

  .type-toggle {
    flex-direction: row;
  }

  .stats-row {
    gap: 7px;
  }

  .stat-num {
    font-size: 24px;
  }

  .task-card {
    padding: 11px 12px;
    gap: 10px;
  }

  .task-icon {
    width: 38px;
    height: 38px;
    font-size: 19px;
    border-radius: 10px;
  }

  .task-title {
    font-size: 13px;
  }

  .tab-btn {
    padding: 9px 12px;
    font-size: 12px;
  }

  .add-btn {
    padding: 9px 14px;
  }

  .task-actions select {
    max-width: 95px;
    font-size: 10px;
  }
}

@media (max-width: 380px) {
  .header-date {
    display: none;
  }

  .school-name {
    font-size: 11px;
  }
}


Now update the `useTasks` hook to expose `updateTask` (used in App.jsx):


1	import { useState, useEffect } from "react";
2	import { SAMPLE_TASKS } from "../data/constants";
3
4	function getWeekDates() {
5	  const today = new Date();
6	  const day = today.getDay();
7	  const monday = new Date(today);
8	  monday.setDate(today.getDate() - ((day + 6) % 7));
9	  return Array.from({ length: 5 }, (_, i) => {
10	    const d = new Date(monday);
11	    d.setDate(monday.getDate() + i);
12	    return d;
13	  });
14	}
15
16	function seedTasks() {
17	  const week = getWeekDates();
18	  return {
19	    abdulla: SAMPLE_TASKS.abdulla.map((t, i) => ({
20	      ...t,
21	      due: week[i + 1]?.toISOString().split("T")[0] || week[2].toISOString().split("T")[0],
22	    })),
23	    salama: SAMPLE_TASKS.salama.map((t, i) => ({
24	      ...t,
25	      due: week[i]?.toISOString().split("T")[0] || week[0].toISOString().split("T")[0],
26	    })),
27	  };
28	}
29
30	export function useTasks() {
31	  const [tasks, setTasks] = useState(() => {
32	    try {
33	      const saved = localStorage.getItem("ascs_tasks");
34	      return saved ? JSON.parse(saved) : seedTasks();
35	    } catch {
36	      return seedTasks();
37	    }
38	  });
39
40	  useEffect(() => {
41	    localStorage.setItem("ascs_tasks", JSON.stringify(tasks));
42	  }, [tasks]);
43
44	  function addTask(kidId, task) {
45	    setTasks((prev) => ({
46	      ...prev,
47	      [kidId]: [...prev[kidId], { ...task, id: Date.now() }],
48	    }));
49	  }
50
51	  function updateStatus(kidId, taskId, status) {
52	    setTasks((prev) => ({
53	      ...prev,
54	      [kidId]: prev[kidId].map((t) => (t.id === taskId ? { ...t, status } : t)),
55	    }));
56	  }
57
58	  function removeTask(kidId, taskId) {
59	    setTasks((prev) => ({
60	      ...prev,
61	      [kidId]: prev[kidId].filter((t) => t.id !== taskId),
62	    }));
63	  }
64
65	  return { tasks, addTask, updateStatus, removeTask };
66	}
67


Edit

  return { tasks, addTask, updateStatus, removeTask };
}

  function updateTask(kidId, taskId, changes) {
    setTasks((prev) => ({
      ...prev,
      [kidId]: prev[kidId].map((t) => (t.id === taskId ? { ...t, ...changes } : t)),
    }));
  }

  return { tasks, addTask, updateStatus, removeTask, updateTask };
}


The file /Users/khalidbinkalban/ascs-homework-tracker/src/hooks/useTasks.js has been updated successfully.

  function updateTask(kidId, taskId, changes) {
    setTasks((prev) => ({
      ...prev,
      [kidId]: prev[kidId].map((t) => (t.id === taskId ? { ...t, ...changes } : t)),
    }));
  }

  return { tasks, addTask, updateStatus, removeTask, updateTask };
}

import { useState, useEffect } from "react";
import { SAMPLE_TASKS } from "../data/constants";

function getWeekDates() {
  const today = new Date();
  const day = today.getDay();
  const monday = new Date(today);
  monday.setDate(today.getDate() - ((day + 6) % 7));
  return Array.from({ length: 5 }, (_, i) => {
    const d = new Date(monday);
    d.setDate(monday.getDate() + i);
    return d;
  });
}

function seedTasks() {
  const week = getWeekDates();
  return {
    abdulla: SAMPLE_TASKS.abdulla.map((t, i) => ({
      ...t,
      due: week[i + 1]?.toISOString().split("T")[0] || week[2].toISOString().split("T")[0],
    })),
    salama: SAMPLE_TASKS.salama.map((t, i) => ({
      ...t,
      due: week[i]?.toISOString().split("T")[0] || week[0].toISOString().split("T")[0],
    })),
  };
}

export function useTasks() {
  const [tasks, setTasks] = useState(() => {
    try {
      const saved = localStorage.getItem("ascs_tasks");
      return saved ? JSON.parse(saved) : seedTasks();
    } catch {
      return seedTasks();
    }
  });

  useEffect(() => {
    localStorage.setItem("ascs_tasks", JSON.stringify(tasks));
  }, [tasks]);

  function addTask(kidId, task) {
    setTasks((prev) => ({
      ...prev,
      [kidId]: [...prev[kidId], { ...task, id: Date.now() }],
    }));
  }

  function updateStatus(kidId, taskId, status) {
    setTasks((prev) => ({
      ...prev,
      [kidId]: prev[kidId].map((t) => (t.id === taskId ? { ...t, status } : t)),
    }));
  }

  function removeTask(kidId, taskId) {
    setTasks((prev) => ({
      ...prev,
      [kidId]: prev[kidId].filter((t) => t.id !== taskId),
    }));
  }

  return { tasks, addTask, updateStatus, removeTask };
}

-  return { tasks, addTask, updateStatus, removeTask };

+  function updateTask(kidId, taskId, changes) {

+      [kidId]: prev[kidId].map((t) => (t.id === taskId ? { ...t, ...changes } : t)),

+  return { tasks, addTask, updateStatus, removeTask, updateTask };


Now install dependencies and verify the build:


Bash

cd /Users/khalidbinkalban/ascs-homework-tracker && npm install 2>&1 | tail -5


To address all issues (including breaking changes), run:
  npm audit fix --force

Run `npm audit` for details.


> ascs-homework-tracker@1.0.0 build
> vite build

The CJS build of Vite's Node API is deprecated. See https://vite.dev/guide/troubleshooting.html#vite-cjs-node-api-deprecated for more details.
vite v5.4.21 building for production...
transforming...
✓ 33 modules transformed.
rendering chunks...
computing gzip size...
dist/index.html                   0.59 kB │ gzip:  0.40 kB
dist/assets/index-a5T-5Ajy.css    9.20 kB │ gzip:  2.36 kB
dist/assets/index-DR_5Xdd8.js   156.23 kB │ gzip: 49.88 kB
✓ built in 254ms


Build passes clean. Let me verify the full file tree:


find /Users/khalidbinkalban/ascs-homework-tracker/src -type f | sort


Everything is set up and builds successfully. Here's what was created:

**File structure:**
```
ascs-homework-tracker/
├── index.html
├── package.json
├── vite.config.js
└── src/
    ├── App.jsx
    ├── App.css
    ├── main.jsx
    ├── data/constants.js
    └── hooks/useTasks.js
```

**UI/UX enhancements over the base design:**

- **Progress bar** in the header showing each kid's overall completion %
- **Mini progress bar** on each kid card in the switcher
- **Day calendar** shows `done/total` counts instead of just a dot — at a glance you know `1/2` done for that day
- **Day summary** expands into pill chips with status color-coded, not just plain text
- **Task cards** have a colored left border (green = done, red = overdue, kid color = normal) and strikethrough on completed titles
- **Due date labels** are contextual: "🔔 Today", "⚠ Overdue", or "📅 date"
- **Stat cards** have a colored top border + dot indicator
- **Tabs** include task count badges
- **Form** has labeled fields, a segmented type toggle, and the Save button grays out until all required fields are filled
- **Empty state** has an inline "+ Add" button
- **Mobile-first** breakpoints at 520px and 380px, `-webkit-appearance: none` on selects, and tap highlights removed

To run it:
```
cd ascs-homework-tracker
npm run dev
```


share with me the link to open


npm run dev -- --host 2>&1 &
sleep 3
curl -s http://localhost:5173 | head -5


> ascs-homework-tracker@1.0.0 dev
> vite --host

The CJS build of Vite's Node API is deprecated. See https://vite.dev/guide/troubleshooting.html#vite-cjs-node-api-deprecated for more details.

  VITE v5.4.21  ready in 281 ms

  ➜  Local:   http://localhost:5173/
  ➜  Network: http://192.168.1.140:5173/
  ➜  Network: http://100.72.97.47:5173/
<!DOCTYPE html>
<html lang="en">
  <head>
    <script type="module">import { injectIntoGlobalHook } from "/@react-refresh";
injectIntoGlobalHook(window);


The dev server is running. Open it here:

**http://localhost:5173**

On your phone or other devices on the same Wi-Fi, use:
**http://192.168.1.140:5173**


- Make it SVG instead of emojies
- the source of homeworks dropdown to be Telegram and Edunation
- Make it live data and live date
- provide a url link to share it with my wife and start using the app


Agent

Plan SVG + Firebase + deploy changes

Prompt:
I'm about to update a React + Vite app at /Users/khalidbinkalban/ascs-homework-tracker with these changes:

1. Replace ALL emojis with SVG icons (using lucide-react which is already installed at ^0.383.0)
2. Change SOURCES constant to only ["Telegram", "Edunation"]
3. Add live clock (updates every second)
4. Add Firebase Realtime Database for real-time sync between devices
5. Deploy to Vercel for a shareable URL

Current files:
- src/data/constants.js — has KIDS (with emoji field), SUBJECTS, STATUSES, SOURCES, SUBJECT_ICONS (emoji map), DAYS, SAMPLE_TASKS
- src/hooks/useTasks.js — localStorage-based task management
- src/App.jsx — main component using emojis throughout
- src/App.css — styling
- src/main.jsx — entry point

I need to know:
1. Exact list of all files to create/modify
2. Which lucide-react icons to use for each subject (Math→Calculator, English→BookOpen, Arabic→PenLine, Science→Microscope, Art→Palette, PE→Trophy, Islamic Studies→Moon, Story Time→BookMarked, Phonics→BookOpen) — confirm these exist in lucide-react 0.383
3. Best approach for Firebase Realtime Database integration with a localStorage fallback when Firebase env vars aren't set
4. What FIREBASE_READY flag logic should look like
5. What CSS changes are needed for SVG icons vs emoji (kid avatar sizing, task icon sizing, inline SVG alignment)

Return a concise implementation plan with exact file list and any gotchas to watch for.