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
{filter === 'completed' ? 'No completed tasks yet' : filter === 'active' ? 'No active tasks' : 'No tasks yet. Add one above!'}
) : ( filteredTasks.map(task => (Create a new list to get started!
{confirmModal.message}