mirror of
https://github.com/ManInDark/HabitTrove.git
synced 2026-01-21 06:34:30 +01:00
fix: add TS types
This commit is contained in:
@@ -76,7 +76,7 @@ async function loadData<T>(type: DataType): Promise<T> {
|
|||||||
await fs.access(filePath)
|
await fs.access(filePath)
|
||||||
} catch {
|
} catch {
|
||||||
// File doesn't exist, create it with default data
|
// File doesn't exist, create it with default data
|
||||||
const initialData = getDefaultData(type)
|
const initialData = getDefaultData<T>(type)
|
||||||
await fs.writeFile(filePath, JSON.stringify(initialData, null, 2))
|
await fs.writeFile(filePath, JSON.stringify(initialData, null, 2))
|
||||||
return initialData as T
|
return initialData as T
|
||||||
}
|
}
|
||||||
@@ -136,7 +136,7 @@ async function calculateServerFreshnessToken(): Promise<string | null> {
|
|||||||
// Wishlist specific functions
|
// Wishlist specific functions
|
||||||
export async function loadWishlistData(): Promise<WishlistData> {
|
export async function loadWishlistData(): Promise<WishlistData> {
|
||||||
const user = await getCurrentUser()
|
const user = await getCurrentUser()
|
||||||
if (!user) return getDefaultWishlistData()
|
if (!user) return getDefaultWishlistData<WishlistData>()
|
||||||
|
|
||||||
const data = await loadData<WishlistData>('wishlist')
|
const data = await loadData<WishlistData>('wishlist')
|
||||||
return {
|
return {
|
||||||
@@ -173,7 +173,7 @@ export async function saveWishlistItems(data: WishlistData): Promise<void> {
|
|||||||
// Habits specific functions
|
// Habits specific functions
|
||||||
export async function loadHabitsData(): Promise<HabitsData> {
|
export async function loadHabitsData(): Promise<HabitsData> {
|
||||||
const user = await getCurrentUser()
|
const user = await getCurrentUser()
|
||||||
if (!user) return getDefaultHabitsData()
|
if (!user) return getDefaultHabitsData<HabitsData>()
|
||||||
const data = await loadData<HabitsData>('habits')
|
const data = await loadData<HabitsData>('habits')
|
||||||
return {
|
return {
|
||||||
habits: data.habits.filter(x => user.isAdmin || x.userIds?.includes(user.id))
|
habits: data.habits.filter(x => user.isAdmin || x.userIds?.includes(user.id))
|
||||||
@@ -208,14 +208,14 @@ export async function saveHabitsData(data: HabitsData): Promise<void> {
|
|||||||
export async function loadCoinsData(): Promise<CoinsData> {
|
export async function loadCoinsData(): Promise<CoinsData> {
|
||||||
try {
|
try {
|
||||||
const user = await getCurrentUser()
|
const user = await getCurrentUser()
|
||||||
if (!user) return getDefaultCoinsData()
|
if (!user) return getDefaultCoinsData<CoinsData>()
|
||||||
const data = await loadData<CoinsData>('coins')
|
const data = await loadData<CoinsData>('coins')
|
||||||
return {
|
return {
|
||||||
...data,
|
...data,
|
||||||
transactions: user.isAdmin ? data.transactions : data.transactions.filter(x => x.userId === user.id)
|
transactions: user.isAdmin ? data.transactions : data.transactions.filter(x => x.userId === user.id)
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
return getDefaultCoinsData()
|
return getDefaultCoinsData<CoinsData>()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -278,7 +278,7 @@ export async function addCoins({
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function loadSettings(): Promise<Settings> {
|
export async function loadSettings(): Promise<Settings> {
|
||||||
const defaultSettings = getDefaultSettings()
|
const defaultSettings = getDefaultSettings<Settings>()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const user = await getCurrentUser()
|
const user = await getCurrentUser()
|
||||||
@@ -370,7 +370,7 @@ export async function loadUsersData(): Promise<UserData> {
|
|||||||
try {
|
try {
|
||||||
return await loadData<UserData>('auth')
|
return await loadData<UserData>('auth')
|
||||||
} catch {
|
} catch {
|
||||||
return getDefaultUsersData()
|
return getDefaultUsersData<UserData>()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
20
lib/atoms.ts
20
lib/atoms.ts
@@ -16,6 +16,7 @@ import { atom } from "jotai";
|
|||||||
import { atomFamily, atomWithStorage } from "jotai/utils";
|
import { atomFamily, atomWithStorage } from "jotai/utils";
|
||||||
import { DateTime } from "luxon";
|
import { DateTime } from "luxon";
|
||||||
import {
|
import {
|
||||||
|
CoinsData,
|
||||||
CompletionCache,
|
CompletionCache,
|
||||||
Freq,
|
Freq,
|
||||||
getDefaultCoinsData,
|
getDefaultCoinsData,
|
||||||
@@ -25,7 +26,12 @@ import {
|
|||||||
getDefaultUsersData,
|
getDefaultUsersData,
|
||||||
getDefaultWishlistData,
|
getDefaultWishlistData,
|
||||||
Habit,
|
Habit,
|
||||||
UserId
|
HabitsData,
|
||||||
|
ServerSettings,
|
||||||
|
Settings,
|
||||||
|
UserData,
|
||||||
|
UserId,
|
||||||
|
WishlistData
|
||||||
} from "./types";
|
} from "./types";
|
||||||
|
|
||||||
export interface BrowserSettings {
|
export interface BrowserSettings {
|
||||||
@@ -40,12 +46,12 @@ export const browserSettingsAtom = atomWithStorage('browserSettings', {
|
|||||||
expandedWishlist: false
|
expandedWishlist: false
|
||||||
} as BrowserSettings)
|
} as BrowserSettings)
|
||||||
|
|
||||||
export const usersAtom = atom(getDefaultUsersData())
|
export const usersAtom = atom(getDefaultUsersData<UserData>())
|
||||||
export const settingsAtom = atom(getDefaultSettings());
|
export const settingsAtom = atom(getDefaultSettings<Settings>());
|
||||||
export const habitsAtom = atom(getDefaultHabitsData());
|
export const habitsAtom = atom(getDefaultHabitsData<HabitsData>());
|
||||||
export const coinsAtom = atom(getDefaultCoinsData());
|
export const coinsAtom = atom(getDefaultCoinsData<CoinsData>());
|
||||||
export const wishlistAtom = atom(getDefaultWishlistData());
|
export const wishlistAtom = atom(getDefaultWishlistData<WishlistData>());
|
||||||
export const serverSettingsAtom = atom(getDefaultServerSettings());
|
export const serverSettingsAtom = atom(getDefaultServerSettings<ServerSettings>());
|
||||||
|
|
||||||
// Derived atom for coins earned today
|
// Derived atom for coins earned today
|
||||||
export const coinsEarnedTodayAtom = atom((get) => {
|
export const coinsEarnedTodayAtom = atom((get) => {
|
||||||
|
|||||||
82
lib/types.ts
82
lib/types.ts
@@ -96,52 +96,58 @@ export interface WishlistData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Default value functions
|
// Default value functions
|
||||||
export const getDefaultUsersData = (): UserData => ({
|
export function getDefaultUsersData<UserData>(): UserData {
|
||||||
users: [
|
return {
|
||||||
{
|
users: [
|
||||||
id: crypto.randomUUID(),
|
{
|
||||||
username: 'admin',
|
id: crypto.randomUUID(),
|
||||||
// password: '', // No default password for admin initially? Or set a secure default?
|
username: 'admin',
|
||||||
isAdmin: true,
|
// password: '', // No default password for admin initially? Or set a secure default?
|
||||||
lastNotificationReadTimestamp: undefined, // Initialize as undefined
|
isAdmin: true,
|
||||||
}
|
lastNotificationReadTimestamp: undefined, // Initialize as undefined
|
||||||
]
|
}
|
||||||
});
|
]
|
||||||
|
} as UserData;
|
||||||
|
};
|
||||||
|
|
||||||
export const getDefaultHabitsData = (): HabitsData => ({
|
export function getDefaultHabitsData<HabitsData>(): HabitsData {
|
||||||
habits: []
|
return { habits: [] } as HabitsData;
|
||||||
});
|
}
|
||||||
|
|
||||||
|
export function getDefaultTasksData<TasksData>(): TasksData {
|
||||||
|
return { tasks: [] } as TasksData;
|
||||||
|
};
|
||||||
|
|
||||||
export const getDefaultCoinsData = (): CoinsData => ({
|
export function getDefaultCoinsData<CoinsData>(): CoinsData {
|
||||||
balance: 0,
|
return { balance: 0, transactions: [] } as CoinsData;
|
||||||
transactions: []
|
};
|
||||||
});
|
|
||||||
|
|
||||||
export const getDefaultWishlistData = (): WishlistData => ({
|
export function getDefaultWishlistData<WishlistData>(): WishlistData {
|
||||||
items: []
|
return { items: [] } as WishlistData;
|
||||||
});
|
}
|
||||||
|
|
||||||
export const getDefaultSettings = (): Settings => ({
|
export function getDefaultSettings<Settings>(): Settings {
|
||||||
ui: {
|
return {
|
||||||
useNumberFormatting: true,
|
ui: {
|
||||||
useGrouping: true,
|
useNumberFormatting: true,
|
||||||
},
|
useGrouping: true,
|
||||||
system: {
|
},
|
||||||
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
system: {
|
||||||
weekStartDay: 1, // Monday
|
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
||||||
autoBackupEnabled: true, // Add this line (default to true)
|
weekStartDay: 1, // Monday
|
||||||
language: 'en', // Default language
|
autoBackupEnabled: true, // Add this line (default to true)
|
||||||
},
|
language: 'en', // Default language
|
||||||
profile: {}
|
},
|
||||||
});
|
profile: {}
|
||||||
|
} as Settings;
|
||||||
|
};
|
||||||
|
|
||||||
export const getDefaultServerSettings = (): ServerSettings => ({
|
export function getDefaultServerSettings<ServerSettings>(): ServerSettings {
|
||||||
isDemo: false
|
return { isDemo: false } as ServerSettings;
|
||||||
})
|
}
|
||||||
|
|
||||||
// Map of data types to their default values
|
// Map of data types to their default values
|
||||||
export const DATA_DEFAULTS = {
|
export const DATA_DEFAULTS: { [key: string]: <T>() => T } = {
|
||||||
wishlist: getDefaultWishlistData,
|
wishlist: getDefaultWishlistData,
|
||||||
habits: getDefaultHabitsData,
|
habits: getDefaultHabitsData,
|
||||||
coins: getDefaultCoinsData,
|
coins: getDefaultCoinsData,
|
||||||
|
|||||||
@@ -942,11 +942,11 @@ describe('convertMachineReadableFrequencyToHumanReadable', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('freshness utilities', () => {
|
describe('freshness utilities', () => {
|
||||||
const mockSettings: Settings = getDefaultSettings();
|
const mockSettings: Settings = getDefaultSettings<Settings>();
|
||||||
const mockHabits: HabitsData = getDefaultHabitsData();
|
const mockHabits: HabitsData = getDefaultHabitsData<HabitsData>();
|
||||||
const mockCoins: CoinsData = getDefaultCoinsData();
|
const mockCoins: CoinsData = getDefaultCoinsData<CoinsData>();
|
||||||
const mockWishlist: WishlistData = getDefaultWishlistData();
|
const mockWishlist: WishlistData = getDefaultWishlistData<WishlistData>();
|
||||||
const mockUsers: UserData = getDefaultUsersData();
|
const mockUsers: UserData = getDefaultUsersData<UserData>();
|
||||||
|
|
||||||
// Add a user to mockUsers for more realistic testing
|
// Add a user to mockUsers for more realistic testing
|
||||||
mockUsers.users.push({
|
mockUsers.users.push({
|
||||||
@@ -991,11 +991,11 @@ describe('freshness utilities', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('should handle empty data consistently', () => {
|
test('should handle empty data consistently', () => {
|
||||||
const emptySettings = getDefaultSettings();
|
const emptySettings = getDefaultSettings<Settings>();
|
||||||
const emptyHabits = getDefaultHabitsData();
|
const emptyHabits = getDefaultHabitsData<HabitsData>();
|
||||||
const emptyCoins = getDefaultCoinsData();
|
const emptyCoins = getDefaultCoinsData<CoinsData>();
|
||||||
const emptyWishlist = getDefaultWishlistData();
|
const emptyWishlist = getDefaultWishlistData<WishlistData>();
|
||||||
const emptyUsers = getDefaultUsersData();
|
const emptyUsers = getDefaultUsersData<UserData>();
|
||||||
|
|
||||||
const string1 = prepareDataForHashing(emptySettings, emptyHabits, emptyCoins, emptyWishlist, emptyUsers);
|
const string1 = prepareDataForHashing(emptySettings, emptyHabits, emptyCoins, emptyWishlist, emptyUsers);
|
||||||
const string2 = prepareDataForHashing(emptySettings, emptyHabits, emptyCoins, emptyWishlist, emptyUsers);
|
const string2 = prepareDataForHashing(emptySettings, emptyHabits, emptyCoins, emptyWishlist, emptyUsers);
|
||||||
|
|||||||
Reference in New Issue
Block a user