normalize project structure: src/client + src/server + src/shared, standardize biome to lineWidth 80
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
import { getDb } from "@/shared/db/client"
|
||||
import { useCallback } from "react"
|
||||
|
||||
export function useDataManagement() {
|
||||
const exportData = useCallback(async () => {
|
||||
const db = await getDb()
|
||||
const games = await db.query("SELECT * FROM games")
|
||||
const playlists = await db.query("SELECT * FROM playlists")
|
||||
const playlistGames = await db.query("SELECT * FROM playlist_games")
|
||||
const config = await db.query("SELECT * FROM config")
|
||||
|
||||
const data = {
|
||||
version: "2026.03.01",
|
||||
exportedAt: new Date().toISOString(),
|
||||
games: games.rows,
|
||||
playlists: playlists.rows,
|
||||
playlistGames: playlistGames.rows,
|
||||
config: config.rows,
|
||||
}
|
||||
|
||||
const blob = new Blob([JSON.stringify(data, null, 2)], {
|
||||
type: "application/json",
|
||||
})
|
||||
const url = URL.createObjectURL(blob)
|
||||
const a = document.createElement("a")
|
||||
a.href = url
|
||||
a.download = `whattoplay-export-${new Date().toISOString().slice(0, 10)}.json`
|
||||
a.click()
|
||||
URL.revokeObjectURL(url)
|
||||
}, [])
|
||||
|
||||
const importData = useCallback(async (file: File) => {
|
||||
const text = await file.text()
|
||||
const data = JSON.parse(text)
|
||||
const db = await getDb()
|
||||
|
||||
if (data.games) {
|
||||
for (const game of data.games) {
|
||||
await db.query(
|
||||
`INSERT INTO games (id, title, source, source_id, platform, last_played, playtime_hours, url, canonical_id, rating, game_state, is_favorite)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)
|
||||
ON CONFLICT (id) DO UPDATE SET
|
||||
title = $2, last_played = $6, playtime_hours = $7, url = $8, canonical_id = $9,
|
||||
rating = $10, game_state = $11, is_favorite = $12, updated_at = NOW()`,
|
||||
[
|
||||
game.id,
|
||||
game.title,
|
||||
game.source,
|
||||
game.source_id,
|
||||
game.platform,
|
||||
game.last_played,
|
||||
game.playtime_hours,
|
||||
game.url,
|
||||
game.canonical_id,
|
||||
game.rating ?? -1,
|
||||
game.game_state ?? "not_set",
|
||||
game.is_favorite ?? false,
|
||||
],
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (data.playlists) {
|
||||
for (const pl of data.playlists) {
|
||||
await db.query(
|
||||
"INSERT INTO playlists (id, name, is_static) VALUES ($1, $2, $3) ON CONFLICT (id) DO NOTHING",
|
||||
[pl.id, pl.name, pl.is_static],
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (data.playlistGames) {
|
||||
for (const pg of data.playlistGames) {
|
||||
await db.query(
|
||||
"INSERT INTO playlist_games (playlist_id, game_id) VALUES ($1, $2) ON CONFLICT DO NOTHING",
|
||||
[pg.playlist_id, pg.game_id],
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (data.config) {
|
||||
for (const cfg of data.config) {
|
||||
await db.query(
|
||||
`INSERT INTO config (key, value, updated_at) VALUES ($1, $2, NOW())
|
||||
ON CONFLICT (key) DO UPDATE SET value = $2, updated_at = NOW()`,
|
||||
[cfg.key, JSON.stringify(cfg.value)],
|
||||
)
|
||||
}
|
||||
}
|
||||
}, [])
|
||||
|
||||
const clearAll = useCallback(async () => {
|
||||
const db = await getDb()
|
||||
await db.query("DELETE FROM playlist_games")
|
||||
await db.query("DELETE FROM games")
|
||||
await db.query("DELETE FROM playlists WHERE is_static = FALSE")
|
||||
await db.query("DELETE FROM config")
|
||||
}, [])
|
||||
|
||||
return { exportData, importData, clearAll }
|
||||
}
|
||||
Reference in New Issue
Block a user