import React, { useState, useEffect } from 'react';
import { initializeApp } from 'firebase/app';
import {
getAuth,
createUserWithEmailAndPassword,
signInWithEmailAndPassword,
signOut,
onAuthStateChanged,
updateProfile,
signInWithCustomToken
} from 'firebase/auth';
import {
getFirestore,
collection,
addDoc,
onSnapshot,
doc,
updateDoc,
deleteDoc,
serverTimestamp,
query
} from 'firebase/firestore';
import {
Loader2,
LogOut,
Plus,
Trash2,
Edit2,
CheckCircle2,
Circle,
X,
Save,
Layout,
ListTodo
} from 'lucide-react';
// --- Firebase Configuration & Initialization ---
// Import the functions you need from the SDKs you need
import { initializeApp } from "firebase/app";
// TODO: Add SDKs for Firebase products that you want to use
// https://firebase.google.com/docs/web/setup#available-libraries
// Your web app's Firebase configuration
const firebaseConfig = {
apiKey: "AIzaSyDByV4VYyRydQafZD1e0YUgmIgZOZze4IM",
authDomain: "taskflow-app-68523.firebaseapp.com",
projectId: "taskflow-app-68523",
storageBucket: "taskflow-app-68523.firebasestorage.app",
messagingSenderId: "852660449313",
appId: "1:852660449313:web:1448f523688b22ebc53360"
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
// --- Main Application Component ---
export default function App() {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
const [authError, setAuthError] = useState('');
// Initial Auth Setup
useEffect(() => {
// Safety timer: If Firebase takes too long to initialize (common in iframes/laptops
// with strict privacy settings), force the loading screen to disappear so you can try logging in.
const safetyTimer = setTimeout(() => {
setLoading((currentLoading) => {
if (currentLoading) {
console.warn("Auth listener timed out - forcing UI load");
return false;
}
return currentLoading;
});
}, 2500);
const initAuth = async () => {
// If the environment provides a specific token, we prioritize it
if (typeof __initial_auth_token !== 'undefined' && __initial_auth_token) {
try {
await signInWithCustomToken(auth, __initial_auth_token);
} catch (e) {
console.error("Custom token auth failed", e);
}
}
// Note: We don't force anonymous sign-in here because we want explicit
// Email/Password login for this specific demo requirements.
};
initAuth();
const unsubscribe = onAuthStateChanged(auth, (currentUser) => {
clearTimeout(safetyTimer);
setUser(currentUser);
setLoading(false);
});
return () => {
unsubscribe();
clearTimeout(safetyTimer);
};
}, []);
if (loading) {
return (
);
}
return (
);
}
// --- Authentication Screen (Login/Register) ---
function AuthScreen({ onAuthError, authError }) {
const [isLogin, setIsLogin] = useState(true);
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [isSubmitting, setIsSubmitting] = useState(false);
const handleSubmit = async (e) => {
e.preventDefault();
setIsSubmitting(true);
onAuthError('');
try {
if (isLogin) {
await signInWithEmailAndPassword(auth, email, password);
} else {
await createUserWithEmailAndPassword(auth, email, password);
}
} catch (error) {
console.error(error);
let msg = "An error occurred.";
if (error.code === 'auth/invalid-email') msg = "Invalid email address.";
if (error.code === 'auth/user-disabled') msg = "User account disabled.";
if (error.code === 'auth/user-not-found') msg = "No account found with this email.";
if (error.code === 'auth/wrong-password') msg = "Incorrect password.";
if (error.code === 'auth/email-already-in-use') msg = "Email already in use.";
if (error.code === 'auth/weak-password') msg = "Password should be at least 6 characters.";
onAuthError(msg);
} finally {
setIsSubmitting(false);
}
};
return (
{isLogin ? 'Welcome Back' : 'Create Account'}
{isLogin ? 'Enter your details to access your tasks' : 'Start organizing your life today'}
{authError && (
{authError}
)}
);
}
// --- Dashboard Component (CRUD Operations) ---
function Dashboard({ user }) {
const [tasks, setTasks] = useState([]);
const [newTask, setNewTask] = useState('');
const [editingId, setEditingId] = useState(null);
const [editTitle, setEditTitle] = useState('');
const [loadingData, setLoadingData] = useState(true);
// Firestore: Real-time Listener
useEffect(() => {
if (!user) return;
// RULE 1: Correct Path for User Data
const tasksCollection = collection(db, 'artifacts', appId, 'users', user.uid, 'tasks');
// RULE 2: Simple Query (Filtering done in client if needed, sorting here is memory-based later)
const q = query(tasksCollection);
const unsubscribe = onSnapshot(q, (snapshot) => {
const taskList = snapshot.docs.map(doc => ({
id: doc.id,
...doc.data()
}));
// Sort manually since we avoid complex queries
taskList.sort((a, b) => (b.createdAt?.seconds || 0) - (a.createdAt?.seconds || 0));
setTasks(taskList);
setLoadingData(false);
}, (error) => {
console.error("Error fetching tasks:", error);
setLoadingData(false);
});
return () => unsubscribe();
}, [user]);
// Create
const handleAddTask = async (e) => {
e.preventDefault();
if (!newTask.trim()) return;
try {
const tasksCollection = collection(db, 'artifacts', appId, 'users', user.uid, 'tasks');
await addDoc(tasksCollection, {
title: newTask,
completed: false,
createdAt: serverTimestamp()
});
setNewTask('');
} catch (error) {
console.error("Error adding task:", error);
}
};
// Update (Toggle Complete)
const toggleComplete = async (task) => {
try {
const taskRef = doc(db, 'artifacts', appId, 'users', user.uid, 'tasks', task.id);
await updateDoc(taskRef, {
completed: !task.completed
});
} catch (error) {
console.error("Error updating task:", error);
}
};
// Update (Edit Title)
const startEdit = (task) => {
setEditingId(task.id);
setEditTitle(task.title);
};
const saveEdit = async () => {
if (!editTitle.trim()) return;
try {
const taskRef = doc(db, 'artifacts', appId, 'users', user.uid, 'tasks', editingId);
await updateDoc(taskRef, {
title: editTitle
});
setEditingId(null);
} catch (error) {
console.error("Error saving edit:", error);
}
};
// Delete
const deleteTask = async (id) => {
if (!window.confirm("Delete this task?")) return;
try {
const taskRef = doc(db, 'artifacts', appId, 'users', user.uid, 'tasks', id);
await deleteDoc(taskRef);
} catch (error) {
console.error("Error deleting task:", error);
}
};
const handleLogout = async () => {
try {
await signOut(auth);
} catch (error) {
console.error("Error signing out:", error);
}
};
return (
{/* Header */}
TaskFlow
Welcome, {user.email}
{/* Add Task Form */}
{/* Task List */}
{loadingData ? (
) : tasks.length === 0 ? (
No tasks yet
Add a task above to get started!
) : (
)}
Data is stored securely in Firebase Firestore.
Collection Path: users/{user.uid}/tasks
);
}