Add bottom navigation, History and Settings pages with improved UI styling
This commit is contained in:
@@ -4,6 +4,9 @@
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Lora:ital,wght@0,400;0,500;1,400&family=Playfair+Display:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||||
<title>Grateful Journal</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
1275
src/App.css
1275
src/App.css
File diff suppressed because it is too large
Load Diff
18
src/App.tsx
18
src/App.tsx
@@ -2,6 +2,8 @@ import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom'
|
||||
import { AuthProvider } from './contexts/AuthContext'
|
||||
import { ProtectedRoute } from './components/ProtectedRoute'
|
||||
import HomePage from './pages/HomePage'
|
||||
import HistoryPage from './pages/HistoryPage'
|
||||
import SettingsPage from './pages/SettingsPage'
|
||||
import LoginPage from './pages/LoginPage'
|
||||
import './App.css'
|
||||
|
||||
@@ -18,6 +20,22 @@ function App() {
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/history"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<HistoryPage />
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/settings"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<SettingsPage />
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route path="/login" element={<LoginPage />} />
|
||||
<Route path="*" element={<Navigate to="/login" replace />} />
|
||||
</Routes>
|
||||
|
||||
48
src/components/BottomNav.tsx
Normal file
48
src/components/BottomNav.tsx
Normal file
@@ -0,0 +1,48 @@
|
||||
import { useNavigate, useLocation } from 'react-router-dom'
|
||||
|
||||
export default function BottomNav() {
|
||||
const navigate = useNavigate()
|
||||
const location = useLocation()
|
||||
|
||||
const isActive = (path: string) => location.pathname === path
|
||||
|
||||
return (
|
||||
<nav className="bottom-nav">
|
||||
<button
|
||||
type="button"
|
||||
className={`bottom-nav-btn ${isActive('/') ? 'bottom-nav-btn-active' : ''}`}
|
||||
onClick={() => navigate('/')}
|
||||
>
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<path d="M12 19l7-7 3 3-7 7-3-3z"></path>
|
||||
<path d="M18 13l-1.5-7.5L2 2l3.5 14.5L13 18l5-5z"></path>
|
||||
<path d="M2 2l7.586 7.586"></path>
|
||||
<circle cx="11" cy="11" r="2"></circle>
|
||||
</svg>
|
||||
<span>Write</span>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className={`bottom-nav-btn ${isActive('/history') ? 'bottom-nav-btn-active' : ''}`}
|
||||
onClick={() => navigate('/history')}
|
||||
>
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path>
|
||||
<polyline points="9 22 9 12 15 12 15 22"></polyline>
|
||||
</svg>
|
||||
<span>History</span>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className={`bottom-nav-btn ${isActive('/settings') ? 'bottom-nav-btn-active' : ''}`}
|
||||
onClick={() => navigate('/settings')}
|
||||
>
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<circle cx="12" cy="12" r="3"></circle>
|
||||
<path d="M12 1v6m0 6v6m5.196-15.804l-4.243 4.243m-5.657 5.657l-4.243 4.243M23 12h-6m-6 0H1m15.804 5.196l-4.243-4.243m-5.657-5.657L2.661 2.661"></path>
|
||||
</svg>
|
||||
<span>Settings</span>
|
||||
</button>
|
||||
</nav>
|
||||
)
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Grateful Journal – green palette from Coolors */
|
||||
/* Grateful Journal – enhanced green palette */
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
@@ -6,7 +6,7 @@
|
||||
}
|
||||
|
||||
:root {
|
||||
font-family: system-ui, -apple-system, sans-serif;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
|
||||
line-height: 1.5;
|
||||
font-weight: 400;
|
||||
/* Responsive base: 16px at 320px, scales up to 18px by 768px */
|
||||
@@ -19,7 +19,7 @@
|
||||
--color-accent-light: #cff2dc;
|
||||
--color-accent-bright: #c3fd2f;
|
||||
--color-text: #1a1a1a;
|
||||
--color-text-muted: #555;
|
||||
--color-text-muted: #6b7280;
|
||||
--color-border: #cff2dc;
|
||||
|
||||
color: var(--color-text);
|
||||
|
||||
180
src/pages/HistoryPage.tsx
Normal file
180
src/pages/HistoryPage.tsx
Normal file
@@ -0,0 +1,180 @@
|
||||
import { useState } from 'react'
|
||||
import BottomNav from '../components/BottomNav'
|
||||
|
||||
interface JournalEntry {
|
||||
id: string
|
||||
date: Date
|
||||
title: string
|
||||
content: string
|
||||
}
|
||||
|
||||
export default function HistoryPage() {
|
||||
const [currentMonth, setCurrentMonth] = useState(new Date())
|
||||
|
||||
// Mock data - replace with actual Firebase data later
|
||||
const mockEntries: JournalEntry[] = [
|
||||
{
|
||||
id: '1',
|
||||
date: new Date(2026, 1, 12),
|
||||
title: 'Feeling much lighter today',
|
||||
content: 'After the long conversation yesterday, I woke up with a sense of clarity I haven\'t felt in weeks...'
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
date: new Date(2026, 1, 5),
|
||||
title: 'Morning thoughts',
|
||||
content: 'The coffee smells amazing this morning. Simple pleasures like this remind me...'
|
||||
}
|
||||
]
|
||||
|
||||
const getDaysInMonth = (date: Date) => {
|
||||
const year = date.getFullYear()
|
||||
const month = date.getMonth()
|
||||
const firstDay = new Date(year, month, 1)
|
||||
const lastDay = new Date(year, month + 1, 0)
|
||||
const daysInMonth = lastDay.getDate()
|
||||
const startingDayOfWeek = firstDay.getDay()
|
||||
|
||||
return { daysInMonth, startingDayOfWeek }
|
||||
}
|
||||
|
||||
const hasEntryOnDate = (day: number) => {
|
||||
return mockEntries.some(entry => {
|
||||
const entryDate = new Date(entry.date)
|
||||
return entryDate.getDate() === day &&
|
||||
entryDate.getMonth() === currentMonth.getMonth() &&
|
||||
entryDate.getFullYear() === currentMonth.getFullYear()
|
||||
})
|
||||
}
|
||||
|
||||
const isToday = (day: number) => {
|
||||
const today = new Date()
|
||||
return day === today.getDate() &&
|
||||
currentMonth.getMonth() === today.getMonth() &&
|
||||
currentMonth.getFullYear() === today.getFullYear()
|
||||
}
|
||||
|
||||
const formatDate = (date: Date) => {
|
||||
return date.toLocaleDateString('en-US', {
|
||||
weekday: 'short',
|
||||
month: 'short',
|
||||
day: '2-digit'
|
||||
}).toUpperCase()
|
||||
}
|
||||
|
||||
const formatTime = (date: Date) => {
|
||||
return date.toLocaleTimeString('en-US', {
|
||||
hour: '2-digit',
|
||||
minute: '2-digit'
|
||||
}).toUpperCase()
|
||||
}
|
||||
|
||||
const { daysInMonth, startingDayOfWeek } = getDaysInMonth(currentMonth)
|
||||
const monthName = currentMonth.toLocaleDateString('en-US', { month: 'long', year: 'numeric' })
|
||||
|
||||
const previousMonth = () => {
|
||||
setCurrentMonth(new Date(currentMonth.getFullYear(), currentMonth.getMonth() - 1))
|
||||
}
|
||||
|
||||
const nextMonth = () => {
|
||||
setCurrentMonth(new Date(currentMonth.getFullYear(), currentMonth.getMonth() + 1))
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="history-page">
|
||||
<div className="history-bg-decoration">
|
||||
<div className="bg-orb bg-orb-1"></div>
|
||||
<div className="bg-orb bg-orb-2"></div>
|
||||
<div className="bg-pattern"></div>
|
||||
</div>
|
||||
|
||||
<header className="history-header">
|
||||
<div className="history-header-text">
|
||||
<h1>History</h1>
|
||||
<p className="history-subtitle">Your past reflections</p>
|
||||
</div>
|
||||
<button type="button" className="history-search-btn" title="Search entries">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<circle cx="11" cy="11" r="8"></circle>
|
||||
<path d="m21 21-4.35-4.35"></path>
|
||||
</svg>
|
||||
</button>
|
||||
</header>
|
||||
|
||||
<main className="history-container">
|
||||
<div className="calendar-card">
|
||||
<div className="calendar-header">
|
||||
<h2 className="calendar-month">{monthName}</h2>
|
||||
<div className="calendar-nav">
|
||||
<button type="button" onClick={previousMonth} className="calendar-nav-btn" title="Previous month">
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<polyline points="15 18 9 12 15 6"></polyline>
|
||||
</svg>
|
||||
</button>
|
||||
<button type="button" onClick={nextMonth} className="calendar-nav-btn" title="Next month">
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<polyline points="9 18 15 12 9 6"></polyline>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="calendar-grid">
|
||||
<div className="calendar-weekday">S</div>
|
||||
<div className="calendar-weekday">M</div>
|
||||
<div className="calendar-weekday">T</div>
|
||||
<div className="calendar-weekday">W</div>
|
||||
<div className="calendar-weekday">T</div>
|
||||
<div className="calendar-weekday">F</div>
|
||||
<div className="calendar-weekday">S</div>
|
||||
|
||||
{Array.from({ length: startingDayOfWeek }).map((_, i) => (
|
||||
<div key={`empty-${i}`} className="calendar-day calendar-day-empty"></div>
|
||||
))}
|
||||
|
||||
{Array.from({ length: daysInMonth }).map((_, i) => {
|
||||
const day = i + 1
|
||||
const hasEntry = hasEntryOnDate(day)
|
||||
const isTodayDate = isToday(day)
|
||||
|
||||
return (
|
||||
<button
|
||||
key={day}
|
||||
type="button"
|
||||
className={`calendar-day ${hasEntry ? 'calendar-day-has-entry' : ''} ${isTodayDate ? 'calendar-day-today' : ''}`}
|
||||
onClick={() => console.log('View entries for', day)}
|
||||
>
|
||||
{day}
|
||||
</button>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section className="recent-entries">
|
||||
<h3 className="recent-entries-title">RECENT ENTRIES</h3>
|
||||
|
||||
<div className="entries-list">
|
||||
{mockEntries.map(entry => (
|
||||
<button
|
||||
key={entry.id}
|
||||
type="button"
|
||||
className="entry-card"
|
||||
onClick={() => console.log('Open entry', entry.id)}
|
||||
>
|
||||
<div className="entry-header">
|
||||
<span className="entry-date">{formatDate(entry.date)}</span>
|
||||
<span className="entry-time">{formatTime(entry.date)}</span>
|
||||
</div>
|
||||
<h4 className="entry-title">{entry.title}</h4>
|
||||
<p className="entry-preview">{entry.content}</p>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<BottomNav />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,8 +1,12 @@
|
||||
import { useAuth } from '../contexts/AuthContext'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { useState } from 'react'
|
||||
import BottomNav from '../components/BottomNav'
|
||||
|
||||
export default function HomePage() {
|
||||
const { user, loading, signOut } = useAuth()
|
||||
const [entry, setEntry] = useState('')
|
||||
const [title, setTitle] = useState('')
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
@@ -24,11 +28,32 @@ export default function HomePage() {
|
||||
)
|
||||
}
|
||||
|
||||
const displayName =
|
||||
user.displayName ?? user.email ?? 'there'
|
||||
const displayName = user.displayName ?? user.email ?? 'there'
|
||||
|
||||
// Get current date formatted like "THURSDAY, OCT 24"
|
||||
const today = new Date()
|
||||
const dateString = today.toLocaleDateString('en-US', {
|
||||
weekday: 'long',
|
||||
month: 'short',
|
||||
day: 'numeric'
|
||||
}).toUpperCase()
|
||||
|
||||
const handleWrite = () => {
|
||||
console.log('Saving entry:', { title, entry })
|
||||
// TODO: Save to Firebase
|
||||
setTitle('')
|
||||
setEntry('')
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="home-page">
|
||||
<div className="home-bg-decoration">
|
||||
<div className="bg-orb bg-orb-1"></div>
|
||||
<div className="bg-orb bg-orb-2"></div>
|
||||
<div className="bg-orb bg-orb-3"></div>
|
||||
<div className="bg-pattern"></div>
|
||||
</div>
|
||||
|
||||
<header className="home-header">
|
||||
<h1>Grateful Journal</h1>
|
||||
<div className="home-user">
|
||||
@@ -38,10 +63,32 @@ export default function HomePage() {
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
<main className="home-main">
|
||||
<p className="home-welcome">Hello, {displayName}.</p>
|
||||
<p className="home-sub">Your writing space will go here.</p>
|
||||
|
||||
<main className="journal-container">
|
||||
<div className="journal-card">
|
||||
<div className="journal-date">{dateString}</div>
|
||||
|
||||
<h2 className="journal-prompt">What are you grateful for today?</h2>
|
||||
|
||||
<div className="journal-writing-area">
|
||||
<input
|
||||
type="text"
|
||||
className="journal-title-input"
|
||||
placeholder="Title your thoughts..."
|
||||
value={title}
|
||||
onChange={(e) => setTitle(e.target.value)}
|
||||
/>
|
||||
<textarea
|
||||
className="journal-entry-textarea"
|
||||
placeholder=""
|
||||
value={entry}
|
||||
onChange={(e) => setEntry(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<BottomNav />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
172
src/pages/SettingsPage.tsx
Normal file
172
src/pages/SettingsPage.tsx
Normal file
@@ -0,0 +1,172 @@
|
||||
import { useState } from 'react'
|
||||
import { useAuth } from '../contexts/AuthContext'
|
||||
import BottomNav from '../components/BottomNav'
|
||||
|
||||
export default function SettingsPage() {
|
||||
const { user, signOut } = useAuth()
|
||||
const [passcodeEnabled, setPasscodeEnabled] = useState(false)
|
||||
const [faceIdEnabled, setFaceIdEnabled] = useState(false)
|
||||
|
||||
const displayName = user?.displayName || 'User'
|
||||
const photoURL = user?.photoURL || ''
|
||||
|
||||
const handleClearData = () => {
|
||||
if (window.confirm('Are you sure you want to clear all local data? This action cannot be undone.')) {
|
||||
// TODO: Implement clear local data
|
||||
console.log('Clearing local data...')
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="settings-page">
|
||||
<div className="settings-bg-decoration">
|
||||
<div className="bg-orb bg-orb-1"></div>
|
||||
<div className="bg-orb bg-orb-2"></div>
|
||||
<div className="bg-pattern"></div>
|
||||
</div>
|
||||
|
||||
<header className="settings-header">
|
||||
<div className="settings-header-text">
|
||||
<h1>Settings</h1>
|
||||
<p className="settings-subtitle">Manage your privacy and preferences.</p>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main className="settings-container">
|
||||
{/* Profile Section */}
|
||||
<div className="settings-profile">
|
||||
<div className="settings-avatar">
|
||||
{photoURL ? (
|
||||
<img src={photoURL} alt={displayName} className="settings-avatar-img" />
|
||||
) : (
|
||||
<div className="settings-avatar-placeholder">
|
||||
{displayName.charAt(0).toUpperCase()}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="settings-profile-info">
|
||||
<h2 className="settings-profile-name">{displayName}</h2>
|
||||
<span className="settings-profile-badge">PRO MEMBER</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Privacy & Security */}
|
||||
<section className="settings-section">
|
||||
<h3 className="settings-section-title">PRIVACY & SECURITY</h3>
|
||||
<div className="settings-card">
|
||||
<div className="settings-item">
|
||||
<div className="settings-item-icon settings-item-icon-green">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect>
|
||||
<path d="M7 11V7a5 5 0 0 1 10 0v4"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<div className="settings-item-content">
|
||||
<h4 className="settings-item-title">Passcode Lock</h4>
|
||||
<p className="settings-item-subtitle">Secure your entries</p>
|
||||
</div>
|
||||
<label className="settings-toggle">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={passcodeEnabled}
|
||||
onChange={(e) => setPasscodeEnabled(e.target.checked)}
|
||||
/>
|
||||
<span className="settings-toggle-slider"></span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div className="settings-divider"></div>
|
||||
|
||||
<div className="settings-item">
|
||||
<div className="settings-item-icon settings-item-icon-gray">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<path d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10 10-4.5 10-10S17.5 2 12 2z"></path>
|
||||
<path d="M12 6v6l4 2"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<div className="settings-item-content">
|
||||
<h4 className="settings-item-title">Face ID</h4>
|
||||
<p className="settings-item-subtitle">Unlock with glance</p>
|
||||
</div>
|
||||
<label className="settings-toggle">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={faceIdEnabled}
|
||||
onChange={(e) => setFaceIdEnabled(e.target.checked)}
|
||||
/>
|
||||
<span className="settings-toggle-slider"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Data & Look */}
|
||||
<section className="settings-section">
|
||||
<h3 className="settings-section-title">DATA & LOOK</h3>
|
||||
<div className="settings-card">
|
||||
<button type="button" className="settings-item settings-item-button">
|
||||
<div className="settings-item-icon settings-item-icon-orange">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
|
||||
<polyline points="7 10 12 15 17 10"></polyline>
|
||||
<line x1="12" y1="15" x2="12" y2="3"></line>
|
||||
</svg>
|
||||
</div>
|
||||
<div className="settings-item-content">
|
||||
<h4 className="settings-item-title">Export Journal</h4>
|
||||
<p className="settings-item-subtitle">PDF or Plain Text</p>
|
||||
</div>
|
||||
<svg className="settings-item-arrow" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<polyline points="9 18 15 12 9 6"></polyline>
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<div className="settings-divider"></div>
|
||||
|
||||
<button type="button" className="settings-item settings-item-button">
|
||||
<div className="settings-item-icon settings-item-icon-blue">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<circle cx="13.5" cy="6.5" r=".5"></circle>
|
||||
<circle cx="17.5" cy="10.5" r=".5"></circle>
|
||||
<circle cx="8.5" cy="7.5" r=".5"></circle>
|
||||
<circle cx="6.5" cy="12.5" r=".5"></circle>
|
||||
<path d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10c.926 0 1.648-.746 1.648-1.688 0-.437-.18-.835-.437-1.125-.29-.289-.438-.652-.438-1.125a1.64 1.64 0 0 1 1.668-1.668h1.996c3.051 0 5.555-2.503 5.555-5.554C21.965 6.012 17.461 2 12 2z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<div className="settings-item-content">
|
||||
<h4 className="settings-item-title">Theme</h4>
|
||||
<p className="settings-item-subtitle">Currently: Warm Beige</p>
|
||||
</div>
|
||||
<div className="settings-theme-colors">
|
||||
<span className="settings-theme-dot settings-theme-dot-beige"></span>
|
||||
<span className="settings-theme-dot settings-theme-dot-dark"></span>
|
||||
</div>
|
||||
<svg className="settings-item-arrow" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<polyline points="9 18 15 12 9 6"></polyline>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Clear Data */}
|
||||
<button type="button" className="settings-clear-btn" onClick={handleClearData}>
|
||||
<span>Clear Local Data</span>
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<polyline points="3 6 5 6 21 6"></polyline>
|
||||
<path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path>
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
{/* Sign Out */}
|
||||
<button type="button" className="settings-signout-btn" onClick={() => signOut()}>
|
||||
Sign Out
|
||||
</button>
|
||||
|
||||
{/* Version */}
|
||||
<p className="settings-version">VERSION 1.0.2</p>
|
||||
</main>
|
||||
|
||||
<BottomNav />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user