Checkpoint SHD dashboard design system

This commit is contained in:
JB
2026-07-24 21:31:35 -04:00
commit 5e113454ee
52 changed files with 3128 additions and 0 deletions
+59
View File
@@ -0,0 +1,59 @@
import { getSessionUser } from '$lib/server/auth/session';
import { requireAdmin } from '$lib/server/auth/authorization';
import { getDatabase } from '$lib/server/database';
import { fail } from '@sveltejs/kit';
import { randomUUID } from 'node:crypto';
import type { Actions, PageServerLoad } from './$types';
export const load: PageServerLoad = async () => {
const db = await getDatabase();
const [talents, tiers, triggers, links, effects, stats] = await Promise.all([
(await db.prepare('SELECT * FROM talents ORDER BY active DESC,name COLLATE NOCASE')).all(),
(await db.prepare('SELECT id,talent_id,tier,description FROM talent_tiers')).all(),
(await db.prepare('SELECT * FROM talent_triggers ORDER BY active DESC,name COLLATE NOCASE')).all(),
(await db.prepare('SELECT talent_tier_id,trigger_id FROM talent_tier_triggers')).all(),
(await db.prepare('SELECT talent_tier_id,stat_attribute_id,value FROM talent_tier_effects')).all(),
(await db.prepare('SELECT id,name,unit FROM stat_attributes WHERE active=1 ORDER BY name COLLATE NOCASE')).all()
]);
return { talents: talents.map((talent) => ({...talent, tiers: tiers.filter((tier) => tier.talent_id === talent.id).map((tier) => ({...tier, triggerIds: links.filter((link) => link.talent_tier_id === tier.id).map((link) => String(link.trigger_id)), effects: effects.filter((effect) => effect.talent_tier_id === tier.id)}))})), triggers, stats };
};
const parseEffects = (raw: FormDataEntryValue | null) => {
const value = JSON.parse(String(raw ?? '[]')) as Array<{statId:string;value:string|number}>;
if (!Array.isArray(value)) throw new Error();
return value.map((effect) => ({statId:String(effect.statId),value:Number(effect.value)}));
};
export const actions: Actions = {
saveTrigger: async ({request,cookies}) => {
requireAdmin(await getSessionUser(cookies)); const form=await request.formData();
const id=String(form.get('id')??''), name=String(form.get('name')??'').trim(), description=String(form.get('description')??'').trim(), uptime=form.get('supportsUptime')==='on';
const min=uptime?Number(form.get('minUptime')):null,max=uptime?Number(form.get('maxUptime')):null;
if(name.length<2||!description)return fail(400,{triggerError:'A trigger name and description are required.'});
if(uptime&&(!Number.isFinite(min)||!Number.isFinite(max)||Number(min)<0||Number(max)>100||Number(min)>Number(max)))return fail(400,{triggerError:'Uptime must be a valid 0–100% range.'});
const db=await getDatabase(); if(await(await db.prepare('SELECT id FROM talent_triggers WHERE name=? COLLATE NOCASE AND id<>?')).get(name,id||'new'))return fail(409,{triggerError:'That trigger already exists.'});
const now=new Date().toISOString();
if(id)await(await db.prepare('UPDATE talent_triggers SET name=?,description=?,supports_uptime=?,min_uptime=?,max_uptime=?,updated_at=? WHERE id=?')).run(name,description,uptime?1:0,min,max,now,id);
else await(await db.prepare('INSERT INTO talent_triggers(id,name,description,supports_uptime,min_uptime,max_uptime,created_at,updated_at) VALUES(?,?,?,?,?,?,?,?)')).run(randomUUID(),name,description,uptime?1:0,min,max,now,now);
return {triggerSaved:true};
},
saveTalent: async ({request,cookies}) => {
requireAdmin(await getSessionUser(cookies)); const form=await request.formData();
const id=String(form.get('id')??''),name=String(form.get('name')??'').trim(),category=String(form.get('category')??'');
const descriptions={I:String(form.get('tierIDescription')??'').trim(),II:String(form.get('tierIIDescription')??'').trim()};
const triggerIds={I:form.getAll('tierITriggerIds').map(String),II:form.getAll('tierIITriggerIds').map(String)};
let tierEffects:{I:Array<{statId:string;value:number}>;II:Array<{statId:string;value:number}>};
try{tierEffects={I:parseEffects(form.get('tierIEffects')),II:parseEffects(form.get('tierIIEffects'))};}catch{return fail(400,{talentError:'Effects could not be read.'});}
if(name.length<2||!['Weapon','Backpack','Vest'].includes(category))return fail(400,{talentError:'Provide a valid talent name and category.'});
for(const tier of ['I','II'] as const)if(!descriptions[tier]||!triggerIds[tier].length||!tierEffects[tier].length||tierEffects[tier].some((effect)=>!effect.statId||!Number.isFinite(effect.value)))return fail(400,{talentError:`Tier ${tier} requires a description, trigger, and valid attribute effects.`});
const db=await getDatabase(); if(await(await db.prepare('SELECT id FROM talents WHERE name=? COLLATE NOCASE AND category=? AND id<>?')).get(name,category,id||'new'))return fail(409,{talentError:'That talent already exists in this category.'});
const talentId=id||randomUUID(),now=new Date().toISOString();
if(id)await(await db.prepare('UPDATE talents SET name=?,category=?,updated_at=? WHERE id=?')).run(name,category,now,id);else await(await db.prepare('INSERT INTO talents(id,name,category,created_at,updated_at) VALUES(?,?,?,?,?)')).run(talentId,name,category,now,now);
for(const tier of ['I','II'] as const){
await(await db.prepare(`INSERT INTO talent_tiers(id,talent_id,tier,description,trigger_text,effect_text,created_at,updated_at) VALUES(?,?,?,?,?,?,?,?) ON CONFLICT(talent_id,tier) DO UPDATE SET description=excluded.description,updated_at=excluded.updated_at`)).run(randomUUID(),talentId,tier,descriptions[tier],'','',now,now);
const tierRow=await(await db.prepare('SELECT id FROM talent_tiers WHERE talent_id=? AND tier=?')).get(talentId,tier); const tierId=String(tierRow?.id);
await(await db.prepare('DELETE FROM talent_tier_triggers WHERE talent_tier_id=?')).run(tierId); await(await db.prepare('DELETE FROM talent_tier_effects WHERE talent_tier_id=?')).run(tierId);
for(const triggerId of triggerIds[tier])await(await db.prepare('INSERT INTO talent_tier_triggers(talent_tier_id,trigger_id) VALUES(?,?)')).run(tierId,triggerId);
for(const effect of tierEffects[tier])await(await db.prepare('INSERT INTO talent_tier_effects(id,talent_tier_id,stat_attribute_id,value,created_at) VALUES(?,?,?,?,?)')).run(randomUUID(),tierId,effect.statId,effect.value,now);
}
return {talentSaved:true};
}
};