Compare commits
8 Commits
780706ce4a
...
17a1ea8524
| Author | SHA1 | Date | |
|---|---|---|---|
| 17a1ea8524 | |||
| bbdb684a8a | |||
| f88c8dc7ed | |||
| 54d154e445 | |||
| b9aea2e501 | |||
| b4552f7d50 | |||
| f4fcb2e745 | |||
| 965504ed4e |
@ -11,7 +11,7 @@
|
|||||||
import type { Race } from "$lib/schema";
|
import type { Race } from "$lib/schema";
|
||||||
import { RACE_PICTOGRAM_HEIGHT, RACE_PICTOGRAM_WIDTH } from "$lib/config";
|
import { RACE_PICTOGRAM_HEIGHT, RACE_PICTOGRAM_WIDTH } from "$lib/config";
|
||||||
import { get_race_pictogram_template } from "$lib/database";
|
import { get_race_pictogram_template } from "$lib/database";
|
||||||
import { format_date } from "$lib/date";
|
import { format_date, isodatetimeformat } from "$lib/date";
|
||||||
import { get_error_toast } from "$lib/toast";
|
import { get_error_toast } from "$lib/toast";
|
||||||
import { pb } from "$lib/pocketbase";
|
import { pb } from "$lib/pocketbase";
|
||||||
import { error } from "@sveltejs/kit";
|
import { error } from "@sveltejs/kit";
|
||||||
@ -38,12 +38,14 @@
|
|||||||
const toastStore: ToastStore = getToastStore();
|
const toastStore: ToastStore = getToastStore();
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
const labelwidth = "80px";
|
const labelwidth = "85px";
|
||||||
const dateformat: string = "yyyy-MM-dd'T'HH:mm";
|
|
||||||
|
|
||||||
const clear_sprint = () => {
|
const clear_sprint = () => {
|
||||||
(document.getElementById("sqdate") as HTMLInputElement).value = "";
|
(document.getElementById("sqdate") as HTMLInputElement).value = "";
|
||||||
(document.getElementById("sdate") as HTMLInputElement).value = "";
|
(document.getElementById("sdate") as HTMLInputElement).value = "";
|
||||||
|
|
||||||
|
sprintqualidate_value = "";
|
||||||
|
sprintdate_value = "";
|
||||||
};
|
};
|
||||||
|
|
||||||
// Reactive state
|
// Reactive state
|
||||||
@ -58,14 +60,16 @@
|
|||||||
let racedate_value: string = $state("");
|
let racedate_value: string = $state("");
|
||||||
let pictogram_value: FileList | undefined = $state();
|
let pictogram_value: FileList | undefined = $state();
|
||||||
|
|
||||||
|
// Set the initial values if we've clicked on an existing race
|
||||||
|
// PocketBase stores in UTC, so resulting values will be offset by 1h here
|
||||||
if (race) {
|
if (race) {
|
||||||
if (race.sprintqualidate && race.sprintdate) {
|
if (race.sprintqualidate && race.sprintdate) {
|
||||||
sprintqualidate_value = format_date(race.sprintqualidate, dateformat);
|
sprintqualidate_value = format_date(race.sprintqualidate, isodatetimeformat);
|
||||||
sprintdate_value = format_date(race.sprintdate, dateformat);
|
sprintdate_value = format_date(race.sprintdate, isodatetimeformat);
|
||||||
}
|
}
|
||||||
|
|
||||||
qualidate_value = format_date(race.qualidate, dateformat);
|
qualidate_value = format_date(race.qualidate, isodatetimeformat);
|
||||||
racedate_value = format_date(race.racedate, dateformat);
|
racedate_value = format_date(race.racedate, isodatetimeformat);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Database actions
|
// Database actions
|
||||||
@ -119,6 +123,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Use toISOString here, as we want to convert from localtime to UTC, which PocketBase uses
|
||||||
const race_data = {
|
const race_data = {
|
||||||
name: name_value,
|
name: name_value,
|
||||||
step: step_value,
|
step: step_value,
|
||||||
@ -126,11 +131,11 @@
|
|||||||
sprintqualidate:
|
sprintqualidate:
|
||||||
sprintqualidate_value && sprintqualidate_value !== ""
|
sprintqualidate_value && sprintqualidate_value !== ""
|
||||||
? new Date(sprintqualidate_value).toISOString()
|
? new Date(sprintqualidate_value).toISOString()
|
||||||
: undefined,
|
: null,
|
||||||
sprintdate:
|
sprintdate:
|
||||||
sprintdate_value && sprintdate_value != ""
|
sprintdate_value && sprintdate_value != ""
|
||||||
? new Date(sprintdate_value).toISOString()
|
? new Date(sprintdate_value).toISOString()
|
||||||
: undefined,
|
: null,
|
||||||
qualidate: new Date(qualidate_value).toISOString(),
|
qualidate: new Date(qualidate_value).toISOString(),
|
||||||
racedate: new Date(racedate_value).toISOString(),
|
racedate: new Date(racedate_value).toISOString(),
|
||||||
pictogram: pictogram_avif,
|
pictogram: pictogram_avif,
|
||||||
@ -214,9 +219,9 @@
|
|||||||
<!-- NOTE: Input datetime-local accepts YYYY-mm-ddTHH:MM format -->
|
<!-- NOTE: Input datetime-local accepts YYYY-mm-ddTHH:MM format -->
|
||||||
<Input
|
<Input
|
||||||
id="sqdate"
|
id="sqdate"
|
||||||
|
type="datetime-local"
|
||||||
bind:value={sprintqualidate_value}
|
bind:value={sprintqualidate_value}
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
type="datetime-local"
|
|
||||||
{labelwidth}
|
{labelwidth}
|
||||||
{disabled}
|
{disabled}
|
||||||
>
|
>
|
||||||
@ -224,18 +229,18 @@
|
|||||||
</Input>
|
</Input>
|
||||||
<Input
|
<Input
|
||||||
id="sdate"
|
id="sdate"
|
||||||
|
type="datetime-local"
|
||||||
bind:value={sprintdate_value}
|
bind:value={sprintdate_value}
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
type="datetime-local"
|
|
||||||
{labelwidth}
|
{labelwidth}
|
||||||
{disabled}
|
{disabled}
|
||||||
>
|
>
|
||||||
SRace
|
SRace
|
||||||
</Input>
|
</Input>
|
||||||
<Input
|
<Input
|
||||||
|
type="datetime-local"
|
||||||
bind:value={qualidate_value}
|
bind:value={qualidate_value}
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
type="datetime-local"
|
|
||||||
{labelwidth}
|
{labelwidth}
|
||||||
{disabled}
|
{disabled}
|
||||||
{required}
|
{required}
|
||||||
@ -243,9 +248,9 @@
|
|||||||
Quali
|
Quali
|
||||||
</Input>
|
</Input>
|
||||||
<Input
|
<Input
|
||||||
|
type="datetime-local"
|
||||||
bind:value={racedate_value}
|
bind:value={racedate_value}
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
type="datetime-local"
|
|
||||||
{labelwidth}
|
{labelwidth}
|
||||||
{disabled}
|
{disabled}
|
||||||
{required}
|
{required}
|
||||||
|
|||||||
@ -26,7 +26,7 @@
|
|||||||
|
|
||||||
<div class="input-group input-group-divider grid-cols-[auto_1fr_auto]">
|
<div class="input-group input-group-divider grid-cols-[auto_1fr_auto]">
|
||||||
<div
|
<div
|
||||||
class="input-group-shim select-none text-nowrap text-neutral-900"
|
class="input-group-shim select-none text-nowrap border-r text-neutral-900"
|
||||||
style="width: {labelwidth};"
|
style="width: {labelwidth};"
|
||||||
>
|
>
|
||||||
{@render children()}
|
{@render children()}
|
||||||
|
|||||||
@ -1,4 +1,28 @@
|
|||||||
import { format } from "date-fns";
|
import { format } from "date-fns";
|
||||||
|
|
||||||
export const format_date = (date: string, formatstring: string): string =>
|
/**
|
||||||
|
* 2025-03-28T17:35
|
||||||
|
*/
|
||||||
|
export const isodatetimeformat: string = "yyyy-MM-dd'T'HH:mm";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 28.03. 17:35
|
||||||
|
*/
|
||||||
|
export const shortdatetimeformat: string = "dd.MM.' 'HH:mm";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 2025-03-28
|
||||||
|
*/
|
||||||
|
export const isodateformat: string = "yyyy-MM-dd";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 17:35
|
||||||
|
*/
|
||||||
|
export const timeformat: string = "HH:mm";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format a [Date] object using a [date-fns] formatstring.
|
||||||
|
* This function uses localtime instead of UTC.
|
||||||
|
*/
|
||||||
|
export const format_date = <T extends Date | string>(date: T, formatstring: string): string =>
|
||||||
format(new Date(date), formatstring);
|
format(new Date(date), formatstring);
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
import type { PageData } from "./$types";
|
import type { PageData } from "./$types";
|
||||||
import { get_by_value } from "$lib/database";
|
import { get_by_value } from "$lib/database";
|
||||||
import type { Race } from "$lib/schema";
|
import type { Race } from "$lib/schema";
|
||||||
|
import { format_date, shortdatetimeformat } from "$lib/date";
|
||||||
|
|
||||||
let { data }: { data: PageData } = $props();
|
let { data }: { data: PageData } = $props();
|
||||||
|
|
||||||
@ -26,7 +27,7 @@
|
|||||||
modalStore.trigger(modalSettings);
|
modalStore.trigger(modalSettings);
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: Displayed dates differ from actual dates by 1 hour
|
// The date value functions convert UTC from PocketBase to localtime
|
||||||
const races_columns: TableColumn[] = $derived([
|
const races_columns: TableColumn[] = $derived([
|
||||||
{
|
{
|
||||||
data_value_name: "name",
|
data_value_name: "name",
|
||||||
@ -38,22 +39,22 @@
|
|||||||
{
|
{
|
||||||
data_value_name: "sprintqualidate",
|
data_value_name: "sprintqualidate",
|
||||||
label: "Sprint Quali",
|
label: "Sprint Quali",
|
||||||
valuefun: async (value: string): Promise<string> => value.slice(0, -5), // Cutoff the "Z" from the ISO datetime
|
valuefun: async (value: string): Promise<string> => format_date(value, shortdatetimeformat),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
data_value_name: "sprintdate",
|
data_value_name: "sprintdate",
|
||||||
label: "Sprint Race",
|
label: "Sprint Race",
|
||||||
valuefun: async (value: string): Promise<string> => value.slice(0, -5),
|
valuefun: async (value: string): Promise<string> => format_date(value, shortdatetimeformat),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
data_value_name: "qualidate",
|
data_value_name: "qualidate",
|
||||||
label: "Quali",
|
label: "Quali",
|
||||||
valuefun: async (value: string): Promise<string> => value.slice(0, -5),
|
valuefun: async (value: string): Promise<string> => format_date(value, shortdatetimeformat),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
data_value_name: "racedate",
|
data_value_name: "racedate",
|
||||||
label: "Race",
|
label: "Race",
|
||||||
valuefun: async (value: string): Promise<string> => value.slice(0, -5),
|
valuefun: async (value: string): Promise<string> => format_date(value, shortdatetimeformat),
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -19,7 +19,7 @@
|
|||||||
RACE_PICTOGRAM_HEIGHT,
|
RACE_PICTOGRAM_HEIGHT,
|
||||||
RACE_PICTOGRAM_WIDTH,
|
RACE_PICTOGRAM_WIDTH,
|
||||||
} from "$lib/config";
|
} from "$lib/config";
|
||||||
import { format_date } from "$lib/date";
|
import { format_date, shortdatetimeformat } from "$lib/date";
|
||||||
import type { CurrentPickedUser, RacePick } from "$lib/schema";
|
import type { CurrentPickedUser, RacePick } from "$lib/schema";
|
||||||
import { get_by_value, get_driver_headshot_template } from "$lib/database";
|
import { get_by_value, get_driver_headshot_template } from "$lib/database";
|
||||||
|
|
||||||
@ -53,8 +53,6 @@
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
const dateformat: string = "dd.MM' 'HH:mm";
|
|
||||||
|
|
||||||
const race_popupsettings = (target: string): PopupSettings => {
|
const race_popupsettings = (target: string): PopupSettings => {
|
||||||
return {
|
return {
|
||||||
event: "click",
|
event: "click",
|
||||||
@ -87,20 +85,21 @@
|
|||||||
{#if data.currentrace.sprintdate}
|
{#if data.currentrace.sprintdate}
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<span class="w-12">SQuali:</span>
|
<span class="w-12">SQuali:</span>
|
||||||
<span>{format_date(data.currentrace.sprintqualidate, dateformat)}</span>
|
<span>{format_date(data.currentrace.sprintqualidate, shortdatetimeformat)}</span
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<span class="w-12">SRace:</span>
|
<span class="w-12">SRace:</span>
|
||||||
<span>{format_date(data.currentrace.sprintdate, dateformat)}</span>
|
<span>{format_date(data.currentrace.sprintdate, shortdatetimeformat)}</span>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<span class="w-12">Quali:</span>
|
<span class="w-12">Quali:</span>
|
||||||
<span>{format_date(data.currentrace.qualidate, dateformat)}</span>
|
<span>{format_date(data.currentrace.qualidate, shortdatetimeformat)}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<span class="w-12">Race:</span>
|
<span class="w-12">Race:</span>
|
||||||
<span>{format_date(data.currentrace.racedate, dateformat)}</span>
|
<span>{format_date(data.currentrace.racedate, shortdatetimeformat)}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="m-auto flex">
|
<div class="m-auto flex">
|
||||||
<div class="mr-1 mt-1">
|
<div class="mr-1 mt-1">
|
||||||
@ -255,7 +254,7 @@
|
|||||||
{race?.step}: {race?.name}
|
{race?.step}: {race?.name}
|
||||||
</span>
|
</span>
|
||||||
<span class="hidden text-sm lg:block">
|
<span class="hidden text-sm lg:block">
|
||||||
Date: {format_date(race?.racedate ?? "", dateformat)}
|
Date: {format_date(race?.racedate ?? "", shortdatetimeformat)}
|
||||||
</span>
|
</span>
|
||||||
<span class="hidden text-sm lg:block">Guessed: P{race?.pxx}</span>
|
<span class="hidden text-sm lg:block">Guessed: P{race?.pxx}</span>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user