102 lines
2.9 KiB
TypeScript
102 lines
2.9 KiB
TypeScript
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 }
|
|
}
|