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