From 4a45cc67bc04502c22a3f7e5837bb6618f2f7030 Mon Sep 17 00:00:00 2001 From: Ulrika Einebrant Date: Tue, 21 Oct 2025 14:53:32 +0200 Subject: [PATCH 01/15] =?UTF-8?q?=E2=9C=A8=20Add=20Zustand=20store,=20comp?= =?UTF-8?q?onents=20and=20global=20styles=20for=20Todo=20app?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 5 ++- src/App.jsx | 40 +++++++++++++++++++- src/components/EmptyState.jsx | 17 +++++++++ src/components/Footer.jsx | 28 ++++++++++++++ src/components/TodoForm.jsx | 71 +++++++++++++++++++++++++++++++++++ src/components/TodoItem.jsx | 50 ++++++++++++++++++++++++ src/components/TodoList.jsx | 16 ++++++++ src/store/useTodoStore.js | 39 +++++++++++++++++++ src/styles/GlobalStyles.js | 38 +++++++++++++++++++ 9 files changed, 302 insertions(+), 2 deletions(-) create mode 100644 src/components/EmptyState.jsx create mode 100644 src/components/Footer.jsx create mode 100644 src/components/TodoForm.jsx create mode 100644 src/components/TodoItem.jsx create mode 100644 src/components/TodoList.jsx create mode 100644 src/store/useTodoStore.js create mode 100644 src/styles/GlobalStyles.js diff --git a/package.json b/package.json index caf6289..5689a8b 100644 --- a/package.json +++ b/package.json @@ -10,8 +10,11 @@ "preview": "vite preview" }, "dependencies": { + "nanoid": "^5.1.6", "react": "^19.0.0", - "react-dom": "^19.0.0" + "react-dom": "^19.0.0", + "styled-components": "^6.1.19", + "zustand": "^5.0.8" }, "devDependencies": { "@eslint/js": "^9.21.0", diff --git a/src/App.jsx b/src/App.jsx index 5427540..fcab3a5 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,5 +1,43 @@ +// src/App.jsx +import styled from 'styled-components' +import GlobalStyles from './styles/GlobalStyles.js' +import { useTodoStore } from './store/useTodoStore.js' +import TodoForm from './components/TodoForm.jsx' +import TodoList from './components/TodoList.jsx' +import EmptyState from './components/EmptyState.jsx' +import Footer from './components/Footer.jsx' + +const Shell = styled.main` + max-width: 720px; margin: 0 auto; padding: 24px; min-height: 100dvh; display: grid; align-content: start; gap: 18px; +` +const H1 = styled.h1` + margin: 8px 0 4px; font-size: clamp(28px, 3vw, 40px); +` +const Card = styled.section` + display: grid; gap: 12px; +` + export const App = () => { + const tasks = useTodoStore(s => s.tasks) + const total = tasks.length + const remaining = tasks.filter(t => !t.completed).length + return ( -

React Boilerplate

+ <> + + +
+

Todos

+

Powered by Zustand β€” no prop drilling πŸ‘‹

+
+ + + + + {total === 0 ? : } +