Skip to content

Commit ee45197

Browse files
committed
Add ability to clear all local data (closes #5)
1 parent e6f21f5 commit ee45197

File tree

3 files changed

+62
-13
lines changed

3 files changed

+62
-13
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Worthy Derby Voting App
22

3-
A web application for running pinewood derby voting events. Built for Trail Life Troop TX-0521's annual Worthy Derby competition.
3+
A web application for running derby voting events. Built for Trail Life Troop TX-0521's annual Worthy Derby competition.
44

55
## Features
66

@@ -66,7 +66,7 @@ npm run preview
6666

6767
## Data Storage
6868

69-
All data is stored in the browser's localStorage under the key `derby-vote-data`. Use the Export/Import feature in Setup to backup your data or transfer between devices.
69+
All data is stored in the browser's localStorage under the key `derby-vote-data`. Use the Export/Import feature in Setup to backup your data or transfer between devices. The Danger Zone section provides options to delete individual events or clear all local data.
7070

7171
## Tech Stack
7272

src/App.jsx

Lines changed: 55 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { useState, useEffect } from 'react';
2-
import { getEvent, saveEvent, getAllEvents, getCars, createEvent, getEventById, setCurrentEventId, getCurrentEventId, deleteEvent } from './storage';
2+
import { getEvent, saveEvent, getAllEvents, getCars, createEvent, getEventById, setCurrentEventId, getCurrentEventId, deleteEvent, clearAllData } from './storage';
33
import Setup from './components/Setup';
44
import Voting from './components/Voting';
55
import Results from './components/Results';
@@ -38,6 +38,7 @@ function App() {
3838
const [newEventDate, setNewEventDate] = useState(new Date().toISOString().split('T')[0]);
3939
const [sidebarCollapsed, setSidebarCollapsed] = useState(false);
4040
const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);
41+
const [showClearAllConfirm, setShowClearAllConfirm] = useState(false);
4142

4243
const handleUpdateEvent = (updatedEvent) => {
4344
saveEvent(updatedEvent);
@@ -97,6 +98,16 @@ function App() {
9798
setShowEventPicker(false);
9899
};
99100

101+
const handleClearAllData = () => {
102+
clearAllData();
103+
// Reset to a fresh state with a new default event
104+
const newEvent = createEvent(`Worthy Derby ${currentYear}`, new Date().toISOString().split('T')[0]);
105+
setAllEvents([newEvent]);
106+
setEvent(newEvent);
107+
setShowClearAllConfirm(false);
108+
setView('setup');
109+
};
110+
100111
// Toggle presentation mode with Escape key
101112
useEffect(() => {
102113
const handleKeyDown = (e) => {
@@ -278,17 +289,31 @@ function App() {
278289

279290
<div className="mt-8 p-6 bg-surface rounded-lg shadow">
280291
<h3 className="text-lg font-semibold text-danger mb-4 flex items-center gap-2"><AlertTriangle size={20} /> Danger Zone</h3>
281-
<div className="flex items-center justify-between gap-4 p-4 bg-background rounded">
282-
<div>
283-
<strong className="text-text-primary">Delete this event</strong>
284-
<p className="text-text-light text-sm mt-1">Permanently delete "{event.name}" and all its votes. This cannot be undone.</p>
292+
<div className="space-y-4">
293+
<div className="flex items-center justify-between gap-4 p-4 bg-background rounded">
294+
<div>
295+
<strong className="text-text-primary">Delete this event</strong>
296+
<p className="text-text-light text-sm mt-1">Permanently delete "{event.name}" and all its votes. This cannot be undone.</p>
297+
</div>
298+
<button
299+
className="px-4 py-2 bg-danger text-white font-semibold rounded hover:bg-danger/80 transition-colors shrink-0"
300+
onClick={() => setShowDeleteConfirm(true)}
301+
>
302+
Delete Event
303+
</button>
304+
</div>
305+
<div className="flex items-center justify-between gap-4 p-4 bg-background rounded">
306+
<div>
307+
<strong className="text-text-primary">Clear all local data</strong>
308+
<p className="text-text-light text-sm mt-1">Delete all events, votes, and settings from this browser. This cannot be undone.</p>
309+
</div>
310+
<button
311+
className="px-4 py-2 bg-danger text-white font-semibold rounded hover:bg-danger/80 transition-colors shrink-0"
312+
onClick={() => setShowClearAllConfirm(true)}
313+
>
314+
Clear All Data
315+
</button>
285316
</div>
286-
<button
287-
className="px-4 py-2 bg-danger text-white font-semibold rounded hover:bg-danger/80 transition-colors shrink-0"
288-
onClick={() => setShowDeleteConfirm(true)}
289-
>
290-
Delete Event
291-
</button>
292317
</div>
293318
</div>
294319

@@ -312,6 +337,25 @@ function App() {
312337
</div>
313338
</div>
314339
)}
340+
341+
{showClearAllConfirm && (
342+
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50" onClick={() => setShowClearAllConfirm(false)}>
343+
<div className="bg-surface p-6 rounded-lg shadow-lg max-w-md w-full mx-4" onClick={(e) => e.stopPropagation()}>
344+
<h3 className="text-lg font-semibold text-text-primary mb-4">Clear All Data?</h3>
345+
<p className="text-text-primary mb-2">Are you sure you want to delete <strong>all events and data</strong> from this browser?</p>
346+
<p className="text-text-primary text-sm mb-2">Consider exporting a backup first using the Export Data button above.</p>
347+
<p className="text-danger text-sm mb-6">This action cannot be undone.</p>
348+
<div className="flex justify-end gap-3">
349+
<button className="px-4 py-2 bg-background text-text-primary font-medium rounded hover:bg-border transition-colors" onClick={() => setShowClearAllConfirm(false)}>
350+
Cancel
351+
</button>
352+
<button className="px-4 py-2 bg-danger text-white font-semibold rounded hover:bg-danger/80 transition-colors" onClick={handleClearAllData}>
353+
Clear All Data
354+
</button>
355+
</div>
356+
</div>
357+
</div>
358+
)}
315359
</>
316360
)}
317361
</div>

src/storage.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,11 @@ export function deleteEvent(year) {
231231
saveAllData(data);
232232
}
233233

234+
// Clear all data from localStorage
235+
export function clearAllData() {
236+
localStorage.removeItem(STORAGE_KEY);
237+
}
238+
234239
// Slips are stored directly in the event as event.slips
235240
// Each slip is { timestamp, votes: [{ category, carNumber }, ...] }
236241

0 commit comments

Comments
 (0)