update ui and other frontend updates
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { RequestEvent } from '@sveltejs/kit';
|
||||
import { SERVER_IP, PROXY_PORT } from '../../../../config.ts';
|
||||
|
||||
const HONO_URL = `http://${SERVER_IP}:${PROXY_PORT}`;
|
||||
|
||||
export function getSession(event: RequestEvent) {
|
||||
return event.locals.session;
|
||||
}
|
||||
|
||||
export function requireAuth(event: RequestEvent) {
|
||||
const session = getSession(event);
|
||||
if (!session) {
|
||||
throw redirect(303, '/login');
|
||||
}
|
||||
return session;
|
||||
}
|
||||
|
||||
export async function signup(email: string, password: string, famName: string, parentName?: string) {
|
||||
const res = await fetch(`${HONO_URL}/api/admin/signup`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ email, password, famName, parentName }),
|
||||
});
|
||||
const data = await res.json();
|
||||
if (!res.ok) throw new Error(data.error || 'Signup failed');
|
||||
return data;
|
||||
}
|
||||
|
||||
export async function login(email: string, password: string) {
|
||||
console.log(email);
|
||||
const res = await fetch(`${HONO_URL}/api/admin/login`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ email, password }),
|
||||
});
|
||||
const data = await res.json();
|
||||
if (!res.ok) throw new Error(data.error || 'Login failed');
|
||||
return data;
|
||||
}
|
||||
|
||||
export async function joinMember(inviteCode: string, name: string, deviceToken: string) {
|
||||
const res = await fetch(`${HONO_URL}/api/members/join`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ inviteCode, name, deviceToken }),
|
||||
});
|
||||
const data = await res.json();
|
||||
if (!res.ok) throw new Error(data.error || 'Join failed');
|
||||
return data;
|
||||
}
|
||||
|
||||
export function setSessionCookie(event: RequestEvent, session: { famId: string; userId: string; famSlug: string }) {
|
||||
event.cookies.set('session', JSON.stringify(session), {
|
||||
httpOnly: true,
|
||||
sameSite: 'lax',
|
||||
path: '/',
|
||||
maxAge: 60 * 60 * 24 * 30,
|
||||
secure: false,
|
||||
});
|
||||
}
|
||||
|
||||
export function setDeviceTokenCookie(event: RequestEvent, token: string) {
|
||||
event.cookies.set('device_token', token, {
|
||||
httpOnly: true,
|
||||
sameSite: 'lax',
|
||||
path: '/',
|
||||
maxAge: 60 * 60 * 24 * 365,
|
||||
secure: false,
|
||||
});
|
||||
}
|
||||
|
||||
export function setPbTokenCookie(event: RequestEvent, token: string) {
|
||||
event.cookies.set('pb_token', token, {
|
||||
httpOnly: false,
|
||||
sameSite: 'lax',
|
||||
path: '/',
|
||||
maxAge: 60 * 60 * 24,
|
||||
secure: false,
|
||||
});
|
||||
}
|
||||
|
||||
export function clearSession(event: RequestEvent) {
|
||||
event.cookies.delete('session', { path: '/' });
|
||||
event.cookies.delete('pb_token', { path: '/' });
|
||||
event.cookies.delete('device_token', { path: '/' });
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
import { SERVER_IP, PROXY_PORT } from '../../../../config.ts';
|
||||
import type { RequestEvent } from '@sveltejs/kit';
|
||||
|
||||
const HONO_URL = `http://${SERVER_IP}:${PROXY_PORT}`;
|
||||
|
||||
function sessionHeaders(event: RequestEvent): Record<string, string> {
|
||||
const s = event.locals.session;
|
||||
if (!s) return {};
|
||||
return {
|
||||
'x-session-famid': s.famId,
|
||||
'x-session-userid': s.userId,
|
||||
'Content-Type': 'application/json',
|
||||
};
|
||||
}
|
||||
|
||||
async function request(method: string, path: string, body?: unknown, headers?: Record<string, string>) {
|
||||
const res = await fetch(`${HONO_URL}${path}`, {
|
||||
method,
|
||||
headers: headers || { 'Content-Type': 'application/json' },
|
||||
body: body ? JSON.stringify(body) : undefined,
|
||||
});
|
||||
const data = await res.json();
|
||||
if (!res.ok) throw new Error(data.error || `${method} ${path} failed`);
|
||||
return data;
|
||||
}
|
||||
|
||||
export const hono = {
|
||||
admin: {
|
||||
async list(event: RequestEvent, resource: string, famId: string) {
|
||||
return request('GET', `/api/admin/${famId}/${resource}`, undefined, sessionHeaders(event));
|
||||
},
|
||||
async create(event: RequestEvent, resource: string, famId: string, data: Record<string, unknown>) {
|
||||
return request('POST', `/api/admin/${famId}/${resource}`, data, sessionHeaders(event));
|
||||
},
|
||||
async update(event: RequestEvent, resource: string, famId: string, id: string, data: Record<string, unknown>) {
|
||||
return request('PATCH', `/api/admin/${famId}/${resource}/${id}`, data, sessionHeaders(event));
|
||||
},
|
||||
async remove(event: RequestEvent, resource: string, famId: string, id: string) {
|
||||
return request('DELETE', `/api/admin/${famId}/${resource}/${id}`, undefined, sessionHeaders(event));
|
||||
},
|
||||
async renameFam(event: RequestEvent, famId: string, name: string) {
|
||||
return request('PATCH', `/api/admin/${famId}/fam`, { name }, sessionHeaders(event));
|
||||
},
|
||||
async updatePayday(event: RequestEvent, famId: string, payday: number) {
|
||||
return request('PATCH', `/api/admin/${famId}/fam`, { payday }, sessionHeaders(event));
|
||||
},
|
||||
async fam(event: RequestEvent, famId: string) {
|
||||
return request('GET', `/api/admin/${famId}/fam`, undefined, sessionHeaders(event));
|
||||
},
|
||||
async verify(event: RequestEvent, famId: string) {
|
||||
return request('GET', `/api/admin/${famId}/verify`, undefined, sessionHeaders(event));
|
||||
},
|
||||
async regenInvite(event: RequestEvent, famId: string) {
|
||||
return request('POST', `/api/admin/${famId}/regen-invite`, undefined, sessionHeaders(event));
|
||||
},
|
||||
async weeklySummary(event: RequestEvent, famId: string) {
|
||||
return request('GET', `/api/admin/${famId}/weekly-summary`, undefined, sessionHeaders(event));
|
||||
},
|
||||
async completions(event: RequestEvent, famId: string) {
|
||||
return request('GET', `/api/admin/${famId}/completions`, undefined, sessionHeaders(event));
|
||||
},
|
||||
async rewards(event: RequestEvent, famId: string) {
|
||||
return request('GET', `/api/admin/${famId}/rewards`, undefined, sessionHeaders(event));
|
||||
},
|
||||
async claimReward(event: RequestEvent, famId: string, rewardId: string) {
|
||||
return request('POST', `/api/admin/${famId}/rewards/${rewardId}/claim`, undefined, sessionHeaders(event));
|
||||
},
|
||||
async bonusConfigs(event: RequestEvent, famId: string) {
|
||||
return request('GET', `/api/admin/${famId}/bonus-configs`, undefined, sessionHeaders(event));
|
||||
},
|
||||
async bonusConfigProgress(event: RequestEvent, famId: string) {
|
||||
return request('GET', `/api/admin/${famId}/bonus-configs/progress`, undefined, sessionHeaders(event));
|
||||
},
|
||||
async evaluateBonusConfig(event: RequestEvent, famId: string, configId?: string) {
|
||||
return request('POST', `/api/admin/${famId}/bonus-configs/evaluate`, { configId }, sessionHeaders(event));
|
||||
},
|
||||
async triggerBonusConfig(event: RequestEvent, famId: string, configId: string, memberId?: string) {
|
||||
return request('POST', `/api/admin/${famId}/bonus-configs/${configId}/trigger`, { memberId }, sessionHeaders(event));
|
||||
},
|
||||
async assignBonusConfig(event: RequestEvent, famId: string, configId: string, data: Record<string, unknown>) {
|
||||
return request('POST', `/api/admin/${famId}/bonus-configs/${configId}/assign`, data, sessionHeaders(event));
|
||||
},
|
||||
async completeBonusConfig(event: RequestEvent, famId: string, configId: string, phase?: string) {
|
||||
return request('POST', `/api/admin/${famId}/bonus-configs/${configId}/complete`, { phase }, sessionHeaders(event));
|
||||
},
|
||||
async destroyBonusConfig(event: RequestEvent, famId: string, configId: string) {
|
||||
return request('POST', `/api/admin/${famId}/bonus-configs/${configId}/destroy`, undefined, sessionHeaders(event));
|
||||
},
|
||||
async bonusConfigTallies(event: RequestEvent, famId: string) {
|
||||
return request('GET', `/api/admin/${famId}/bonus-configs/tallies`, undefined, sessionHeaders(event));
|
||||
},
|
||||
async revokeCompletion(event: RequestEvent, famId: string, completionId: string) {
|
||||
return request('POST', `/api/admin/${famId}/completions/${completionId}/revoke`, undefined, sessionHeaders(event));
|
||||
},
|
||||
async sendMessage(event: RequestEvent, famId: string, memberId: string, message: string) {
|
||||
return request('POST', `/api/admin/${famId}/send-message`, { memberId, message }, sessionHeaders(event));
|
||||
},
|
||||
async memberChores(event: RequestEvent, famId: string, memberId: string) {
|
||||
return request('GET', `/api/admin/${famId}/members/${memberId}/chores`, undefined, sessionHeaders(event));
|
||||
},
|
||||
async updateMember(event: RequestEvent, famId: string, memberId: string, data: Record<string, unknown>) {
|
||||
return request('PATCH', `/api/admin/${famId}/members/${memberId}`, data, sessionHeaders(event));
|
||||
},
|
||||
async getProfile(event: RequestEvent, famId: string) {
|
||||
return request('GET', `/api/admin/${famId}/profile`, undefined, sessionHeaders(event));
|
||||
},
|
||||
async updateProfile(event: RequestEvent, famId: string, data: Record<string, unknown>) {
|
||||
return request('PATCH', `/api/admin/${famId}/profile`, data, sessionHeaders(event));
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,45 @@
|
||||
import { SERVER_IP, PB_PORT, PB_EMAIL, PB_PASSWORD } from '../../../../config.ts';
|
||||
|
||||
const PB_ENDPOINT = `http://${SERVER_IP}:${PB_PORT}`;
|
||||
|
||||
let token: string | null = null;
|
||||
let tokenExpiry = 0;
|
||||
|
||||
async function ensureToken(): Promise<string> {
|
||||
if (token && Date.now() < tokenExpiry) return token;
|
||||
const res = await fetch(`${PB_ENDPOINT}/api/collections/_superusers/auth-with-password`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ identity: PB_EMAIL, password: PB_PASSWORD }),
|
||||
});
|
||||
const data = await res.json();
|
||||
if (!res.ok) throw new Error(`PB admin auth failed: ${JSON.stringify(data)}`);
|
||||
token = data.token;
|
||||
tokenExpiry = Date.now() + 23 * 60 * 60 * 1000;
|
||||
return token!;
|
||||
}
|
||||
|
||||
export const pbAdmin = {
|
||||
async getList(collection: string, filter = '') {
|
||||
const t = await ensureToken();
|
||||
const params = new URLSearchParams();
|
||||
if (filter) params.set('filter', filter);
|
||||
params.set('perPage', '200');
|
||||
const res = await fetch(`${PB_ENDPOINT}/api/collections/${collection}/records?${params}`, {
|
||||
headers: { Authorization: `Bearer ${t}` },
|
||||
});
|
||||
const data = await res.json();
|
||||
if (!res.ok) throw new Error(`PB list ${collection}: ${JSON.stringify(data)}`);
|
||||
return data.items || [];
|
||||
},
|
||||
|
||||
async getOne(collection: string, id: string) {
|
||||
const t = await ensureToken();
|
||||
const res = await fetch(`${PB_ENDPOINT}/api/collections/${collection}/records/${id}`, {
|
||||
headers: { Authorization: `Bearer ${t}` },
|
||||
});
|
||||
const data = await res.json();
|
||||
if (!res.ok) throw new Error(`PB get ${collection}/${id}: ${JSON.stringify(data)}`);
|
||||
return data;
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user