import { useState, useEffect } from 'react' import Auth from './Auth' import './App.css' const API_URL = import.meta.env.VITE_API_URL || 'http://localhost:8000' const AVAILABLE_ICONS = [ '📝', '💼', '🏠', '🛒', '🎯', '💪', '📚', '✈️', '🎨', '🎮', '🎵', '🎬', '📱', '💻', '⚽', '🏃', '🍕', '☕', '🌟', '❤️', '🔥', '✨', '🌈', '🎉', '📖', '✍️', '🎓', '💡', '🔧', '🏆', '🎪', '🎭' ] function App() { const [user, setUser] = useState(null) const [token, setToken] = useState(null) const [lists, setLists] = useState([]) const [selectedList, setSelectedList] = useState(null) const [tasks, setTasks] = useState([]) const [newTask, setNewTask] = useState('') const [newListName, setNewListName] = useState('') const [selectedIcon, setSelectedIcon] = useState('📝') const [showNewListForm, setShowNewListForm] = useState(false) const [filter, setFilter] = useState('all') const [loading, setLoading] = useState(false) const [editingTaskId, setEditingTaskId] = useState(null) const [editingTaskTitle, setEditingTaskTitle] = useState('') const [confirmModal, setConfirmModal] = useState({ show: false, message: '', onConfirm: null }) const [darkMode, setDarkMode] = useState(false) useEffect(() => { // Check for stored token on mount const storedToken = localStorage.getItem('token') const storedUser = localStorage.getItem('user') if (storedToken && storedUser) { setToken(storedToken) const userData = JSON.parse(storedUser) setUser(userData) // Load user's dark mode preference const userDarkMode = localStorage.getItem(`darkMode_${userData.id}`) setDarkMode(userDarkMode ? JSON.parse(userDarkMode) : false) } }, []) useEffect(() => { if (token) { fetchLists() } }, [token]) useEffect(() => { if (selectedList && token) { fetchTasks(selectedList.id) } }, [selectedList, token]) useEffect(() => { if (user) { localStorage.setItem(`darkMode_${user.id}`, JSON.stringify(darkMode)) } if (darkMode) { document.body.classList.add('dark-mode') } else { document.body.classList.remove('dark-mode') } }, [darkMode, user]) const toggleDarkMode = () => { setDarkMode(!darkMode) } const getAuthHeaders = () => ({ 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` }) const handleLogin = (userData, userToken) => { setUser(userData) setToken(userToken) // Load user's dark mode preference const userDarkMode = localStorage.getItem(`darkMode_${userData.id}`) setDarkMode(userDarkMode ? JSON.parse(userDarkMode) : false) } const handleLogout = () => { setConfirmModal({ show: true, message: 'Are you sure you want to sign out?', onConfirm: async () => { try { await fetch(`${API_URL}/logout`, { method: 'POST', headers: getAuthHeaders() }) } catch (error) { console.error('Logout error:', error) } localStorage.removeItem('token') localStorage.removeItem('user') setUser(null) setToken(null) setLists([]) setTasks([]) setSelectedList(null) setConfirmModal({ show: false, message: '', onConfirm: null }) } }) } const fetchLists = async () => { try { const response = await fetch(`${API_URL}/lists`, { headers: getAuthHeaders() }) const data = await response.json() setLists(data) if (data.length > 0 && !selectedList) { setSelectedList(data[0]) } } catch (error) { console.error('Error fetching lists:', error) } } const fetchTasks = async (listId) => { try { const response = await fetch(`${API_URL}/tasks?list_id=${listId}`, { headers: getAuthHeaders() }) const data = await response.json() setTasks(data) } catch (error) { console.error('Error fetching tasks:', error) } } const addList = async (e) => { e.preventDefault() if (!newListName.trim()) return const colors = ['#667eea', '#f093fb', '#4facfe', '#43e97b', '#fa709a', '#feca57', '#ff6b6b', '#48dbfb'] try { const response = await fetch(`${API_URL}/lists`, { method: 'POST', headers: getAuthHeaders(), body: JSON.stringify({ name: newListName, icon: selectedIcon, color: colors[Math.floor(Math.random() * colors.length)] }) }) const data = await response.json() setLists([...lists, data]) setNewListName('') setSelectedIcon('📝') setShowNewListForm(false) setSelectedList(data) } catch (error) { console.error('Error adding list:', error) } } const deleteList = async (listId) => { setConfirmModal({ show: true, message: 'Delete this list and all its tasks?', onConfirm: async () => { try { await fetch(`${API_URL}/lists/${listId}`, { method: 'DELETE', headers: getAuthHeaders() }) const updatedLists = lists.filter(list => list.id !== listId) setLists(updatedLists) if (selectedList?.id === listId) { setSelectedList(updatedLists[0] || null) setTasks([]) } } catch (error) { console.error('Error deleting list:', error) } setConfirmModal({ show: false, message: '', onConfirm: null }) } }) } const addTask = async (e) => { e.preventDefault() if (!newTask.trim() || !selectedList) return setLoading(true) try { const response = await fetch(`${API_URL}/tasks`, { method: 'POST', headers: getAuthHeaders(), body: JSON.stringify({ title: newTask, list_id: selectedList.id }) }) const data = await response.json() setTasks([...tasks, data]) setNewTask('') } catch (error) { console.error('Error adding task:', error) } finally { setLoading(false) } } const toggleTask = async (id, completed) => { try { const response = await fetch(`${API_URL}/tasks/${id}`, { method: 'PUT', headers: getAuthHeaders(), body: JSON.stringify({ completed: !completed }) }) const data = await response.json() setTasks(tasks.map(task => task.id === id ? data : task)) } catch (error) { console.error('Error updating task:', error) } } const deleteTask = async (id) => { try { await fetch(`${API_URL}/tasks/${id}`, { method: 'DELETE', headers: getAuthHeaders() }) setTasks(tasks.filter(task => task.id !== id)) } catch (error) { console.error('Error deleting task:', error) } } const startEditTask = (task) => { setEditingTaskId(task.id) setEditingTaskTitle(task.title) } const saveEditTask = async (id) => { if (!editingTaskTitle.trim()) return try { const response = await fetch(`${API_URL}/tasks/${id}`, { method: 'PUT', headers: getAuthHeaders(), body: JSON.stringify({ title: editingTaskTitle }) }) const data = await response.json() setTasks(tasks.map(task => task.id === id ? data : task)) setEditingTaskId(null) setEditingTaskTitle('') } catch (error) { console.error('Error updating task:', error) } } const cancelEditTask = () => { setEditingTaskId(null) setEditingTaskTitle('') } const filteredTasks = tasks.filter(task => { if (filter === 'active') return !task.completed if (filter === 'completed') return task.completed return true }) const activeTasks = tasks.filter(t => !t.completed).length if (!user || !token) { return } return (

✓ Tasko

Hello, {user.username}!
{lists.map(list => (
setSelectedList(list)} >
{list.icon} {list.name}
))}
{showNewListForm ? (
setNewListName(e.target.value)} placeholder="List name..." className="new-list-input" autoFocus />
{AVAILABLE_ICONS.map(icon => ( ))}
) : ( )}
{selectedList ? ( <>

{selectedList.icon} {selectedList.name}

setNewTask(e.target.value)} placeholder="What needs to be done?" className="task-input" disabled={loading} />
{filteredTasks.length === 0 ? (

{filter === 'completed' ? 'No completed tasks yet' : filter === 'active' ? 'No active tasks' : 'No tasks yet. Add one above!'}

) : ( filteredTasks.map(task => (
toggleTask(task.id, task.completed)} className="task-checkbox" /> {editingTaskId === task.id ? ( setEditingTaskTitle(e.target.value)} className="task-edit-input" autoFocus onKeyDown={(e) => { if (e.key === 'Enter') saveEditTask(task.id) if (e.key === 'Escape') cancelEditTask() }} /> ) : ( startEditTask(task)} title="Double-click to edit" > {task.title} )}
{editingTaskId === task.id ? ( <> ) : ( <> )}
)) )}
) : (

No lists yet

Create a new list to get started!

)}
{/* Confirmation Modal */} {confirmModal.show && (
setConfirmModal({ show: false, message: '', onConfirm: null })}>
e.stopPropagation()}>

Confirm Action

{confirmModal.message}

)}
) } export default App