Added settings, enabled calendar

This commit is contained in:
dohsimpson
2024-12-31 13:58:14 -05:00
parent c4f0db329b
commit 7195f0d1f2
18 changed files with 493 additions and 137 deletions

View File

@@ -2,9 +2,21 @@
import fs from 'fs/promises'
import path from 'path'
import { HabitsData, CoinsData, CoinTransaction, TransactionType, WishlistItemType } from '@/lib/types'
import {
HabitsData,
CoinsData,
CoinTransaction,
TransactionType,
WishlistItemType,
WishlistData,
Settings,
DataType,
DATA_DEFAULTS
} from '@/lib/types'
type DataType = 'wishlist' | 'habits' | 'coins'
function getDefaultData<T>(type: DataType): T {
return DATA_DEFAULTS[type]() as T;
}
async function ensureDataDir() {
const dataDir = path.join(process.cwd(), 'data')
@@ -23,13 +35,8 @@ async function loadData<T>(type: DataType): Promise<T> {
try {
await fs.access(filePath)
} catch {
// File doesn't exist, create it with initial data
const initialData = type === 'wishlist'
? { items: [] }
: type === 'habits'
? { habits: [] }
: { balance: 0, transactions: [] }
// File doesn't exist, create it with default data
const initialData = getDefaultData(type)
await fs.writeFile(filePath, JSON.stringify(initialData, null, 2))
return initialData as T
}
@@ -37,13 +44,10 @@ async function loadData<T>(type: DataType): Promise<T> {
// File exists, read and return its contents
const data = await fs.readFile(filePath, 'utf8')
const jsonData = JSON.parse(data)
return type === 'wishlist' ? jsonData.items : jsonData
return jsonData
} catch (error) {
console.error(`Error loading ${type} data:`, error)
if (type === 'wishlist') return [] as T
if (type === 'habits') return { habits: [] } as T
if (type === 'coins') return { balance: 0, transactions: [] } as T
return {} as T
return getDefaultData<T>(type)
}
}
@@ -51,7 +55,7 @@ async function saveData<T>(type: DataType, data: T): Promise<void> {
try {
await ensureDataDir()
const filePath = path.join(process.cwd(), 'data', `${type}.json`)
const saveData = type === 'wishlist' ? { items: data } : data
const saveData = data
await fs.writeFile(filePath, JSON.stringify(saveData, null, 2))
} catch (error) {
console.error(`Error saving ${type} data:`, error)
@@ -60,11 +64,12 @@ async function saveData<T>(type: DataType, data: T): Promise<void> {
// Wishlist specific functions
export async function loadWishlistItems(): Promise<WishlistItemType[]> {
return loadData<WishlistItemType[]>('wishlist')
const data = await loadData<WishlistData>('wishlist')
return data.items
}
export async function saveWishlistItems(items: WishlistItemType[]): Promise<void> {
return saveData('wishlist', items)
return saveData('wishlist', { items })
}
// Habits specific functions
@@ -114,6 +119,26 @@ export async function addCoins(
return newData
}
export async function loadSettings(): Promise<Settings> {
const defaultSettings: Settings = {
ui: {
useNumberFormatting: true,
useGrouping: true,
}
}
try {
const data = await loadData<Settings>('settings')
return { ...defaultSettings, ...data }
} catch {
return defaultSettings
}
}
export async function saveSettings(settings: Settings): Promise<void> {
return saveData('settings', settings)
}
export async function removeCoins(
amount: number,
description: string,

9
app/settings/layout.tsx Normal file
View File

@@ -0,0 +1,9 @@
import Layout from '@/components/Layout'
export default function SettingsLayout({
children,
}: {
children: React.ReactNode
}) {
return <Layout>{children}</Layout>
}

63
app/settings/page.tsx Normal file
View File

@@ -0,0 +1,63 @@
'use client'
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
import { Switch } from '@/components/ui/switch'
import { Label } from '@/components/ui/label'
import { useSettings } from '@/hooks/useSettings'
export default function SettingsPage() {
const { settings, updateSettings } = useSettings()
if (!settings) return null
return (
<div className="container mx-auto px-4 py-8">
<h1 className="text-3xl font-bold mb-6">Settings</h1>
<Card className="mb-6">
<CardHeader>
<CardTitle>UI Settings</CardTitle>
</CardHeader>
<CardContent className="space-y-6">
<div className="flex items-center justify-between">
<div className="space-y-0.5">
<Label htmlFor="number-formatting">Number Formatting</Label>
<div className="text-sm text-muted-foreground">
Format large numbers (e.g., 1K, 1M, 1B)
</div>
</div>
<Switch
id="number-formatting"
checked={settings.ui.useNumberFormatting}
onCheckedChange={(checked) =>
updateSettings({
...settings,
ui: { ...settings.ui, useNumberFormatting: checked }
})
}
/>
</div>
<div className="flex items-center justify-between">
<div className="space-y-0.5">
<Label htmlFor="number-grouping">Number Grouping</Label>
<div className="text-sm text-muted-foreground">
Use thousand separators (e.g., 1,000 vs 1000)
</div>
</div>
<Switch
id="number-grouping"
checked={settings.ui.useGrouping}
onCheckedChange={(checked) =>
updateSettings({
...settings,
ui: { ...settings.ui, useGrouping: checked }
})
}
/>
</div>
</CardContent>
</Card>
</div>
)
}