@@ -27,3 +27,22 @@ export async function sendJSON(url: string, data: any): Promise<Result<any, stri
|
||||
return { status: 'error', value: e!.toString() }
|
||||
}
|
||||
}
|
||||
|
||||
export async function sendDelete(url: string): Promise<Result<any, string>> {
|
||||
try {
|
||||
const res = await fetch(url, {
|
||||
method: 'DELETE',
|
||||
credentials: 'include',
|
||||
})
|
||||
|
||||
if (!res.ok) {
|
||||
console.error(res)
|
||||
return { status: 'error', value: await res.text() }
|
||||
}
|
||||
|
||||
return { status: 'ok', value: await res.json() }
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
return { status: 'error', value: e!.toString() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ const ActionCardAnswer = ({ action, ...props }: { action: ActionAnswer } & Actio
|
||||
<div class="stack-h center gap-sm">
|
||||
<div class="icon">schedule</div>
|
||||
<div class="text dimmed">
|
||||
{action.timestamp && format(new Date(action.timestamp), 'dd/MM/yyyy HH:mm:ss')}
|
||||
{action.timestamp && format(new Date(action.timestamp), 'HH:mm:ss')}
|
||||
<span class="text smaller">
|
||||
{action.timestamp && ' ' + format(new Date(action.timestamp), 'SSS')}
|
||||
</span>
|
||||
@@ -79,7 +79,7 @@ const ActionCardJolly = ({ action, ...props }: { action: ActionJolly } & ActionC
|
||||
<div class="stack-h center gap-sm">
|
||||
<div class="icon">schedule</div>
|
||||
<div class="text dimmed">
|
||||
{action.timestamp && format(new Date(action.timestamp), 'dd/MM/yyyy HH:mm:ss')}
|
||||
{action.timestamp && format(new Date(action.timestamp), 'HH:mm:ss')}
|
||||
<span class="text smaller">
|
||||
{action.timestamp && ' ' + format(new Date(action.timestamp), 'SSS')}
|
||||
</span>
|
||||
|
||||
@@ -2,7 +2,7 @@ import { SubmitAction } from '@/components/SubmitAction'
|
||||
import { ActionRegistry } from '@/components/ActionRegistry'
|
||||
import { useEffect, useRef, useState } from 'preact/hooks'
|
||||
import type { Room } from '@/db/model'
|
||||
import { requestJSON } from '@/client/utils'
|
||||
import { requestJSON, sendDelete, sendJSON } from '@/client/utils'
|
||||
import { computeScoreboardState } from '@/ggwp'
|
||||
import { Leaderboard } from './Leaderboard'
|
||||
|
||||
@@ -86,6 +86,23 @@ export const AdminPage = ({ roomId }: { roomId: string }) => {
|
||||
/>
|
||||
<h2>Registro Azioni</h2>
|
||||
<ActionRegistry room={room} refreshRoom={fetchRoom} />
|
||||
<h2>Zona Pericolosa</h2>
|
||||
<div class="card tint-red stack-v center">
|
||||
<button
|
||||
onClick={async () => {
|
||||
const answer = confirm('Sei sicuro di voler eliminare la stanza?')
|
||||
if (!answer) {
|
||||
return
|
||||
}
|
||||
|
||||
await sendDelete(`/api/room/${room.id}`)
|
||||
|
||||
alert('Stanza eliminata, puoi comunque continuare a visualizzare i risultati')
|
||||
}}
|
||||
>
|
||||
Elimina Stanza
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ export const SubmitActionAnswer = ({
|
||||
})
|
||||
|
||||
return (
|
||||
<div class="card tint-red stack-v center">
|
||||
<div class="card tint-green stack-v center">
|
||||
<h3>Invia Risposta</h3>
|
||||
|
||||
<select
|
||||
@@ -120,7 +120,7 @@ export const SubmitActionJolly = ({
|
||||
})
|
||||
|
||||
return (
|
||||
<div class="card tint-red stack-v center">
|
||||
<div class="card tint-gold stack-v center">
|
||||
<h3>Invia Jolly</h3>
|
||||
|
||||
<select
|
||||
|
||||
+32
-11
@@ -19,17 +19,19 @@ db.exec(`
|
||||
);
|
||||
`)
|
||||
|
||||
// db.exec(`
|
||||
// CREATE TABLE IF NOT EXISTS game_actions (
|
||||
// id INTEGER PRIMARY KEY,
|
||||
// room_id TEXT NOT NULL,
|
||||
// created_at TEXT NOT NULL,
|
||||
db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS deleted_rooms (
|
||||
id TEXT PRIMARY KEY,
|
||||
deleted_at TEXT NOT NULL
|
||||
);
|
||||
`)
|
||||
|
||||
// data TEXT NOT NULL,
|
||||
|
||||
// FOREIGN KEY (room_id) REFERENCES rooms (id)
|
||||
// );
|
||||
// `)
|
||||
db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS sessions (
|
||||
sid TEXT PRIMARY KEY,
|
||||
room_id TEXT NOT NULL
|
||||
);
|
||||
`)
|
||||
|
||||
export function databaseStatus(): string {
|
||||
return 'ok'
|
||||
@@ -66,6 +68,15 @@ export function updateRoom(id: string, data: RoomData): void {
|
||||
).run(JSON.stringify(data), id)
|
||||
}
|
||||
|
||||
export function deleteRoom(id: string): void {
|
||||
db.prepare<[string, string]>(
|
||||
`
|
||||
INSERT INTO deleted_rooms (id, deleted_at)
|
||||
VALUES (?, ?);
|
||||
`
|
||||
).run(id, new Date().toISOString())
|
||||
}
|
||||
|
||||
export function getRoom(id: string): RoomData | null {
|
||||
const row = db
|
||||
.prepare<
|
||||
@@ -77,6 +88,9 @@ export function getRoom(id: string): RoomData | null {
|
||||
}
|
||||
>('SELECT * FROM rooms WHERE id = ?')
|
||||
.get(id)
|
||||
|
||||
console.log(row)
|
||||
|
||||
if (!row) {
|
||||
return null
|
||||
}
|
||||
@@ -108,7 +122,14 @@ export function getRooms(): Room[] {
|
||||
id: string
|
||||
data: string
|
||||
}
|
||||
>('SELECT id, data FROM rooms')
|
||||
>(
|
||||
`
|
||||
SELECT rooms.id, rooms.data
|
||||
FROM rooms
|
||||
LEFT JOIN deleted_rooms ON rooms.id = deleted_rooms.id
|
||||
WHERE deleted_rooms.id IS NULL
|
||||
`
|
||||
)
|
||||
.all()
|
||||
|
||||
return rows.map(row => ({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { getRoom, updateRoom } from '@/db'
|
||||
import { deleteRoom, getRoom, updateRoom } from '@/db'
|
||||
import { addRoomUpdateListener, removeRoomUpdateListener } from '@/db/events'
|
||||
import type { RoomData } from '@/db/model'
|
||||
import { getSession } from '@/db/sessions'
|
||||
@@ -88,3 +88,32 @@ export const POST: APIRoute = async ({ params, request, cookies }) => {
|
||||
headers: { 'content-type': 'application/json' },
|
||||
})
|
||||
}
|
||||
|
||||
export const DELETE: APIRoute = async ({ params, cookies }) => {
|
||||
const { id: roomId } = params
|
||||
if (!roomId) {
|
||||
return new Response('Invalid room id', { status: 400 })
|
||||
}
|
||||
|
||||
const room = getRoom(roomId)
|
||||
if (!room) {
|
||||
return new Response('Room not found', { status: 404 })
|
||||
}
|
||||
|
||||
// check auth
|
||||
const sid = cookies.get('sid')
|
||||
if (!sid) {
|
||||
return new Response('Unauthorized', { status: 401 })
|
||||
}
|
||||
|
||||
const sessionRoom = getSession(sid.value)
|
||||
if (sessionRoom !== roomId) {
|
||||
return new Response('Unauthorized', { status: 401 })
|
||||
}
|
||||
|
||||
deleteRoom(roomId)
|
||||
|
||||
return new Response(JSON.stringify('ok'), {
|
||||
headers: { 'content-type': 'application/json' },
|
||||
})
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ img {
|
||||
--red: oklch(63.11% 0.2387 32.0573);
|
||||
--green: oklch(60.3% 0.3 134.48);
|
||||
--orange: oklch(76.96% 0.1692 67.6368);
|
||||
--gold: oklch(from royalblue calc(l + 0.1) calc(c - 0.025) 90);
|
||||
}
|
||||
|
||||
body {
|
||||
@@ -169,6 +170,10 @@ a {
|
||||
--tint: var(--orange);
|
||||
}
|
||||
|
||||
.tint-gold {
|
||||
--tint: var(--gold);
|
||||
}
|
||||
|
||||
.stack-v {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
Reference in New Issue
Block a user