diff --git a/webapp/package.json b/webapp/package.json index 651e4e5..4e72130 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -25,6 +25,7 @@ "vite": "^7.0.4" }, "dependencies": { - "hotkeys-js": "^3.13.15" + "hotkeys-js": "^3.13.15", + "@libsql/client": "^0.14.0" } } diff --git a/webapp/src/lib/server/db/schema.js b/webapp/src/lib/server/db/schema.js index c136cf2..1d8b8cb 100644 --- a/webapp/src/lib/server/db/schema.js +++ b/webapp/src/lib/server/db/schema.js @@ -34,7 +34,7 @@ export const combined = sqliteView('combined', { winning_ticket: integer('winning_ticket'), winner: text('winner') }).as( - sql`SELECT b.prefix, b.b_id, b.winning_ticket, CONCAT(t.last_name, ", ", t.first_name) AS winner + sql`SELECT b.prefix, b.b_id, b.winning_ticket, CONCAT(t.last_name, ', ', t.first_name) AS winner FROM baskets b LEFT JOIN tickets t ON b.prefix = t.prefix AND b.winning_ticket = t.t_id ORDER BY b.prefix, b.b_id` @@ -49,7 +49,7 @@ export const report = sqliteView('report', { winning_ticket: integer('winning_ticket'), description: text('description') }).as( - sql`SELECT b.prefix, CONCAT(t.last_name, ", ", t.first_name) AS winner_name, t.phone_number, \ + sql`SELECT b.prefix, CONCAT(t.last_name, ', ', t.first_name) AS winner_name, t.phone_number, \ t.preference, b.b_id, b.winning_ticket, b.description FROM baskets b LEFT JOIN tickets t ON b.prefix = t.prefix AND b.winning_ticket = t.t_id diff --git a/webapp/src/routes/api/baskets/[prefix]/[b_from]/[b_to]/+server.js b/webapp/src/routes/api/baskets/[prefix]/[b_from]/[b_to]/+server.js index 56bf0ec..4e85fe3 100644 --- a/webapp/src/routes/api/baskets/[prefix]/[b_from]/[b_to]/+server.js +++ b/webapp/src/routes/api/baskets/[prefix]/[b_from]/[b_to]/+server.js @@ -21,7 +21,7 @@ export async function GET({ params }) { for (let i=n_b_from; i <= n_b_to; i++) { let data = await db.select().from(baskets).where(and(eq(baskets.prefix, params.prefix), eq(baskets.b_id, i))); if (data[0]) { - r_dict[i] = {...data[0]}; + r_dict[i] = {...data[0], changed: false}; } else { r_dict[i] = {prefix: params.prefix, b_id: i, description: "", donors: "", winning_ticket: 0, changed: false}; } diff --git a/webapp/src/routes/api/combined/+server.js b/webapp/src/routes/api/combined/+server.js new file mode 100644 index 0000000..05f722d --- /dev/null +++ b/webapp/src/routes/api/combined/+server.js @@ -0,0 +1,39 @@ +import { env } from "$env/dynamic/private"; +import { db } from "$lib/server/db"; +import { baskets, combined } from "$lib/server/db/schema"; + +export async function GET() { + if (env.TAM3_REMOTE) { + const res = await fetch(`${env.TAM3_REMOTE}/api/combined/?api_key=${env.TAM3_REMOTE_KEY}`); + if (!res.ok) { + return new Response(JSON.stringify({detail: "Error fetching winners"}), { + status: res.status, + statusText: res.statusText + }) + }; + const data = await res.json(); + return new Response(JSON.stringify(data), {status: 200, statusText: "Winners fetched successfully."}) + } else { + const data = await db.select().from(combined); + return new Response(JSON.stringify(data), {status: 200, statusText: "Winners loaded successfully."}) + } +} + +export async function POST({ request }) { + const r_data = await request.json() + for (let winner of r_data) { + await db.insert(baskets).values({prefix: winner.prefix, b_id: winner.b_id, winning_ticket: winner.winning_ticket}) + .onConflictDoUpdate({target: [baskets.prefix, baskets.b_id], set: {winning_ticket: winner.winning_ticket}}) + } + if (env.TAM3_REMOTE) { + const res = await fetch(`${env.TAM3_REMOTE}/api/combined/?api_key=${env.TAM3_REMOTE_KEY}`, { + body: JSON.stringify(r_data), + method: 'POST', + headers: {'Content-Type': 'application/json'} + }); + if (!res.ok) { + return new Response(JSON.stringify({detail: "Error posting winners."}), {status: res.status, statusText: res.statusText}) + }; + } + return new Response(JSON.stringify({detail: "Posted winners successfully."})) +} \ No newline at end of file diff --git a/webapp/src/routes/api/combined/[prefix]/[b_from]/[b_to]/+server.js b/webapp/src/routes/api/combined/[prefix]/[b_from]/[b_to]/+server.js new file mode 100644 index 0000000..d7e69d8 --- /dev/null +++ b/webapp/src/routes/api/combined/[prefix]/[b_from]/[b_to]/+server.js @@ -0,0 +1,27 @@ +import { env } from "process"; +import { db } from "$lib/server/db"; +import { combined } from "$lib/server/db/schema"; +import { eq, and } from "drizzle-orm"; + +export async function GET({ params }) { + const n_b_from = parseInt(params.b_from), n_b_to = parseInt(params.b_to); + if (env.TAM3_REMOTE) { + const res = await fetch(`${env.TAM3_REMOTE}/api/combined/${params.prefix}/${n_b_from}/${n_b_to}/?api_key=${env.TAM3_REMOTE_KEY}`); + if (!res.ok) { + return new Response(JSON.stringify({detail: "Unable to fetch winners"}), {status: res.status, statusText: res.statusText}) + }; + const data = await res.json(); + return new Response(JSON.stringify(data), {status: 200, statusText: "Tickets fetched successfully."}) + } else { + let r_dict = {}; + for (let i = n_b_from; i <= n_b_to; i++) { + let data = await db.select().from(combined).where(and(eq(combined.prefix, params.prefix), eq(combined.b_id, i))); + if (data[0]) { + r_dict[i] = {...data[0], changed: false}; + } else { + r_dict[i] = {prefix: params.prefix, b_id: i, winning_ticket: 0, winner: ", ", changed: false} + }; + }; + return new Response(JSON.stringify(Object.values(r_dict)), {status: 200, statusText: "Tickets loaded successfully."}) + } +} \ No newline at end of file diff --git a/webapp/src/routes/api/combined/[prefix]/[b_id]/+server.js b/webapp/src/routes/api/combined/[prefix]/[b_id]/+server.js new file mode 100644 index 0000000..53e2c2d --- /dev/null +++ b/webapp/src/routes/api/combined/[prefix]/[b_id]/+server.js @@ -0,0 +1,24 @@ +import { env } from "$env/dynamic/private"; +import { db } from "$lib/server/db"; +import { combined } from "$lib/server/db/schema"; +import { eq, and } from "drizzle-orm"; + +export async function GET({ params }) { + if (env.TAM3_REMOTE) { + const res = await fetch(`${env.TAM3_REMOTE}/api/combined/${params.prefix}/${params.b_id}/?api_key=${env.TAM3_REMOTE_KEY}`); + if (!res.ok) { + return new Response(JSON.stringify({detail: "Unable to fetch winner"}), {status: res.status, statusText: res.statusText}) + }; + const data = await res.json(); + return new Response(JSON.stringify(data), {status: 200, statusText: "Fetched winner successfully."}) + } else { + let r_data = {} + const data = await db.select().from(combined).where(and(eq(combined.prefix, params.prefix), eq(combined.b_id, params.b_id))); + if (data[0]) { + r_data = {...data[0], changed: false}; + } else { + r_data = {prefix: params.prefix, b_id: parseInt(params.b_id), winning_ticket: 0, winner: ", ", changed: false} + } + return new Response(JSON.stringify(r_data), {status: 200, statusText: "Loaded winner successfully."}); + } +} \ No newline at end of file diff --git a/webapp/src/routes/api/tickets/[prefix]/[t_from]/[t_to]/+server.js b/webapp/src/routes/api/tickets/[prefix]/[t_from]/[t_to]/+server.js index 1a4b5af..4adf0c4 100644 --- a/webapp/src/routes/api/tickets/[prefix]/[t_from]/[t_to]/+server.js +++ b/webapp/src/routes/api/tickets/[prefix]/[t_from]/[t_to]/+server.js @@ -21,7 +21,7 @@ export async function GET({ params }) { for (let i=n_t_from; i <= n_t_to; i++) { let data = await db.select().from(tickets).where(and(eq(tickets.prefix, params.prefix), eq(tickets.t_id, i))); if (data[0]) { - r_dict[i] = {...data[0]}; + r_dict[i] = {...data[0], changed: false}; } else { r_dict[i] = {prefix: params.prefix, t_id: i, first_name: "", last_name: "", phone_number: "", preference: "CALL", changed: false}; } diff --git a/webapp/src/routes/drawing/[prefix]/+page.js b/webapp/src/routes/drawing/[prefix]/+page.js new file mode 100644 index 0000000..212d086 --- /dev/null +++ b/webapp/src/routes/drawing/[prefix]/+page.js @@ -0,0 +1,5 @@ +export async function load({ params, fetch }) { + const res = await fetch(`/api/prefixes/${params.prefix}`); + const prefix_data = await res.json(); + return {prefix: prefix_data} +} \ No newline at end of file diff --git a/webapp/src/routes/drawing/[prefix]/+page.svelte b/webapp/src/routes/drawing/[prefix]/+page.svelte new file mode 100644 index 0000000..c5e2de1 --- /dev/null +++ b/webapp/src/routes/drawing/[prefix]/+page.svelte @@ -0,0 +1,62 @@ + + +

{prefix.name} Drawing Form

+ + + + + + + + + + + + {#each current_drawings as drawing, idx} + + + + + + + {/each} + +
Basket IDWinning NumberWinnerChanged
{drawing.b_id}{drawing.winner}
+ + \ No newline at end of file