diff --git a/src/App.css b/src/App.css index 68f8799..cf67a79 100644 --- a/src/App.css +++ b/src/App.css @@ -61,23 +61,6 @@ color: #61dafb; } -.habit-card .font-bold { - transition: color 0.3s ease; -} - -.habit-card:hover .font-bold { - color: #21a1f1; -} - -.habit-card .text-sm { - color: #c0c0c0; - transition: color 0.3s ease; -} - -.habit-card:hover .text-sm { - color: #a0d8ff; -} - button { cursor: pointer; border: none; @@ -97,35 +80,6 @@ button:hover { box-shadow: 0 4px 12px rgba(59,130,246,0.7); } -button:active { - transform: scale(0.95); - box-shadow: 0 1px 4px rgba(59,130,246,0.9); -} - -.toggle-button { - background-color: #10b981; - box-shadow: 0 2px 6px rgba(16,185,129,0.5); - color: white; - padding: 0.5rem 1rem; - border-radius: 6px; - font-weight: 600; - cursor: pointer; - transition: background-color 0.3s ease, box-shadow 0.3s ease, transform 0.2s ease; - margin-bottom: 1rem; -} - -.toggle-button:hover { - background-color: #059669; - box-shadow: 0 4px 12px rgba(5,150,105,0.7); - transform: scale(1.05); -} - -.toggle-button:active { - background-color: #047857; - box-shadow: 0 1px 4px rgba(4,120,87,0.9); - transform: scale(0.95); -} - input[type="text"], select { background-color: #1e1e1e; border: 1px solid #444; @@ -141,146 +95,6 @@ input[type="text"]:focus, select:focus { box-shadow: 0 0 8px #61dafb; } -.badge { - display: inline-flex; - align-items: center; - gap: 0.3rem; - padding: 0.3rem 0.6rem; - border-radius: 9999px; - font-size: 0.75rem; - font-weight: 700; - user-select: none; - transition: background-color 0.3s ease, color 0.3s ease; -} - -.badge:hover { - background-color: #3b82f6; - color: white; - cursor: pointer; -} - -button { - cursor: pointer; - border: none; - outline: none; - font-weight: 600; - border-radius: 6px; - transition: background-color 0.3s ease; -} - -button:hover { - filter: brightness(1.1); -} - -input[type="text"], select { - background-color: #1e1e1e; - border: 1px solid #444; - color: #ddd; - padding: 0.5rem 0.75rem; - border-radius: 6px; - transition: border-color 0.3s ease; -} - -input[type="text"]:focus, select:focus { - border-color: #61dafb; - outline: none; -} - -.badge { - display: inline-flex; - align-items: center; - gap: 0.3rem; - padding: 0.3rem 0.6rem; - border-radius: 9999px; - font-size: 0.75rem; - font-weight: 700; - user-select: none; -} - -.bg-yellow-500 { - background-color: #facc15; -} - -.bg-blue-500 { - background-color: #3b82f6; -} - -.bg-green-500 { - background-color: #22c55e; -} - -.text-white { - color: white; -} - -.text-green-800 { - color: #166534; -} - -.text-gray-500 { - color: #6b7280; -} - -.text-gray-400 { - color: #9ca3af; -} - -.text-indigo-500 { - color: #6366f1; -} - -.text-gray-700 { - color: #374151; -} - -.rounded-full { - border-radius: 9999px; -} - -.cursor-pointer { - cursor: pointer; -} - -.min-h-11 { - min-height: 2.75rem; -} - -.min-w-11 { - min-width: 2.75rem; -} - -.bg-gray-100 { - background-color: #f3f4f6; -} - -.bg-gray-200 { - background-color: #e5e7eb; -} - -.bg-gray-500 { - background-color: #6b7280; -} - -.bg-red-500 { - background-color: #ef4444; -} - -.bg-red-600 { - background-color: #dc2626; -} - -.focus\:outline-none:focus { - outline: none; -} - -.focus\:ring-2:focus { - box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.5); -} - -.focus\:ring-red-400:focus { - box-shadow: 0 0 0 2px rgba(248, 113, 113, 0.5); -} - @keyframes App-logo-spin { from { transform: rotate(0deg); @@ -290,29 +104,51 @@ input[type="text"]:focus, select:focus { } } -/* --- Styles for Motivational Quote Component --- */ +/* --- Your Accessibility Styles --- */ +.App.large-text .App-header { + font-size: calc(12px + 2.4vmin); +} + +.App.high-contrast .App-header { + background-color: #000000; + color: #ffffff; +} + +.App.high-contrast .App-link { + color: #ffff00; /* Bright yellow for high contrast */ +} +.App.high-contrast input, +.App.high-contrast select, +.App.high-contrast button { + background-color: #222; + color: #fff; + border: 2px solid #fff; +} + +/* --- Styles for Motivational Quote Component (from other branch) --- */ .motivational-quote-container { width: 100%; - max-width: 600px; /* Adjust max-width as needed */ - margin: 0 auto 1.5rem auto; /* Centers the component and adds bottom margin */ + max-width: 600px; + margin: 0 auto 1.5rem auto; padding: 1.5rem; - background-color: #f8f9fa; /* A light, clean background */ + background-color: #f8f9fa; border: 1px solid #dee2e6; border-radius: 8px; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); text-align: center; + color: #343a40; /* Set a default text color for contrast */ } .quote-header { display: flex; align-items: center; justify-content: center; - gap: 0.5rem; /* Space between icon and title */ + gap: 0.5rem; } .quote-icon { - color: #f59e0b; /* A warm yellow for the lightbulb */ + color: #f59e0b; } .quote-title { @@ -330,10 +166,10 @@ input[type="text"]:focus, select:focus { } .quote-author { - display: block; /* Makes it take its own line */ - text-align: right; /* Aligns the author to the right */ + display: block; + text-align: right; font-size: 0.9rem; font-weight: 500; color: #6c757d; margin-top: 0.5rem; -} +} \ No newline at end of file diff --git a/src/App.js b/src/App.js index ff9f432..3ec1dfc 100644 --- a/src/App.js +++ b/src/App.js @@ -1,205 +1,159 @@ -import './App.css'; // This line imports the styles you just added -import { useState, useCallback } from 'react'; -// Import custom hook for habit reminders -import { useReminder } from './hooks/useReminder'; -import { subWeeks, addWeeks, subMonths, addMonths } from 'date-fns'; -import { useHabits } from './hooks/useHabits'; -import { achievements } from './constants'; -import { initialHabits } from './constants'; -import HabitForm from './components/HabitForm'; -import CategoryFilter from './components/CategoryFilter'; -import CalendarToggle from './components/CalendarToggle'; -import HabitGrid from './components/HabitGrid'; -import HabitCard from './components/HabitCard'; -import AchievementModal from './components/AchievementModal'; -import NotificationSettings from './components/NotificationSettings/NotificationSettings'; -// --- 1. IMPORT THE NEW MOTIVATIONAL QUOTE COMPONENT --- -import MotivationalQuote from './components/MotivationalQuote'; +import "./App.css"; +import { useState, useCallback } from "react"; +import { useHabits } from "./hooks/useHabits"; +import { useReminder } from "./hooks/useReminder"; +import { subWeeks, addWeeks, subMonths, addMonths } from "date-fns"; +import { initialHabits } from "./constants"; + +// Import all components +import HabitForm from "./components/HabitForm"; +import CategoryFilter from "./components/CategoryFilter"; +import CalendarToggle from "./components/CalendarToggle"; +import HabitGrid from "./components/HabitGrid"; +import HabitCard from "./components/HabitCard"; +import AchievementModal from "./components/AchievementModal"; +import NotificationSettings from "./components/NotificationSettings/NotificationSettings"; +import MotivationalQuote from "./components/MotivationalQuote"; function App() { + // Custom hooks for managing state const { habits, - calculateStreak, - averageCompletion, - isCompletedOn, - toggleCompletion, addHabit, deleteHabit, + toggleCompletion, + isCompletedOn, + calculateStreak, + averageCompletion, } = useHabits(initialHabits); - const [selectedCategory, setSelectedCategory] = useState('All'); - const [calendarMode, setCalendarMode] = useState('90day'); - // Removed unused state: newlyUnlocked, setNewlyUnlocked, modalOpen, setModalOpen + // All state for this component + const [accessibility, setAccessibility] = useState({ + largeText: false, + highContrast: false, + }); + const [selectedCategory, setSelectedCategory] = useState("All"); + const [calendarMode, setCalendarMode] = useState("90day"); const [selectedHabit, setSelectedHabit] = useState(null); const [currentDate, setCurrentDate] = useState(new Date()); - // User opt-in for habit reminders (permission control) const [reminderPermission, setReminderPermission] = useState(false); - // Function to show a simple toast/alert for reminders + + // Your accessibility functions + const toggleLargeText = () => { + setAccessibility((prev) => ({ ...prev, largeText: !prev.largeText })); + }; + + const toggleHighContrast = () => { + setAccessibility((prev) => ({ ...prev, highContrast: !prev.highContrast })); + }; + + // Your dynamic class name logic + const appClasses = [ + "App", + accessibility.largeText ? "large-text" : "", + accessibility.highContrast ? "high-contrast" : "", + ] + .join(" ") + .trim(); + + // Logic from the other branch const showReminder = (habit) => { alert(`Reminder: Complete Daily ${habit.name}!`); }; - - // Integrate reminder hook: only active if user has opted in useReminder(habits, showReminder, reminderPermission); - const filteredHabits = selectedCategory === 'All' - ? habits - : habits.filter(habit => habit.category === selectedCategory); + const filteredHabits = + selectedCategory === "All" + ? habits + : habits.filter((habit) => habit.category === selectedCategory); const toggleCalendarMode = useCallback(() => { - setCalendarMode(prev => { - if (prev === '90day') return 'weekly'; - if (prev === 'weekly') return 'monthly'; - return '90day'; + setCalendarMode((prev) => { + if (prev === "90day") return "weekly"; + if (prev === "weekly") return "monthly"; + return "90day"; }); }, []); - const handleToggleCompletion = useCallback((habitId, day) => { - toggleCompletion(habitId, day); - }, [toggleCompletion]); + const handleToggleCompletion = useCallback( + (habitId, day) => { + toggleCompletion(habitId, day); + }, + [toggleCompletion] + ); - // Show achievements modal for selected habit const handleViewAchievements = useCallback((habit) => { setSelectedHabit(habit); }, []); - // Close achievements modal const handleCloseModal = useCallback(() => { setSelectedHabit(null); }, []); - const handleExportCSV = () => { - if (habits.length === 0) { - alert("There are no habits to export."); - return; - } - - const headers = ['id', 'name', 'category', 'completions']; - - const rows = habits.map(habit => { - const { id, name, category, completions } = habit; - - const escapedName = `"${name.replace(/"/g, '""')}"`; - const escapedCategory = `"${category.replace(/"/g, '""')}"`; - - const completionsJSON = `"${JSON.stringify(completions).replace(/"/g, '""')}"`; - - return [id, escapedName, escapedCategory, completionsJSON].join(','); - }); - - const csvContent = [ - headers.join(','), - ...rows - ].join('\n'); - - const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' }); - const link = document.createElement('a'); - const url = URL.createObjectURL(blob); - link.setAttribute('href', url); - link.setAttribute('download', 'habits.csv'); - link.style.visibility = 'hidden'; - document.body.appendChild(link); - link.click(); - document.body.removeChild(link); - }; - - const handleExportJSON = () => { - if (habits.length === 0) { - alert("There are no habits to export."); - return; - } - - const jsonContent = JSON.stringify(habits, null, 2); - const blob = new Blob([jsonContent], { type: 'application/json;charset=utf-8;' }); - const link = document.createElement('a'); - const url = URL.createObjectURL(blob); - link.setAttribute('href', url); - link.setAttribute('download', 'habits.json'); - link.style.visibility = 'hidden'; - document.body.appendChild(link); - link.click(); - document.body.removeChild(link); - }; - return ( -
- {/* Reminder permission opt-in UI */} -
- {/* Checkbox to allow user to enable/disable reminders */} - -
+
+ {" "} + {/* Your dynamic class is here */}
- - - {/* --- 2. RENDER THE NEW COMPONENT RIGHT HERE --- */} - - -
- + - -
- - {/* END: Added Export Buttons Container */} - -
-

Achievements:

- {habits.map(habit => ( -
-
{habit.name}
-
- {habit.achievements.length === 0 ? ( - No achievements yet - ) : ( - habit.achievements.map(aid => { - const ach = achievements.find(a => a.id === aid); - return ( - - {ach ? ach.name : aid} - - ); - }) - )} -
-
- ))}
- - + {/* All components and features from the other branch */} + + + + + + - {calendarMode !== '90day' && ( + {calendarMode !== "90day" && (
- - + +
)} -
+

Current Habits:

{filteredHabits.length === 0 ? (

No habits in this category

- ) : calendarMode === '90day' ? ( + ) : calendarMode === "90day" ? (
{filteredHabits.map((habit) => ( ))}
@@ -224,17 +177,7 @@ function App() { /> )}
- - - Learn React -
-
);