varierty of implementstions based on platform droplet issuance
This commit is contained in:
@@ -23,6 +23,8 @@ export const load: PageServerLoad = async (event) => {
|
||||
authenticated: false,
|
||||
fams: [],
|
||||
codes: [],
|
||||
choreTemplates: [],
|
||||
bonusTemplates: [],
|
||||
platformFlags: {},
|
||||
totalFams: 0,
|
||||
totalMembers: 0,
|
||||
@@ -82,10 +84,17 @@ export const load: PageServerLoad = async (event) => {
|
||||
usedBy: usage[c.id] || []
|
||||
}));
|
||||
|
||||
const [choreTemplates, bonusTemplates] = await Promise.all([
|
||||
pbAdmin.getList('chore_templates', 'global = true'),
|
||||
pbAdmin.getList('bonus_templates', 'global = true')
|
||||
]);
|
||||
|
||||
return {
|
||||
authenticated: true,
|
||||
fams: famsWithStats,
|
||||
codes: codeList,
|
||||
choreTemplates: choreTemplates as any[],
|
||||
bonusTemplates: bonusTemplates as any[],
|
||||
totalFams: fams.length,
|
||||
totalMembers: famsWithStats.reduce((s, f) => s + f.memberCount, 0),
|
||||
totalRewards: famsWithStats.reduce((s, f) => s + f.totalRewards, 0),
|
||||
@@ -110,6 +119,8 @@ export const load: PageServerLoad = async (event) => {
|
||||
subCount: 0,
|
||||
gatedCount: 0,
|
||||
codeCount: 0,
|
||||
choreTemplates: [],
|
||||
bonusTemplates: [],
|
||||
loadError: e instanceof Error ? e.message : 'Failed to load platform data'
|
||||
};
|
||||
}
|
||||
@@ -225,5 +236,113 @@ export const actions: Actions = {
|
||||
} catch (e) {
|
||||
return fail(500, { error: e instanceof Error ? e.message : 'Failed to delete code' });
|
||||
}
|
||||
},
|
||||
|
||||
// Platform-owned chore/reward templates. `type` selects the target
|
||||
// collection (chore_templates | bonus_templates); the droplet is always
|
||||
// global (visible to every family as an assignable source).
|
||||
createTemplate: async (event) => {
|
||||
requirePlatform(event);
|
||||
const fd = await event.request.formData();
|
||||
const type = fd.get('type') as string;
|
||||
const name = (fd.get('name') as string || '').trim();
|
||||
const description = (fd.get('description') as string) || '';
|
||||
const icon = (fd.get('icon') as string) || '';
|
||||
const color = (fd.get('color') as string) || '#6366f1';
|
||||
if (!name) return fail(400, { error: 'Name required' });
|
||||
|
||||
try {
|
||||
if (type === 'chore') {
|
||||
await pbAdmin.create('chore_templates', {
|
||||
name,
|
||||
description,
|
||||
icon,
|
||||
color,
|
||||
global: true,
|
||||
defaultFrequency: (fd.get('defaultFrequency') as string) || 'daily',
|
||||
defaultType: (fd.get('defaultType') as string) || 'points',
|
||||
defaultValue: Number(fd.get('defaultValue') || 0)
|
||||
});
|
||||
} else {
|
||||
await pbAdmin.create('bonus_templates', {
|
||||
name,
|
||||
description,
|
||||
icon,
|
||||
color,
|
||||
global: true,
|
||||
target: (fd.get('target') as string) || 'individual',
|
||||
type: (fd.get('bonusType') as string) || 'threshold',
|
||||
thresholdType: (fd.get('thresholdType') as string) || 'points',
|
||||
occurrence: (fd.get('occurrence') as string) || 'recurring',
|
||||
rewardType: (fd.get('rewardType') as string) || 'points',
|
||||
rewardValue: (fd.get('rewardValue') as string) || '',
|
||||
criteriaValue: Number(fd.get('criteriaValue') || 0),
|
||||
period: (fd.get('period') as string) || 'weekly',
|
||||
isPocketMoney: fd.get('isPocketMoney') === 'true'
|
||||
});
|
||||
}
|
||||
return { success: true };
|
||||
} catch (e) {
|
||||
return fail(500, { error: e instanceof Error ? e.message : 'Failed to create template' });
|
||||
}
|
||||
},
|
||||
|
||||
updateTemplate: async (event) => {
|
||||
requirePlatform(event);
|
||||
const fd = await event.request.formData();
|
||||
const kind = fd.get('kind') as string; // chore | reward
|
||||
const id = fd.get('id') as string;
|
||||
if (!id) return fail(400, { error: 'Missing id' });
|
||||
const name = (fd.get('name') as string || '').trim();
|
||||
const description = (fd.get('description') as string) || '';
|
||||
const icon = (fd.get('icon') as string) || '';
|
||||
const color = (fd.get('color') as string) || '#6366f1';
|
||||
|
||||
try {
|
||||
if (kind === 'chore') {
|
||||
await pbAdmin.update('chore_templates', id, {
|
||||
name,
|
||||
description,
|
||||
icon,
|
||||
color,
|
||||
defaultFrequency: (fd.get('defaultFrequency') as string) || 'daily',
|
||||
defaultType: (fd.get('defaultType') as string) || 'points',
|
||||
defaultValue: Number(fd.get('defaultValue') || 0)
|
||||
});
|
||||
} else {
|
||||
await pbAdmin.update('bonus_templates', id, {
|
||||
name,
|
||||
description,
|
||||
icon,
|
||||
color,
|
||||
target: (fd.get('target') as string) || 'individual',
|
||||
type: (fd.get('bonusType') as string) || 'threshold',
|
||||
thresholdType: (fd.get('thresholdType') as string) || 'points',
|
||||
occurrence: (fd.get('occurrence') as string) || 'recurring',
|
||||
rewardType: (fd.get('rewardType') as string) || 'points',
|
||||
rewardValue: (fd.get('rewardValue') as string) || '',
|
||||
criteriaValue: Number(fd.get('criteriaValue') || 0),
|
||||
period: (fd.get('period') as string) || 'weekly',
|
||||
isPocketMoney: fd.get('isPocketMoney') === 'true'
|
||||
});
|
||||
}
|
||||
return { success: true };
|
||||
} catch (e) {
|
||||
return fail(500, { error: e instanceof Error ? e.message : 'Failed to update template' });
|
||||
}
|
||||
},
|
||||
|
||||
deleteTemplate: async (event) => {
|
||||
requirePlatform(event);
|
||||
const fd = await event.request.formData();
|
||||
const kind = fd.get('kind') as string;
|
||||
const id = fd.get('id') as string;
|
||||
if (!id) return fail(400, { error: 'Missing id' });
|
||||
try {
|
||||
await pbAdmin.remove(kind === 'chore' ? 'chore_templates' : 'bonus_templates', id);
|
||||
return { success: true };
|
||||
} catch (e) {
|
||||
return fail(500, { error: e instanceof Error ? e.message : 'Failed to delete template' });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user