(add): Sheet printing form and compiler corrections
This commit is contained in:
@@ -26,9 +26,9 @@
|
||||
<div id="formheader" class="{prefix.color}" bind:offsetHeight={headerHeight}>
|
||||
<div class="flex-row-space tb-margin">
|
||||
<div class="flex-row">
|
||||
<input type="number" bind:value={pagerForm.id_from}>
|
||||
<input type="number" onfocus={(e) => e.target.select()} bind:value={pagerForm.id_from}>
|
||||
<div style="font-size: 22pt">-</div>
|
||||
<input type="number" bind:value={pagerForm.id_to}>
|
||||
<input type="number" onfocus={(e) => e.target.select()} bind:value={pagerForm.id_to}>
|
||||
<button class="styled" onclick={() => {
|
||||
if (Math.abs(pagerForm.id_to - pagerForm.id_from) > 800) {
|
||||
pagerForm.id_to = pagerForm.id_from + 799;
|
||||
|
||||
@@ -1,94 +1,142 @@
|
||||
<script>
|
||||
import { browser } from "$app/environment";
|
||||
import { env } from "$env/dynamic/public";
|
||||
import hotkeys from "hotkeys-js";
|
||||
import favicon from "$lib/assets/favicon.svg"
|
||||
import { browser } from "$app/environment";
|
||||
import { env } from "$env/dynamic/public";
|
||||
import { setContext } from "svelte";
|
||||
import hotkeys from "hotkeys-js";
|
||||
import favicon from "$lib/assets/favicon.svg";
|
||||
|
||||
let { data } = $props();
|
||||
const all_prefixes = [...data.prefixes];
|
||||
let prefix_name = $state("");
|
||||
let current_prefix = $state({name: "", color: "", weight: 0});
|
||||
let admin_mode = $state(false);
|
||||
const venue = env.PUBLIC_TAM3_VENUE || "TAM3";
|
||||
let { data } = $props();
|
||||
const all_prefixes = $derived(data.prefixes);
|
||||
let prefix_name = $state("");
|
||||
let current_prefix = $state({ name: "", color: "", weight: 0 });
|
||||
let admin_mode = $state(false);
|
||||
const venue = env.PUBLIC_TAM3_VENUE || "TAM3";
|
||||
|
||||
$effect(() => {
|
||||
const new_prefix = all_prefixes.find((prefix) => prefix.name === prefix_name);
|
||||
if (new_prefix) {
|
||||
current_prefix = {...new_prefix};
|
||||
$effect(() => {
|
||||
const new_prefix = all_prefixes.find(
|
||||
(prefix) => prefix.name === prefix_name,
|
||||
);
|
||||
if (new_prefix) {
|
||||
current_prefix = { ...new_prefix };
|
||||
}
|
||||
});
|
||||
|
||||
if (browser) {
|
||||
hotkeys.filter = function (event) {
|
||||
return true;
|
||||
};
|
||||
hotkeys("alt+a", function (event) {
|
||||
event.preventDefault();
|
||||
admin_mode = !admin_mode;
|
||||
return false;
|
||||
});
|
||||
setTimeout(() => {
|
||||
if (all_prefixes[0]) {
|
||||
prefix_name = all_prefixes[0].name;
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
})
|
||||
|
||||
if (browser) {
|
||||
document.title = `${venue} - Main Menu`;
|
||||
hotkeys.filter = function(event) {return true};
|
||||
hotkeys('alt+a', function(event) {event.preventDefault(); admin_mode = !admin_mode; return false;});
|
||||
setTimeout(() => {
|
||||
if (all_prefixes[0]) {
|
||||
prefix_name = all_prefixes[0].name;
|
||||
}
|
||||
}, 100);
|
||||
};
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>{venue} - Main Menu</title>
|
||||
</svelte:head>
|
||||
|
||||
<div class="main-menu">
|
||||
<div class="flex-row">
|
||||
<img src="{favicon}" alt="TAM3 Icon - Red ticket with TAM3 on it" class="icon">
|
||||
<h1>{venue} - Main Menu</h1>
|
||||
</div>
|
||||
{#if all_prefixes.length > 0}
|
||||
<div class="universal-reports flex-row tb-margin">
|
||||
<a href="/counts" target="_blank" class="styled">Counts</a>
|
||||
</div>
|
||||
<div>
|
||||
<h2>Current Prefix: {current_prefix.name}</h2>
|
||||
</div>
|
||||
<div class="change_title">
|
||||
<h2>Change Prefix:</h2>
|
||||
</div>
|
||||
<div class="prefix-selector flex-row">
|
||||
{#each all_prefixes as prefix}
|
||||
<div class="{prefix.color} p025{prefix.name === prefix_name ? " active" : ""}">
|
||||
<button class="styled" onclick={() => {
|
||||
prefix_name = prefix.name;
|
||||
}}>{prefix.name}</button>
|
||||
<div class="flex-row">
|
||||
<img
|
||||
src={favicon}
|
||||
alt="TAM3 Icon - Red ticket with TAM3 on it"
|
||||
class="icon"
|
||||
/>
|
||||
<h1>{venue} - Main Menu</h1>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
<div><h2>Forms:</h2></div>
|
||||
<div class="flex-row {current_prefix.color}">
|
||||
<a href="/tickets/{current_prefix.name}/" target="_blank" class="styled">Tickets</a>
|
||||
<a href="/baskets/{current_prefix.name}/" target="_blank" class="styled">Baskets</a>
|
||||
<a href="/drawing/{current_prefix.name}/" target="_blank" class="styled">Drawing</a>
|
||||
</div>
|
||||
<div><h2>Reports:</h2></div>
|
||||
<div class="flex-row {current_prefix.color}">
|
||||
<a href="/reports/byname/{current_prefix.name}/" target="_blank" class="styled">By Name</a>
|
||||
<a href="/reports/bybasket/{current_prefix.name}/" target="_blank" class="styled">By Basket ID</a>
|
||||
</div>
|
||||
{:else}
|
||||
<p>There aren't any prefixes available, please create them.</p>
|
||||
{/if}
|
||||
{#if all_prefixes.length > 0}
|
||||
<div class="universal-reports flex-row tb-margin">
|
||||
<a href="/counts" target="_blank" class="styled">Counts</a>
|
||||
<a href="/sheets" target="_blank" class="styled">Print Sheets</a>
|
||||
</div>
|
||||
<div>
|
||||
<h2>Current Prefix: {current_prefix.name}</h2>
|
||||
</div>
|
||||
<div class="change_title">
|
||||
<h2>Change Prefix:</h2>
|
||||
</div>
|
||||
<div class="prefix-selector flex-row">
|
||||
{#each all_prefixes as prefix}
|
||||
<div
|
||||
class="{prefix.color} p025{prefix.name === prefix_name
|
||||
? ' active'
|
||||
: ''}"
|
||||
>
|
||||
<button
|
||||
class="styled"
|
||||
onclick={() => {
|
||||
prefix_name = prefix.name;
|
||||
}}>{prefix.name}</button
|
||||
>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
<div><h2>Forms:</h2></div>
|
||||
<div class="flex-row {current_prefix.color}">
|
||||
<a
|
||||
href="/tickets/{current_prefix.name}/"
|
||||
target="_blank"
|
||||
class="styled">Tickets</a
|
||||
>
|
||||
<a
|
||||
href="/baskets/{current_prefix.name}/"
|
||||
target="_blank"
|
||||
class="styled">Baskets</a
|
||||
>
|
||||
<a
|
||||
href="/drawing/{current_prefix.name}/"
|
||||
target="_blank"
|
||||
class="styled">Drawing</a
|
||||
>
|
||||
</div>
|
||||
<div><h2>Reports:</h2></div>
|
||||
<div class="flex-row {current_prefix.color}">
|
||||
<a
|
||||
href="/reports/byname/{current_prefix.name}/"
|
||||
target="_blank"
|
||||
class="styled">By Name</a
|
||||
>
|
||||
<a
|
||||
href="/reports/bybasket/{current_prefix.name}/"
|
||||
target="_blank"
|
||||
class="styled">By Basket ID</a
|
||||
>
|
||||
</div>
|
||||
{:else}
|
||||
<p>There aren't any prefixes available, please create them.</p>
|
||||
{/if}
|
||||
</div>
|
||||
{#if admin_mode}
|
||||
<div><h2>Admin Mode:</h2></div>
|
||||
<div class="flex-row">
|
||||
<a href="/prefixes" target="_blank" class="styled">Prefix Editor</a>
|
||||
<a href="/search/tickets" target="_blank" class="styled">Search Tickets</a>
|
||||
<a href="/backuprestore" target="_blank" class="styled">Backup/Restore</a>
|
||||
<a href="/settings" target="_blank" class="styled">Settings</a>
|
||||
</div>
|
||||
<div><h2>Admin Mode:</h2></div>
|
||||
<div class="flex-row">
|
||||
<a href="/prefixes" target="_blank" class="styled">Prefix Editor</a>
|
||||
<a href="/search/tickets" target="_blank" class="styled"
|
||||
>Search Tickets</a
|
||||
>
|
||||
<a href="/backuprestore" target="_blank" class="styled"
|
||||
>Backup/Restore</a
|
||||
>
|
||||
<a href="/settings" target="_blank" class="styled">Settings</a>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="status tb-margin">
|
||||
{data.status}
|
||||
{data.status}
|
||||
</div>
|
||||
|
||||
<div class="annotation">
|
||||
<p>Ticket Auction Manager 3 by Dilan Gilluly</p>
|
||||
<p>Ticket Auction Manager 3 by Dilan Gilluly</p>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
img.icon {
|
||||
max-width: 150px;
|
||||
}
|
||||
img.icon {
|
||||
max-width: 150px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,36 +1,41 @@
|
||||
<script>
|
||||
import { browser } from '$app/environment';
|
||||
import FormHeader from '$lib/components/FormHeader.svelte';
|
||||
import hotkeys from 'hotkeys-js';
|
||||
import { browser } from "$app/environment";
|
||||
import FormHeader from "$lib/components/FormHeader.svelte";
|
||||
import hotkeys from "hotkeys-js";
|
||||
|
||||
const { data } = $props();
|
||||
const prefix = {...data.prefix};
|
||||
let pagerForm = $state({id_from: 0, id_to: 0});
|
||||
const prefix = $derived(data.prefix);
|
||||
let pagerForm = $state({ id_from: 0, id_to: 0 });
|
||||
let current_idx = $state(0);
|
||||
let next_idx = $derived(current_idx+1);
|
||||
let prev_idx = $derived(current_idx-1)
|
||||
let next_idx = $derived(current_idx + 1);
|
||||
let prev_idx = $derived(current_idx - 1);
|
||||
let current_baskets = $state([]);
|
||||
let copy_buffer = $state({prefix: prefix.name, b_id: 0, description: "", donors: "", winning_ticket: 0});
|
||||
let headerHeight = $state()
|
||||
let copy_buffer = $state({});
|
||||
let headerHeight = $state();
|
||||
|
||||
function changeFocus(idx) {
|
||||
const focusDe = document.getElementById(`${idx}_de`);
|
||||
if (focusDe) {
|
||||
focusDe.select();
|
||||
focusDe.scrollIntoView({block: "center"});
|
||||
focusDe.scrollIntoView({ block: "center" });
|
||||
}
|
||||
}
|
||||
|
||||
const functions = {
|
||||
refreshPage: async () => {
|
||||
if (current_baskets.filter(basket => basket.changed === true).length > 0) {
|
||||
functions.saveAll()
|
||||
if (
|
||||
current_baskets.filter((basket) => basket.changed === true)
|
||||
.length > 0
|
||||
) {
|
||||
functions.saveAll();
|
||||
}
|
||||
const res = await fetch(`/api/baskets/${prefix.name}/${pagerForm.id_from}/${pagerForm.id_to}`);
|
||||
const res = await fetch(
|
||||
`/api/baskets/${prefix.name}/${pagerForm.id_from}/${pagerForm.id_to}`,
|
||||
);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
current_baskets = [...data];
|
||||
setTimeout(() => changeFocus(0), 100)
|
||||
setTimeout(() => changeFocus(0), 100);
|
||||
}
|
||||
},
|
||||
prevPage: () => {
|
||||
@@ -47,7 +52,12 @@
|
||||
},
|
||||
duplicateDown: () => {
|
||||
if (current_baskets[next_idx]) {
|
||||
current_baskets[next_idx] = {...current_baskets[current_idx], b_id: current_baskets[next_idx].b_id, winning_ticket: current_baskets[next_idx].winning_ticket, changed: true};
|
||||
current_baskets[next_idx] = {
|
||||
...current_baskets[current_idx],
|
||||
b_id: current_baskets[next_idx].b_id,
|
||||
winning_ticket: current_baskets[next_idx].winning_ticket,
|
||||
changed: true,
|
||||
};
|
||||
changeFocus(next_idx);
|
||||
} else {
|
||||
changeFocus(next_idx);
|
||||
@@ -55,7 +65,12 @@
|
||||
},
|
||||
duplicateUp: () => {
|
||||
if (prev_idx >= 0) {
|
||||
current_baskets[prev_idx] = {...current_baskets[current_idx], b_id: current_baskets[prev_idx].b_id, winning_ticket: current_baskets[prev_idx].winning_ticket, changed: true};
|
||||
current_baskets[prev_idx] = {
|
||||
...current_baskets[current_idx],
|
||||
b_id: current_baskets[prev_idx].b_id,
|
||||
winning_ticket: current_baskets[prev_idx].winning_ticket,
|
||||
changed: true,
|
||||
};
|
||||
changeFocus(prev_idx);
|
||||
} else {
|
||||
changeFocus(prev_idx);
|
||||
@@ -76,35 +91,56 @@
|
||||
}
|
||||
},
|
||||
copy: () => {
|
||||
copy_buffer = {...current_baskets[current_idx]};
|
||||
copy_buffer = { ...current_baskets[current_idx] };
|
||||
},
|
||||
paste: () => {
|
||||
current_baskets[current_idx] = {...copy_buffer, b_id: current_baskets[current_idx].b_id, changed: true}
|
||||
if (Object.keys(copy_buffer).length !== 0) {
|
||||
current_baskets[current_idx] = {
|
||||
...copy_buffer,
|
||||
b_id: current_baskets[current_idx].b_id,
|
||||
changed: true,
|
||||
};
|
||||
}
|
||||
changeFocus(current_idx);
|
||||
},
|
||||
saveAll: async () => {
|
||||
const to_save = current_baskets.filter((basket) => basket.changed === true);
|
||||
const res = await fetch(`/api/baskets`, {body: JSON.stringify(to_save), method: 'POST', headers: {'Content-Type': 'application/json'}});
|
||||
const to_save = current_baskets.filter(
|
||||
(basket) => basket.changed === true,
|
||||
);
|
||||
const res = await fetch(`/api/baskets`, {
|
||||
body: JSON.stringify(to_save),
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
if (res.ok) {
|
||||
for (let basket of current_baskets) {basket.changed = false};
|
||||
for (let basket of current_baskets) {
|
||||
basket.changed = false;
|
||||
}
|
||||
changeFocus(0);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
if (browser) {
|
||||
document.title = `${prefix.name} Basket Entry`
|
||||
window.addEventListener("beforeunload", function(e) {
|
||||
if (current_baskets.filter(basket => basket.changed === true).length > 0) {
|
||||
window.addEventListener("beforeunload", function (e) {
|
||||
if (
|
||||
current_baskets.filter((basket) => basket.changed === true)
|
||||
.length > 0
|
||||
) {
|
||||
e.preventDefault();
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>{prefix.name} Basket Entry</title>
|
||||
</svelte:head>
|
||||
|
||||
<h1>{prefix.name} Basket Entry</h1>
|
||||
<FormHeader {prefix} {functions} bind:pagerForm bind:headerHeight />
|
||||
<table>
|
||||
<thead style="top: {headerHeight+2}px">
|
||||
<thead style="top: {headerHeight + 2}px">
|
||||
<tr>
|
||||
<th style="width: 12ch">Basket ID</th>
|
||||
<th>Description</th>
|
||||
@@ -114,12 +150,32 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each current_baskets as basket, idx}
|
||||
<tr onfocusin={() => current_idx = idx}>
|
||||
<td>{basket.b_id}</td>
|
||||
<td><input type="text" id="{idx}_de" onchange={() => basket.changed = true} bind:value={basket.description}></td>
|
||||
<td><input type="text" id="{idx}_do" onchange={() => basket.changed = true} bind:value={basket.donors}></td>
|
||||
<td><button tabindex="-1" onclick={() => basket.changed = !basket.changed}>{basket.changed ? "Y" : "N"}</button></td>
|
||||
</tr>
|
||||
<tr onfocusin={() => (current_idx = idx)}>
|
||||
<td>{basket.b_id}</td>
|
||||
<td
|
||||
><input
|
||||
type="text"
|
||||
id="{idx}_de"
|
||||
onchange={() => (basket.changed = true)}
|
||||
bind:value={basket.description}
|
||||
/></td
|
||||
>
|
||||
<td
|
||||
><input
|
||||
type="text"
|
||||
id="{idx}_do"
|
||||
onchange={() => (basket.changed = true)}
|
||||
bind:value={basket.donors}
|
||||
/></td
|
||||
>
|
||||
<td
|
||||
><button
|
||||
tabindex="-1"
|
||||
onclick={() => (basket.changed = !basket.changed)}
|
||||
>{basket.changed ? "Y" : "N"}</button
|
||||
></td
|
||||
>
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -148,7 +204,8 @@
|
||||
background: transparent;
|
||||
border: solid 1px #000000;
|
||||
}
|
||||
input, button {
|
||||
input,
|
||||
button {
|
||||
display: block;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
|
||||
@@ -1,19 +1,27 @@
|
||||
<script>
|
||||
import { browser } from '$app/environment';
|
||||
import { browser } from "$app/environment";
|
||||
|
||||
const { data } = $props();
|
||||
const counts = data.counts;
|
||||
const prefixes = data.prefixes;
|
||||
const counts = $derived(data.counts);
|
||||
function copyPrefixes() {
|
||||
return [...data.prefixes];
|
||||
}
|
||||
const prefixes = $state(copyPrefixes());
|
||||
|
||||
let colormap = {};
|
||||
for (let prefix of prefixes) {colormap[prefix.name] = prefix.color}
|
||||
for (let prefix of prefixes) {
|
||||
colormap[prefix.name] = prefix.color;
|
||||
}
|
||||
|
||||
if (browser) {
|
||||
document.title = "Counts of tickets entered";
|
||||
setTimeout(() => window.location.reload(true), 60000);
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Counts of tickets entered</title>
|
||||
</svelte:head>
|
||||
|
||||
<h1>Counts of tickets entered</h1>
|
||||
<table>
|
||||
<thead>
|
||||
@@ -25,11 +33,11 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each counts as count}
|
||||
<tr class={colormap[count.prefix]}>
|
||||
<td>{count.prefix}</td>
|
||||
<td>{parseInt(count.total_sold).toLocaleString()}</td>
|
||||
<td>{parseInt(count.unique_sold).toLocaleString()}</td>
|
||||
</tr>
|
||||
<tr class={colormap[count.prefix]}>
|
||||
<td>{count.prefix}</td>
|
||||
<td>{parseInt(count.total_sold).toLocaleString()}</td>
|
||||
<td>{parseInt(count.unique_sold).toLocaleString()}</td>
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@@ -1,32 +1,37 @@
|
||||
<script>
|
||||
import { browser } from '$app/environment';
|
||||
import FormHeader from '$lib/components/FormHeader.svelte';
|
||||
import { focusElement } from '$lib/focusElement.js';
|
||||
import { browser } from "$app/environment";
|
||||
import FormHeader from "$lib/components/FormHeader.svelte";
|
||||
import { focusElement } from "$lib/focusElement.js";
|
||||
|
||||
const { data } = $props();
|
||||
const prefix = {...data.prefix};
|
||||
let pagerForm = $state({id_from: 0, id_to: 0});
|
||||
const prefix = $derived(data.prefix);
|
||||
let pagerForm = $state({ id_from: 0, id_to: 0 });
|
||||
let current_idx = $state(0);
|
||||
let next_idx = $derived(current_idx+1);
|
||||
let prev_idx = $derived(current_idx-1);
|
||||
let next_idx = $derived(current_idx + 1);
|
||||
let prev_idx = $derived(current_idx - 1);
|
||||
let current_drawings = $state([]);
|
||||
let copy_buffer = $state({prefix: prefix.name, b_id: 1, winning_ticket: 0, winner: ", "});
|
||||
let headerHeight = $state()
|
||||
let copy_buffer = $state({});
|
||||
let headerHeight = $state();
|
||||
|
||||
function changeFocus(idx) {
|
||||
const focusWt = document.getElementById(`${idx}_wt`);
|
||||
if (focusWt) {
|
||||
focusWt.select();
|
||||
focusWt.scrollIntoView({block: "center"});
|
||||
focusWt.scrollIntoView({ block: "center" });
|
||||
}
|
||||
}
|
||||
|
||||
const functions = {
|
||||
refreshPage: async () => {
|
||||
if (current_drawings.filter(drawing => drawing.changed === true).length > 0) {
|
||||
functions.saveAll()
|
||||
if (
|
||||
current_drawings.filter((drawing) => drawing.changed === true)
|
||||
.length > 0
|
||||
) {
|
||||
functions.saveAll();
|
||||
}
|
||||
const res = await fetch(`/api/combined/${prefix.name}/${pagerForm.id_from}/${pagerForm.id_to}`);
|
||||
const res = await fetch(
|
||||
`/api/combined/${prefix.name}/${pagerForm.id_from}/${pagerForm.id_to}`,
|
||||
);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
current_drawings = [...data];
|
||||
@@ -47,7 +52,11 @@
|
||||
},
|
||||
duplicateDown: () => {
|
||||
if (current_drawings[next_idx]) {
|
||||
current_drawings[next_idx] = {...current_drawings[current_idx], b_id: current_drawings[next_idx].b_id, changed: true};
|
||||
current_drawings[next_idx] = {
|
||||
...current_drawings[current_idx],
|
||||
b_id: current_drawings[next_idx].b_id,
|
||||
changed: true,
|
||||
};
|
||||
changeFocus(next_idx);
|
||||
} else {
|
||||
changeFocus(current_idx);
|
||||
@@ -55,7 +64,11 @@
|
||||
},
|
||||
duplicateUp: () => {
|
||||
if (prev_idx >= 0) {
|
||||
current_drawings[prev_idx] = {...current_drawing[current_idx], b_id: current_drawings[prev_idx].b_id, changed: true};
|
||||
current_drawings[prev_idx] = {
|
||||
...current_drawing[current_idx],
|
||||
b_id: current_drawings[prev_idx].b_id,
|
||||
changed: true,
|
||||
};
|
||||
changeFocus(prev_idx);
|
||||
} else {
|
||||
changeFocus(current_idx);
|
||||
@@ -76,35 +89,56 @@
|
||||
}
|
||||
},
|
||||
copy: () => {
|
||||
copy_buffer = {...current_drawings[current_idx]};
|
||||
copy_buffer = { ...current_drawings[current_idx] };
|
||||
},
|
||||
paste: () => {
|
||||
current_drawings[current_idx] = {...copy_buffer, b_id: current_drawings[current_idx], changed: true};
|
||||
if (Object.keys(copy_buffer).length !== 0) {
|
||||
current_drawings[current_idx] = {
|
||||
...copy_buffer,
|
||||
b_id: current_drawings[current_idx],
|
||||
changed: true,
|
||||
};
|
||||
}
|
||||
changeFocus(current_idx);
|
||||
},
|
||||
saveAll: async () => {
|
||||
const to_save = current_drawings.filter((drawing) => drawing.changed === true);
|
||||
const res = await fetch("/api/combined", {body: JSON.stringify(to_save), method: 'POST', headers: {'Content-Type': 'application/json'}});
|
||||
const to_save = current_drawings.filter(
|
||||
(drawing) => drawing.changed === true,
|
||||
);
|
||||
const res = await fetch("/api/combined", {
|
||||
body: JSON.stringify(to_save),
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
if (res.ok) {
|
||||
for (let drawing of current_drawings) {drawing.changed = false};
|
||||
for (let drawing of current_drawings) {
|
||||
drawing.changed = false;
|
||||
}
|
||||
changeFocus(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
if (browser) {
|
||||
document.title = `${prefix.name} Drawing Form`
|
||||
window.addEventListener("beforeunload", function(e) {
|
||||
if (current_drawings.filter(drawing => drawing.changed === true).length > 0) {
|
||||
window.addEventListener("beforeunload", function (e) {
|
||||
if (
|
||||
current_drawings.filter((drawing) => drawing.changed === true)
|
||||
.length > 0
|
||||
) {
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>{prefix.name} Drawing Form</title>
|
||||
</svelte:head>
|
||||
|
||||
<h1>{prefix.name} Drawing Form</h1>
|
||||
<FormHeader {prefix} {functions} bind:pagerForm bind:headerHeight />
|
||||
<table>
|
||||
<thead style="top: {headerHeight+2}px">
|
||||
<thead style="top: {headerHeight + 2}px">
|
||||
<tr>
|
||||
<th style="width: 12ch">Basket ID</th>
|
||||
<th style="width: 20ch">Winning Number</th>
|
||||
@@ -114,19 +148,32 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each current_drawings as drawing, idx}
|
||||
<tr onfocusin={() => current_idx = idx}>
|
||||
<td>{drawing.b_id}</td>
|
||||
<td><input type="number" id="{idx}_wt" bind:value={drawing.winning_ticket} onfocus={focusElement} onchange={async () => {
|
||||
drawing.changed = true;
|
||||
const res = await fetch(`/api/tickets/${prefix.name}/${drawing.winning_ticket}`);
|
||||
if (res.ok) {
|
||||
const t_data = await res.json()
|
||||
drawing.winner = `${t_data.last_name}, ${t_data.first_name}`
|
||||
}
|
||||
}}></td>
|
||||
<td>{drawing.winner}</td>
|
||||
<td><button tabindex="-1">{drawing.changed ? "Y" : "N"}</button></td>
|
||||
</tr>
|
||||
<tr onfocusin={() => (current_idx = idx)}>
|
||||
<td>{drawing.b_id}</td>
|
||||
<td
|
||||
><input
|
||||
type="number"
|
||||
id="{idx}_wt"
|
||||
bind:value={drawing.winning_ticket}
|
||||
onfocus={focusElement}
|
||||
onchange={async () => {
|
||||
drawing.changed = true;
|
||||
const res = await fetch(
|
||||
`/api/tickets/${prefix.name}/${drawing.winning_ticket}`,
|
||||
);
|
||||
if (res.ok) {
|
||||
const t_data = await res.json();
|
||||
drawing.winner = `${t_data.last_name}, ${t_data.first_name}`;
|
||||
}
|
||||
}}
|
||||
/></td
|
||||
>
|
||||
<td>{drawing.winner}</td>
|
||||
<td
|
||||
><button tabindex="-1">{drawing.changed ? "Y" : "N"}</button
|
||||
></td
|
||||
>
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -155,7 +202,8 @@
|
||||
background: transparent;
|
||||
border: solid 1px #000000;
|
||||
}
|
||||
input, button {
|
||||
input,
|
||||
button {
|
||||
display: block;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
|
||||
@@ -1,33 +1,53 @@
|
||||
<script>
|
||||
import { env } from '$env/dynamic/public';
|
||||
import { browser } from '$app/environment';
|
||||
import { env } from "$env/dynamic/public";
|
||||
import { browser } from "$app/environment";
|
||||
|
||||
const { data } = $props();
|
||||
const prefix = {...data.prefix};
|
||||
const report_data = data.report;
|
||||
let show_data = $state([...report_data]);
|
||||
let report_subject = $state("All Preferences");
|
||||
|
||||
if (browser) {
|
||||
document.title = `${prefix.name} Report By Basket ID`
|
||||
const prefix = $derived(data.prefix);
|
||||
const report_data = $derived(data.report);
|
||||
function copyReportData() {
|
||||
return [...report_data];
|
||||
}
|
||||
let show_data = $state(copyReportData());
|
||||
let report_subject = $state("All Preferences");
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>{prefix.name} Report By Basket ID</title>
|
||||
</svelte:head>
|
||||
|
||||
<div id="reportheader">
|
||||
<div class="flex-row-space {prefix.color}">
|
||||
<div class="flex-row">
|
||||
<button class="styled" onclick={() => {
|
||||
show_data = [...report_data];
|
||||
report_subject = "All Preferences";
|
||||
}}>All Preferences</button>
|
||||
<button class="styled" onclick={() => {
|
||||
show_data = [...report_data.filter((entry) => entry.preference === "CALL")];
|
||||
report_subject = "CALL Preference"
|
||||
}}>Call</button>
|
||||
<button class="styled" onclick={() => {
|
||||
show_data = [...report_data.filter((entry) => entry.preference === "TEXT")];
|
||||
report_subject = "TEXT Preference";
|
||||
}}>Text</button>
|
||||
<button
|
||||
class="styled"
|
||||
onclick={() => {
|
||||
show_data = copyReportData();
|
||||
report_subject = "All Preferences";
|
||||
}}>All Preferences</button
|
||||
>
|
||||
<button
|
||||
class="styled"
|
||||
onclick={() => {
|
||||
show_data = [
|
||||
...report_data.filter(
|
||||
(entry) => entry.preference === "CALL",
|
||||
),
|
||||
];
|
||||
report_subject = "CALL Preference";
|
||||
}}>Call</button
|
||||
>
|
||||
<button
|
||||
class="styled"
|
||||
onclick={() => {
|
||||
show_data = [
|
||||
...report_data.filter(
|
||||
(entry) => entry.preference === "TEXT",
|
||||
),
|
||||
];
|
||||
report_subject = "TEXT Preference";
|
||||
}}>Text</button
|
||||
>
|
||||
</div>
|
||||
<div class="flex-row">
|
||||
<button class="styled" onclick={() => window.print()}>Print</button>
|
||||
@@ -35,35 +55,37 @@
|
||||
</div>
|
||||
</div>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th colspan="90"><h1>{prefix.name} - Report - {report_subject}</h1></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Basket ID</th>
|
||||
<th>Description</th>
|
||||
<th>Ticket #</th>
|
||||
<th>Winner Name</th>
|
||||
<th>Phone Number</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each show_data as report_entry}
|
||||
<tr>
|
||||
<td>{report_entry.b_id}</td>
|
||||
<td>{report_entry.description}</td>
|
||||
<td>{report_entry.winning_ticket}</td>
|
||||
<td>{report_entry.winner_name}</td>
|
||||
<td>{report_entry.phone_number}</td>
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="3">{env.PUBLIC_TAM3_VENUE || ""}</td>
|
||||
<td colspan="2" style="text-align: right">TAM3 by Dilan Gilluly</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
<thead>
|
||||
<tr>
|
||||
<th colspan="90"
|
||||
><h1>{prefix.name} - Report - {report_subject}</h1></th
|
||||
>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Basket ID</th>
|
||||
<th>Description</th>
|
||||
<th>Ticket #</th>
|
||||
<th>Winner Name</th>
|
||||
<th>Phone Number</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each show_data as report_entry}
|
||||
<tr>
|
||||
<td>{report_entry.b_id}</td>
|
||||
<td>{report_entry.description}</td>
|
||||
<td>{report_entry.winning_ticket}</td>
|
||||
<td>{report_entry.winner_name}</td>
|
||||
<td>{report_entry.phone_number}</td>
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="3">{env.PUBLIC_TAM3_VENUE || ""}</td>
|
||||
<td colspan="2" style="text-align: right">TAM3 by Dilan Gilluly</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
|
||||
<style>
|
||||
@@ -76,7 +98,6 @@
|
||||
border: solid 1px black;
|
||||
padding: 0.2rem;
|
||||
}
|
||||
|
||||
}
|
||||
table tbody tr:nth-child(2n) {
|
||||
background-color: #dddddd;
|
||||
|
||||
@@ -1,33 +1,53 @@
|
||||
<script>
|
||||
import { env } from '$env/dynamic/public';
|
||||
import { browser } from '$app/environment';
|
||||
import { env } from "$env/dynamic/public";
|
||||
import { browser } from "$app/environment";
|
||||
|
||||
const { data } = $props();
|
||||
const prefix = {...data.prefix};
|
||||
const report_data = data.report;
|
||||
let show_data = $state([...report_data]);
|
||||
let report_subject = $state("All Preferences");
|
||||
|
||||
if (browser) {
|
||||
document.title = `${prefix.name} Report By Name`
|
||||
const prefix = $derived(data.prefix);
|
||||
const report_data = $derived(data.report);
|
||||
function copyReportData() {
|
||||
return [...report_data];
|
||||
}
|
||||
let show_data = $state(copyReportData());
|
||||
let report_subject = $state("All Preferences");
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>{prefix.name} Report By Name</title>
|
||||
</svelte:head>
|
||||
|
||||
<div id="reportheader">
|
||||
<div class="flex-row-space {prefix.color}">
|
||||
<div class="flex-row">
|
||||
<button class="styled" onclick={() => {
|
||||
show_data = [...report_data];
|
||||
report_subject = "All Preferences";
|
||||
}}>All Preferences</button>
|
||||
<button class="styled" onclick={() => {
|
||||
show_data = [...report_data.filter((entry) => entry.preference === "CALL")];
|
||||
report_subject = "CALL Preference"
|
||||
}}>Call</button>
|
||||
<button class="styled" onclick={() => {
|
||||
show_data = [...report_data.filter((entry) => entry.preference === "TEXT")];
|
||||
report_subject = "TEXT Preference";
|
||||
}}>Text</button>
|
||||
<button
|
||||
class="styled"
|
||||
onclick={() => {
|
||||
show_data = copyReportData();
|
||||
report_subject = "All Preferences";
|
||||
}}>All Preferences</button
|
||||
>
|
||||
<button
|
||||
class="styled"
|
||||
onclick={() => {
|
||||
show_data = [
|
||||
...report_data.filter(
|
||||
(entry) => entry.preference === "CALL",
|
||||
),
|
||||
];
|
||||
report_subject = "CALL Preference";
|
||||
}}>Call</button
|
||||
>
|
||||
<button
|
||||
class="styled"
|
||||
onclick={() => {
|
||||
show_data = [
|
||||
...report_data.filter(
|
||||
(entry) => entry.preference === "TEXT",
|
||||
),
|
||||
];
|
||||
report_subject = "TEXT Preference";
|
||||
}}>Text</button
|
||||
>
|
||||
</div>
|
||||
<div class="flex-row">
|
||||
<button class="styled" onclick={() => window.print()}>Print</button>
|
||||
@@ -35,35 +55,37 @@
|
||||
</div>
|
||||
</div>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th colspan="90"><h1>{prefix.name} - Report - {report_subject}</h1></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Winner Name</th>
|
||||
<th>Phone Number</th>
|
||||
<th>Basket ID</th>
|
||||
<th>Ticket #</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each show_data as report_entry}
|
||||
<tr>
|
||||
<td>{report_entry.winner_name}</td>
|
||||
<td>{report_entry.phone_number}</td>
|
||||
<td>{report_entry.b_id}</td>
|
||||
<td>{report_entry.winning_ticket}</td>
|
||||
<td>{report_entry.description}</td>
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="3">{env.PUBLIC_TAM3_VENUE || ""}</td>
|
||||
<td colspan="2" style="text-align: right">TAM3 by Dilan Gilluly</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
<thead>
|
||||
<tr>
|
||||
<th colspan="90"
|
||||
><h1>{prefix.name} - Report - {report_subject}</h1></th
|
||||
>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Winner Name</th>
|
||||
<th>Phone Number</th>
|
||||
<th>Basket ID</th>
|
||||
<th>Ticket #</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each show_data as report_entry}
|
||||
<tr>
|
||||
<td>{report_entry.winner_name}</td>
|
||||
<td>{report_entry.phone_number}</td>
|
||||
<td>{report_entry.b_id}</td>
|
||||
<td>{report_entry.winning_ticket}</td>
|
||||
<td>{report_entry.description}</td>
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="3">{env.PUBLIC_TAM3_VENUE || ""}</td>
|
||||
<td colspan="2" style="text-align: right">TAM3 by Dilan Gilluly</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
|
||||
<style>
|
||||
@@ -76,7 +98,6 @@
|
||||
border: solid 1px black;
|
||||
padding: 0.2rem;
|
||||
}
|
||||
|
||||
}
|
||||
table tbody tr:nth-child(2n) {
|
||||
background-color: #dddddd;
|
||||
|
||||
@@ -1,27 +1,39 @@
|
||||
<script>
|
||||
import { browser } from '$app/environment';
|
||||
import { browser } from "$app/environment";
|
||||
const { data } = $props();
|
||||
|
||||
let stagingSettings = $state({...data.settings});
|
||||
let status = $state("")
|
||||
function copySettings() {
|
||||
return { ...data.settings };
|
||||
}
|
||||
let stagingSettings = $state(copySettings());
|
||||
let status = $state("");
|
||||
|
||||
async function saveChanges() {
|
||||
const res = await fetch('/api/settings', {method: 'POST', body: JSON.stringify(stagingSettings), headers: {'Content-Type': 'application/json'}});
|
||||
const res = await fetch("/api/settings", {
|
||||
method: "POST",
|
||||
body: JSON.stringify(stagingSettings),
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
if (res.ok) {
|
||||
status = "Changes saved successfully";
|
||||
setTimeout(() => {status = ""}, 5000);
|
||||
setTimeout(() => {
|
||||
status = "";
|
||||
}, 5000);
|
||||
} else {
|
||||
status = "Error saving changes, check config file path, make sure folder exists";
|
||||
setTimeout(() => {status = ""}, 5000);
|
||||
status =
|
||||
"Error saving changes, check config file path, make sure folder exists";
|
||||
setTimeout(() => {
|
||||
status = "";
|
||||
}, 5000);
|
||||
}
|
||||
}
|
||||
|
||||
function cancelChanges() {
|
||||
stagingSettings = {...data.settings};
|
||||
stagingSettings = { ...data.settings };
|
||||
}
|
||||
|
||||
if (browser) {
|
||||
document.title = "TAM3 - Settings"
|
||||
document.title = "TAM3 - Settings";
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -31,11 +43,16 @@
|
||||
<h2>Remote Server</h2>
|
||||
<div><strong>Address:</strong></div>
|
||||
<div><em>For example: https://ip_or_hostname:8443</em></div>
|
||||
<div><input type="text" bind:value={stagingSettings.TAM3_REMOTE}></div>
|
||||
<div><input type="text" bind:value={stagingSettings.TAM3_REMOTE} /></div>
|
||||
<div><strong>API Key:</strong></div>
|
||||
<div class="flex-row">
|
||||
<input type="password" bind:value={stagingSettings.TAM3_REMOTE_KEY}>
|
||||
<button class="styled" onclick={() => {stagingSettings.TAM3_REMOTE_KEY = ""}}>Clear</button>
|
||||
<input type="password" bind:value={stagingSettings.TAM3_REMOTE_KEY} />
|
||||
<button
|
||||
class="styled"
|
||||
onclick={() => {
|
||||
stagingSettings.TAM3_REMOTE_KEY = "";
|
||||
}}>Clear</button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
128
webapp/src/routes/sheets/+page.svelte
Normal file
128
webapp/src/routes/sheets/+page.svelte
Normal file
@@ -0,0 +1,128 @@
|
||||
<script>
|
||||
let formData = $state({ startNumber: 0, endNumber: 0, perPage: 20 });
|
||||
let currentRows = $state([]);
|
||||
|
||||
function selectOnFocus(e) {
|
||||
e.target.select();
|
||||
}
|
||||
|
||||
function loadRows() {
|
||||
currentRows = [];
|
||||
for (let i = formData.startNumber; i <= formData.endNumber; i++) {
|
||||
currentRows = [...currentRows, i];
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Print Ticket Sheets</title>
|
||||
</svelte:head>
|
||||
|
||||
<div id="header">
|
||||
<h1>Print Ticket Sheets</h1>
|
||||
<div class="flex-row-space">
|
||||
<div class="flex-row">
|
||||
<div>
|
||||
<div>Start Number</div>
|
||||
<input
|
||||
type="number"
|
||||
onfocus={selectOnFocus}
|
||||
bind:value={formData.startNumber}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<div>Ending Number</div>
|
||||
<input
|
||||
type="number"
|
||||
onfocus={selectOnFocus}
|
||||
bind:value={formData.endNumber}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<div>Per Page</div>
|
||||
<input
|
||||
type="number"
|
||||
onfocus={selectOnFocus}
|
||||
bind:value={formData.perPage}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<button class="styled" onclick={loadRows}>Load</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-row">
|
||||
<button class="styled" onclick={() => window.print()}>Print</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table id="main_table">
|
||||
<colgroup>
|
||||
<col style="width: 15%" />
|
||||
<col style="width: 40%" />
|
||||
<col style="width: 35%" />
|
||||
<col style="width: 10%" />
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Ticket #</th>
|
||||
<th>Name</th>
|
||||
<th>Phone Number</th>
|
||||
<th>Text?</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody style="height: 100%">
|
||||
{#each currentRows as row, idx}
|
||||
{#if idx !== 0 && idx % formData.perPage === 0}
|
||||
<tr class="pagebreak"></tr>
|
||||
{/if}
|
||||
<tr>
|
||||
<td><strong>{row}</strong></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<style>
|
||||
#main_table {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
text-align: left;
|
||||
table-layout: fixed;
|
||||
th,
|
||||
td {
|
||||
border: solid black 1px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
@media print {
|
||||
#header {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#main_table {
|
||||
table-layout: fixed;
|
||||
}
|
||||
|
||||
#main_table tbody {
|
||||
font-size: 16pt;
|
||||
}
|
||||
|
||||
#main_table tbody tr {
|
||||
height: 32pt;
|
||||
}
|
||||
|
||||
#main_table tbody tr.pagebreak {
|
||||
break-after: page;
|
||||
}
|
||||
|
||||
@page:after {
|
||||
content: "My Text";
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,16 +1,16 @@
|
||||
<script>
|
||||
import { browser } from '$app/environment';
|
||||
import FormHeader from '$lib/components/FormHeader.svelte';
|
||||
import { focusElement } from '$lib/focusElement.js';
|
||||
import { browser } from "$app/environment";
|
||||
import FormHeader from "$lib/components/FormHeader.svelte";
|
||||
import { focusElement } from "$lib/focusElement.js";
|
||||
|
||||
const { data } = $props();
|
||||
let prefix = {...data.prefix};
|
||||
let pagerForm = $state({id_from: 0, id_to: 0});
|
||||
const prefix = $derived(data.prefix);
|
||||
let pagerForm = $state({ id_from: 0, id_to: 0 });
|
||||
let current_idx = $state(0);
|
||||
let next_idx = $derived(current_idx+1);
|
||||
let prev_idx = $derived(current_idx-1);
|
||||
let next_idx = $derived(current_idx + 1);
|
||||
let prev_idx = $derived(current_idx - 1);
|
||||
let current_tickets = $state([]);
|
||||
let copy_buffer = $state({prefix: prefix.name, t_id: 0, first_name: "", last_name: "", phone_number: "", preference: "CALL", changed: true});
|
||||
let copy_buffer = $state({});
|
||||
let headerHeight = $state();
|
||||
|
||||
function changeFocus(idx) {
|
||||
@@ -22,42 +22,55 @@
|
||||
|
||||
const functions = {
|
||||
refreshPage: async () => {
|
||||
if (current_tickets.filter(ticket => ticket.changed === true).length > 0) {
|
||||
if (
|
||||
current_tickets.filter((ticket) => ticket.changed === true)
|
||||
.length > 0
|
||||
) {
|
||||
functions.saveAll();
|
||||
};
|
||||
const res = await fetch(`/api/tickets/${prefix.name}/${pagerForm.id_from}/${pagerForm.id_to}`);
|
||||
}
|
||||
const res = await fetch(
|
||||
`/api/tickets/${prefix.name}/${pagerForm.id_from}/${pagerForm.id_to}`,
|
||||
);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
current_tickets = [...data];
|
||||
setTimeout(() => changeFocus(0), 100);
|
||||
};
|
||||
}
|
||||
},
|
||||
prevPage: () => {
|
||||
const diff = current_tickets.length;
|
||||
pagerForm.id_from = pagerForm.id_from - diff;
|
||||
pagerForm.id_to = pagerForm.id_to - diff;
|
||||
functions.refreshPage()
|
||||
functions.refreshPage();
|
||||
},
|
||||
nextPage: () => {
|
||||
const diff = current_tickets.length;
|
||||
pagerForm.id_from = pagerForm.id_from + diff;
|
||||
pagerForm.id_to = pagerForm.id_to + diff;
|
||||
functions.refreshPage()
|
||||
functions.refreshPage();
|
||||
},
|
||||
duplicateDown: () => {
|
||||
if (current_tickets[next_idx]) {
|
||||
current_tickets[next_idx] = {...current_tickets[current_idx], t_id: current_tickets[next_idx].t_id, changed: true};
|
||||
current_tickets[next_idx] = {
|
||||
...current_tickets[current_idx],
|
||||
t_id: current_tickets[next_idx].t_id,
|
||||
changed: true,
|
||||
};
|
||||
changeFocus(next_idx);
|
||||
} else {
|
||||
changeFocus(current_idx)
|
||||
changeFocus(current_idx);
|
||||
}
|
||||
},
|
||||
duplicateUp: () => {
|
||||
if (prev_idx >= 0) {
|
||||
current_tickets[prev_idx] = {...current_tickets[current_idx], t_id: current_tickets[prev_idx].t_id, changed: true};
|
||||
current_tickets[prev_idx] = {
|
||||
...current_tickets[current_idx],
|
||||
t_id: current_tickets[prev_idx].t_id,
|
||||
changed: true,
|
||||
};
|
||||
changeFocus(prev_idx);
|
||||
} else {
|
||||
changeFocus(current_idx)
|
||||
changeFocus(current_idx);
|
||||
}
|
||||
},
|
||||
gotoNext: () => {
|
||||
@@ -75,37 +88,58 @@
|
||||
}
|
||||
},
|
||||
copy: () => {
|
||||
copy_buffer = {...current_tickets[current_idx]};
|
||||
copy_buffer = { ...current_tickets[current_idx] };
|
||||
changeFocus(current_idx);
|
||||
disablePaste = false;
|
||||
},
|
||||
paste: () => {
|
||||
current_tickets[current_idx] = {...copy_buffer, t_id: current_tickets[current_idx].t_id, changed: true};
|
||||
if (Object.keys(copy_buffer).length !== 0) {
|
||||
current_tickets[current_idx] = {
|
||||
...copy_buffer,
|
||||
t_id: current_tickets[current_idx].t_id,
|
||||
changed: true,
|
||||
};
|
||||
}
|
||||
changeFocus(current_idx);
|
||||
},
|
||||
saveAll: async () => {
|
||||
const to_save = current_tickets.filter((ticket) => ticket.changed === true);
|
||||
const res = await fetch(`/api/tickets`, {body: JSON.stringify(to_save), method: 'POST', headers: {'Content-Type': 'application/json'}});
|
||||
const to_save = current_tickets.filter(
|
||||
(ticket) => ticket.changed === true,
|
||||
);
|
||||
const res = await fetch(`/api/tickets`, {
|
||||
body: JSON.stringify(to_save),
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
if (res.ok) {
|
||||
for (let ticket of current_tickets) {ticket.changed = false};
|
||||
for (let ticket of current_tickets) {
|
||||
ticket.changed = false;
|
||||
}
|
||||
changeFocus(0);
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
if (browser) {
|
||||
document.title = `${prefix.name} Ticket Entry`;
|
||||
window.addEventListener("beforeunload", function(e) {
|
||||
if (current_tickets.filter(ticket => ticket.changed === true).length > 0) {
|
||||
window.addEventListener("beforeunload", function (e) {
|
||||
if (
|
||||
current_tickets.filter((ticket) => ticket.changed === true)
|
||||
.length > 0
|
||||
) {
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>{prefix.name} Ticket Entry</title>
|
||||
</svelte:head>
|
||||
|
||||
<h1>{prefix.name} Ticket Entry</h1>
|
||||
<FormHeader {prefix} {functions} bind:pagerForm bind:headerHeight />
|
||||
<table>
|
||||
<thead style="top: {headerHeight+2}px">
|
||||
<thead style="top: {headerHeight + 2}px">
|
||||
<tr>
|
||||
<th style="width: 12ch">Ticket ID</th>
|
||||
<th>First Name</th>
|
||||
@@ -117,17 +151,55 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each current_tickets as ticket, idx}
|
||||
<tr onfocusin={() => current_idx = idx}>
|
||||
<td>{ticket.t_id}</td>
|
||||
<td><input id="{idx}_fn" type="text" bind:value={ticket.first_name} onfocus={focusElement} onchange={() => ticket.changed = true}></td>
|
||||
<td><input id="{idx}_ln" type="text" bind:value={ticket.last_name} onfocus={focusElement} onchange={() => ticket.changed = true}></td>
|
||||
<td><input id="{idx}_pn" type="text" bind:value={ticket.phone_number} onfocus={focusElement} onchange={() => ticket.changed = true}></td>
|
||||
<td><select id="{idx}_pr" style="width: 100%" bind:value={ticket.preference} onfocus={focusElement} onchange={() => ticket.changed = true}>
|
||||
<option value="CALL">Call</option>
|
||||
<option value="TEXT">Text</option>
|
||||
</select></td>
|
||||
<td><button tabindex="-1" onclick={() => ticket.changed = !ticket.changed}>{ticket.changed ? "Y" : "N"}</button></td>
|
||||
</tr>
|
||||
<tr onfocusin={() => (current_idx = idx)}>
|
||||
<td>{ticket.t_id}</td>
|
||||
<td
|
||||
><input
|
||||
id="{idx}_fn"
|
||||
type="text"
|
||||
bind:value={ticket.first_name}
|
||||
onfocus={focusElement}
|
||||
onchange={() => (ticket.changed = true)}
|
||||
/></td
|
||||
>
|
||||
<td
|
||||
><input
|
||||
id="{idx}_ln"
|
||||
type="text"
|
||||
bind:value={ticket.last_name}
|
||||
onfocus={focusElement}
|
||||
onchange={() => (ticket.changed = true)}
|
||||
/></td
|
||||
>
|
||||
<td
|
||||
><input
|
||||
id="{idx}_pn"
|
||||
type="text"
|
||||
bind:value={ticket.phone_number}
|
||||
onfocus={focusElement}
|
||||
onchange={() => (ticket.changed = true)}
|
||||
/></td
|
||||
>
|
||||
<td
|
||||
><select
|
||||
id="{idx}_pr"
|
||||
style="width: 100%"
|
||||
bind:value={ticket.preference}
|
||||
onfocus={focusElement}
|
||||
onchange={() => (ticket.changed = true)}
|
||||
>
|
||||
<option value="CALL">Call</option>
|
||||
<option value="TEXT">Text</option>
|
||||
</select></td
|
||||
>
|
||||
<td
|
||||
><button
|
||||
tabindex="-1"
|
||||
onclick={() => (ticket.changed = !ticket.changed)}
|
||||
>{ticket.changed ? "Y" : "N"}</button
|
||||
></td
|
||||
>
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -156,7 +228,8 @@
|
||||
background: transparent;
|
||||
border: solid 1px #000000;
|
||||
}
|
||||
input, button {
|
||||
input,
|
||||
button {
|
||||
display: block;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
|
||||
Reference in New Issue
Block a user