Further improvements on the open hours endpoints
This commit is contained in:
@@ -2,27 +2,74 @@ public static class LokEndpoints
|
||||
{
|
||||
public static void MapLokEndpoints(WebApplication app)
|
||||
{
|
||||
app.MapPost("/lok/open-hours", async (LokOpenHours openHours, LokService lokService) =>
|
||||
app.MapPost("/lok/open-hours", async (HttpContext httpContext) =>
|
||||
{
|
||||
var lokService = httpContext.RequestServices.GetRequiredService<LokService>();
|
||||
var openHours = await httpContext.Request.ReadFromJsonAsync<LokOpenHours>();
|
||||
|
||||
if (openHours is null)
|
||||
{
|
||||
httpContext.Response.StatusCode = StatusCodes.Status400BadRequest;
|
||||
await httpContext.Response.WriteAsJsonAsync(new
|
||||
{
|
||||
Message = "Request body is required."
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(openHours.Name))
|
||||
{
|
||||
httpContext.Response.StatusCode = StatusCodes.Status400BadRequest;
|
||||
await httpContext.Response.WriteAsJsonAsync(new
|
||||
{
|
||||
Message = "Open hours version name is required."
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
var createdOpenHours = await lokService.InsertOpenHours(openHours);
|
||||
return Results.Created("/lok/open-hours", createdOpenHours);
|
||||
httpContext.Response.StatusCode = StatusCodes.Status201Created;
|
||||
httpContext.Response.Headers.Location = "/lok/open-hours";
|
||||
await httpContext.Response.WriteAsJsonAsync(createdOpenHours);
|
||||
})
|
||||
.WithName("CreateLokOpenHours");
|
||||
|
||||
app.MapGet("/lok/open-hours", async (LokService lokService) =>
|
||||
app.MapGet("/lok/open-hours", async (HttpContext httpContext) =>
|
||||
{
|
||||
var lokService = httpContext.RequestServices.GetRequiredService<LokService>();
|
||||
var openHours = await lokService.GetOpenHours();
|
||||
|
||||
if (openHours.Count == 0)
|
||||
{
|
||||
return Results.NotFound(new
|
||||
httpContext.Response.StatusCode = StatusCodes.Status404NotFound;
|
||||
await httpContext.Response.WriteAsJsonAsync(new
|
||||
{
|
||||
Message = "Open hours not found."
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
return Results.Ok(openHours);
|
||||
await httpContext.Response.WriteAsJsonAsync(openHours);
|
||||
})
|
||||
.WithName("GetLokOpenHours");
|
||||
|
||||
app.MapDelete("/lok/open-hours/{id:long}", async (HttpContext httpContext, long id) =>
|
||||
{
|
||||
var lokService = httpContext.RequestServices.GetRequiredService<LokService>();
|
||||
var deleted = await lokService.DeleteOpenHours(id);
|
||||
|
||||
if (!deleted)
|
||||
{
|
||||
httpContext.Response.StatusCode = StatusCodes.Status404NotFound;
|
||||
await httpContext.Response.WriteAsJsonAsync(new
|
||||
{
|
||||
Message = "Open hours version not found."
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
httpContext.Response.StatusCode = StatusCodes.Status204NoContent;
|
||||
})
|
||||
.WithName("DeleteLokOpenHours");
|
||||
}
|
||||
}
|
||||
@@ -11,18 +11,18 @@ public static class SystemEndpoints
|
||||
})
|
||||
.WithName("GetVersion");
|
||||
|
||||
app.MapGet("/health/db", async (SqliteConnection connection) =>
|
||||
app.MapGet("/health/db", async (Microsoft.Data.Sqlite.SqliteConnection connection) =>
|
||||
{
|
||||
await connection.OpenAsync();
|
||||
await using var command = connection.CreateCommand();
|
||||
command.CommandText = "SELECT 1";
|
||||
var result = await command.ExecuteScalarAsync();
|
||||
|
||||
return Results.Ok(new
|
||||
return new
|
||||
{
|
||||
Database = "ok",
|
||||
Result = result
|
||||
});
|
||||
};
|
||||
})
|
||||
.WithName("GetDatabaseHealth");
|
||||
}
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
public class LokOpenHours
|
||||
{
|
||||
public long Id { get; set; }
|
||||
|
||||
public string Name { get; set; } = string.Empty;
|
||||
|
||||
public DateTime Version { get; set; }
|
||||
|
||||
public string Paragraph1 { get; set; } = string.Empty;
|
||||
|
||||
@@ -55,6 +55,15 @@ public class Program
|
||||
command.CommandText = "ALTER TABLE LokOpenHours ADD COLUMN version TEXT NOT NULL DEFAULT '';";
|
||||
command.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
command.CommandText = "SELECT COUNT(*) FROM pragma_table_info('LokOpenHours') WHERE name = 'name';";
|
||||
var hasNameColumn = Convert.ToInt32(command.ExecuteScalar()) > 0;
|
||||
|
||||
if (!hasNameColumn)
|
||||
{
|
||||
command.CommandText = "ALTER TABLE LokOpenHours ADD COLUMN name TEXT NOT NULL DEFAULT '';";
|
||||
command.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ public class LokService
|
||||
|
||||
await using var command = _connection.CreateCommand();
|
||||
command.CommandText = @"
|
||||
SELECT version, paragraph1, paragraph2, paragraph3, paragraph4, kitchenNotice
|
||||
SELECT id, name, version, paragraph1, paragraph2, paragraph3, paragraph4, kitchenNotice
|
||||
FROM LokOpenHours
|
||||
ORDER BY datetime(version) DESC, id DESC
|
||||
LIMIT 5";
|
||||
@@ -32,6 +32,8 @@ public class LokService
|
||||
{
|
||||
openHoursList.Add(new LokOpenHours
|
||||
{
|
||||
Id = reader["id"] is long id ? id : Convert.ToInt64(reader["id"]),
|
||||
Name = reader["name"]?.ToString() ?? string.Empty,
|
||||
Version = ParseVersion(reader["version"]?.ToString()),
|
||||
Paragraph1 = reader["paragraph1"]?.ToString() ?? string.Empty,
|
||||
Paragraph2 = reader["paragraph2"]?.ToString() ?? string.Empty,
|
||||
@@ -55,9 +57,11 @@ public class LokService
|
||||
|
||||
await using var command = _connection.CreateCommand();
|
||||
command.CommandText = @"
|
||||
INSERT INTO LokOpenHours (version, paragraph1, paragraph2, paragraph3, paragraph4, kitchenNotice)
|
||||
VALUES (@version, @paragraph1, @paragraph2, @paragraph3, @paragraph4, @kitchenNotice);";
|
||||
INSERT INTO LokOpenHours (name, version, paragraph1, paragraph2, paragraph3, paragraph4, kitchenNotice)
|
||||
VALUES (@name, @version, @paragraph1, @paragraph2, @paragraph3, @paragraph4, @kitchenNotice);
|
||||
SELECT last_insert_rowid();";
|
||||
|
||||
command.Parameters.AddWithValue("@name", openHours.Name ?? string.Empty);
|
||||
command.Parameters.AddWithValue("@version", version.ToString("O"));
|
||||
command.Parameters.AddWithValue("@paragraph1", openHours.Paragraph1 ?? string.Empty);
|
||||
command.Parameters.AddWithValue("@paragraph2", openHours.Paragraph2 ?? string.Empty);
|
||||
@@ -65,10 +69,12 @@ public class LokService
|
||||
command.Parameters.AddWithValue("@paragraph4", openHours.Paragraph4 ?? string.Empty);
|
||||
command.Parameters.AddWithValue("@kitchenNotice", openHours.KitchenNotice ?? string.Empty);
|
||||
|
||||
await command.ExecuteNonQueryAsync();
|
||||
var insertedId = await command.ExecuteScalarAsync();
|
||||
|
||||
return new LokOpenHours
|
||||
{
|
||||
Id = Convert.ToInt64(insertedId),
|
||||
Name = openHours.Name ?? string.Empty,
|
||||
Version = version,
|
||||
Paragraph1 = openHours.Paragraph1 ?? string.Empty,
|
||||
Paragraph2 = openHours.Paragraph2 ?? string.Empty,
|
||||
@@ -78,6 +84,24 @@ public class LokService
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<bool> DeleteOpenHours(long id)
|
||||
{
|
||||
if (_connection.State != ConnectionState.Open)
|
||||
{
|
||||
await _connection.OpenAsync();
|
||||
}
|
||||
|
||||
await using var command = _connection.CreateCommand();
|
||||
command.CommandText = @"
|
||||
DELETE FROM LokOpenHours
|
||||
WHERE id = @id;";
|
||||
|
||||
command.Parameters.AddWithValue("@id", id);
|
||||
|
||||
var affectedRows = await command.ExecuteNonQueryAsync();
|
||||
return affectedRows > 0;
|
||||
}
|
||||
|
||||
private static DateTime ParseVersion(string? value)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(value) && DateTime.TryParse(value, out var parsed))
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
CREATE TABLE IF NOT EXISTS LokOpenHours (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL DEFAULT '',
|
||||
version TEXT NOT NULL,
|
||||
paragraph1 TEXT NOT NULL DEFAULT '',
|
||||
paragraph2 TEXT NOT NULL DEFAULT '',
|
||||
|
||||
Binary file not shown.
@@ -1,4 +1,4 @@
|
||||
import { query } from "@solidjs/router";
|
||||
import { action, query } from "@solidjs/router";
|
||||
|
||||
const API_BASE_URL = process.env.API_BASE_URL ?? "http://localhost:5013";
|
||||
|
||||
@@ -19,6 +19,10 @@ async function fetchApi<T>(path: string, init?: RequestInit): Promise<T> {
|
||||
throw new Error(`API ${response.status}: ${text || response.statusText}`);
|
||||
}
|
||||
|
||||
if (response.status === 204) {
|
||||
return undefined as T;
|
||||
}
|
||||
|
||||
return (await response.json()) as T;
|
||||
}
|
||||
|
||||
@@ -27,3 +31,60 @@ export const queryApiVersion = query(async () => {
|
||||
const data = await fetchApi<{ version: string }>("/");
|
||||
return data.version;
|
||||
}, "api-version");
|
||||
|
||||
export type LokOpenHours = {
|
||||
id: number;
|
||||
name: string;
|
||||
version: string;
|
||||
paragraph1: string;
|
||||
paragraph2: string;
|
||||
paragraph3: string;
|
||||
paragraph4: string;
|
||||
kitchenNotice: string;
|
||||
};
|
||||
|
||||
export const queryLokOpenHours = query(async (_refreshKey = 0) => {
|
||||
"use server";
|
||||
return await fetchApi<LokOpenHours[]>("/lok/open-hours");
|
||||
}, "lok-open-hours");
|
||||
|
||||
export const createLokOpenHours = action(async (formData: FormData) => {
|
||||
"use server";
|
||||
const name = String(formData.get("name") ?? "").trim();
|
||||
|
||||
if (!name) {
|
||||
throw new Error("Open hours version name is required.");
|
||||
}
|
||||
|
||||
const payload = {
|
||||
id: 0,
|
||||
name,
|
||||
version: new Date().toISOString(),
|
||||
paragraph1: String(formData.get("paragraph1") ?? ""),
|
||||
paragraph2: String(formData.get("paragraph2") ?? ""),
|
||||
paragraph3: String(formData.get("paragraph3") ?? ""),
|
||||
paragraph4: String(formData.get("paragraph4") ?? ""),
|
||||
kitchenNotice: String(formData.get("kitchenNotice") ?? ""),
|
||||
} satisfies LokOpenHours;
|
||||
|
||||
return await fetchApi<LokOpenHours>("/lok/open-hours", {
|
||||
method: "POST",
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
});
|
||||
|
||||
export const deleteLokOpenHours = action(async (formData: FormData) => {
|
||||
"use server";
|
||||
const idValue = String(formData.get("id") ?? "").trim();
|
||||
const id = Number(idValue);
|
||||
|
||||
if (!Number.isFinite(id) || id <= 0) {
|
||||
throw new Error("Open hours id is required for delete.");
|
||||
}
|
||||
|
||||
await fetchApi<void>(`/lok/open-hours/${id}`, {
|
||||
method: "DELETE",
|
||||
});
|
||||
|
||||
return { deleted: true };
|
||||
});
|
||||
|
||||
228
ui/src/components/OpenHoursForm.tsx
Normal file
228
ui/src/components/OpenHoursForm.tsx
Normal file
@@ -0,0 +1,228 @@
|
||||
import { createAsync, useSubmission } from "@solidjs/router";
|
||||
import { For, Show, createEffect, createMemo, createSignal } from "solid-js";
|
||||
import { createLokOpenHours, deleteLokOpenHours, queryLokOpenHours } from "~/api";
|
||||
import { t } from "~/i18n";
|
||||
|
||||
const NEW_VERSION_OPTION = "__new__";
|
||||
|
||||
export default function OpenHoursForm() {
|
||||
const [refreshKey, setRefreshKey] = createSignal(0);
|
||||
const openHours = createAsync(() => queryLokOpenHours(refreshKey()).catch(() => []));
|
||||
const createSubmission = useSubmission(createLokOpenHours);
|
||||
const deleteSubmission = useSubmission(deleteLokOpenHours);
|
||||
const [selectedVersion, setSelectedVersion] = createSignal("");
|
||||
const [name, setName] = createSignal("");
|
||||
const [paragraph1, setParagraph1] = createSignal("");
|
||||
const [paragraph2, setParagraph2] = createSignal("");
|
||||
const [paragraph3, setParagraph3] = createSignal("");
|
||||
const [paragraph4, setParagraph4] = createSignal("");
|
||||
const [kitchenNotice, setKitchenNotice] = createSignal("");
|
||||
|
||||
const latestFive = createMemo(() => openHours() ?? []);
|
||||
|
||||
const selectedOpenHours = createMemo(() =>
|
||||
latestFive().find(version => String(version.id) === selectedVersion())
|
||||
);
|
||||
|
||||
createEffect(() => {
|
||||
if (!createSubmission.result) return;
|
||||
setRefreshKey(previous => previous + 1);
|
||||
setSelectedVersion("");
|
||||
});
|
||||
|
||||
createEffect(() => {
|
||||
if (!deleteSubmission.result) return;
|
||||
setRefreshKey(previous => previous + 1);
|
||||
setSelectedVersion("");
|
||||
});
|
||||
|
||||
createEffect(() => {
|
||||
const versions = latestFive();
|
||||
const current = selectedVersion();
|
||||
|
||||
if (versions.length === 0) {
|
||||
if (current !== NEW_VERSION_OPTION) {
|
||||
setSelectedVersion(NEW_VERSION_OPTION);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (current === NEW_VERSION_OPTION) {
|
||||
return;
|
||||
}
|
||||
|
||||
const hasCurrent = versions.some(version => String(version.id) === current);
|
||||
if (!current || !hasCurrent) {
|
||||
setSelectedVersion(String(versions[0].id));
|
||||
}
|
||||
});
|
||||
|
||||
const reuseSelected = () => {
|
||||
const selected = selectedOpenHours();
|
||||
if (!selected) {
|
||||
setName("");
|
||||
setParagraph1("");
|
||||
setParagraph2("");
|
||||
setParagraph3("");
|
||||
setParagraph4("");
|
||||
setKitchenNotice("");
|
||||
return;
|
||||
}
|
||||
|
||||
setName(selected.name);
|
||||
setParagraph1(selected.paragraph1);
|
||||
setParagraph2(selected.paragraph2);
|
||||
setParagraph3(selected.paragraph3);
|
||||
setParagraph4(selected.paragraph4);
|
||||
setKitchenNotice(selected.kitchenNotice);
|
||||
};
|
||||
|
||||
createEffect(() => {
|
||||
reuseSelected();
|
||||
});
|
||||
|
||||
return (
|
||||
<section class="w-full max-w-3xl rounded-2xl border border-[#C99763] bg-[#F5D1A9] p-6 shadow-md">
|
||||
<h2 class="text-2xl font-semibold text-[#4C250E]">{t("home.openHours.heading")}</h2>
|
||||
|
||||
<Show when={latestFive().length > 0} fallback={<p class="mt-3 text-[#70421E]">{t("home.openHours.empty")}</p>}>
|
||||
<div class="mt-2 flex gap-2">
|
||||
<select
|
||||
id="open-hours-version"
|
||||
class="min-w-0 flex-1 rounded-md border border-[#C99763] bg-[#FFF7EE] px-3 py-2 text-[#4C250E] focus:outline-none focus:ring-2 focus:ring-[#A56C38]"
|
||||
value={selectedVersion()}
|
||||
onInput={event => setSelectedVersion(event.currentTarget.value)}
|
||||
>
|
||||
<For each={latestFive()}>
|
||||
{version => (
|
||||
<option value={String(version.id)}>
|
||||
{version.name || t("home.openHours.latest")} · {new Date(version.version).toLocaleString()}
|
||||
</option>
|
||||
)}
|
||||
</For>
|
||||
<option value={NEW_VERSION_OPTION}>{t("home.openHours.new")}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<form action={deleteLokOpenHours} method="post" class="mt-3">
|
||||
<input type="hidden" name="id" value={selectedOpenHours()?.id ?? ""} />
|
||||
<button
|
||||
type="submit"
|
||||
disabled={!selectedOpenHours() || deleteSubmission.pending}
|
||||
class="rounded-md border border-[#8E4F24] bg-[#EED5B8] px-4 py-2 text-[#70421E] hover:bg-[#E3A977] disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
>
|
||||
{t("home.openHours.delete")}
|
||||
</button>
|
||||
</form>
|
||||
</Show>
|
||||
|
||||
<form action={createLokOpenHours} method="post" class="mt-5 space-y-3">
|
||||
<div>
|
||||
<label for="name" class="block text-sm font-medium text-[#4C250E]">{t("home.openHours.name")}</label>
|
||||
<input
|
||||
id="name"
|
||||
name="name"
|
||||
required
|
||||
value={name()}
|
||||
onInput={event => setName(event.currentTarget.value)}
|
||||
class="mt-1 w-full rounded-md border border-[#C99763] bg-[#FFF7EE] px-3 py-2 text-[#4C250E] focus:outline-none focus:ring-2 focus:ring-[#A56C38]"
|
||||
/>
|
||||
<Show when={!name().trim()}>
|
||||
<p class="mt-1 text-xs text-[#8E4F24]">{t("home.openHours.nameRequired")}</p>
|
||||
</Show>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="paragraph1" class="block text-sm font-medium text-[#4C250E]">{t("home.openHours.paragraph1")}</label>
|
||||
<textarea
|
||||
id="paragraph1"
|
||||
name="paragraph1"
|
||||
rows={2}
|
||||
value={paragraph1()}
|
||||
onInput={event => setParagraph1(event.currentTarget.value)}
|
||||
class="mt-1 w-full rounded-md border border-[#C99763] bg-[#FFF7EE] px-3 py-2 text-[#4C250E] focus:outline-none focus:ring-2 focus:ring-[#A56C38]"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="paragraph2" class="block text-sm font-medium text-[#4C250E]">{t("home.openHours.paragraph2")}</label>
|
||||
<textarea
|
||||
id="paragraph2"
|
||||
name="paragraph2"
|
||||
rows={2}
|
||||
value={paragraph2()}
|
||||
onInput={event => setParagraph2(event.currentTarget.value)}
|
||||
class="mt-1 w-full rounded-md border border-[#C99763] bg-[#FFF7EE] px-3 py-2 text-[#4C250E] focus:outline-none focus:ring-2 focus:ring-[#A56C38]"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="paragraph3" class="block text-sm font-medium text-[#4C250E]">{t("home.openHours.paragraph3")}</label>
|
||||
<textarea
|
||||
id="paragraph3"
|
||||
name="paragraph3"
|
||||
rows={2}
|
||||
value={paragraph3()}
|
||||
onInput={event => setParagraph3(event.currentTarget.value)}
|
||||
class="mt-1 w-full rounded-md border border-[#C99763] bg-[#FFF7EE] px-3 py-2 text-[#4C250E] focus:outline-none focus:ring-2 focus:ring-[#A56C38]"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="paragraph4" class="block text-sm font-medium text-[#4C250E]">{t("home.openHours.paragraph4")}</label>
|
||||
<textarea
|
||||
id="paragraph4"
|
||||
name="paragraph4"
|
||||
rows={2}
|
||||
value={paragraph4()}
|
||||
onInput={event => setParagraph4(event.currentTarget.value)}
|
||||
class="mt-1 w-full rounded-md border border-[#C99763] bg-[#FFF7EE] px-3 py-2 text-[#4C250E] focus:outline-none focus:ring-2 focus:ring-[#A56C38]"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="kitchenNotice" class="block text-sm font-medium text-[#4C250E]">{t("home.openHours.kitchenNotice")}</label>
|
||||
<textarea
|
||||
id="kitchenNotice"
|
||||
name="kitchenNotice"
|
||||
rows={2}
|
||||
value={kitchenNotice()}
|
||||
onInput={event => setKitchenNotice(event.currentTarget.value)}
|
||||
class="mt-1 w-full rounded-md border border-[#C99763] bg-[#FFF7EE] px-3 py-2 text-[#4C250E] focus:outline-none focus:ring-2 focus:ring-[#A56C38]"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap gap-3 pt-1">
|
||||
<button
|
||||
type="button"
|
||||
disabled={!selectedOpenHours()}
|
||||
onClick={reuseSelected}
|
||||
class="rounded-md border border-[#A56C38] bg-[#EED5B8] px-4 py-2 text-[#70421E] hover:bg-[#E3A977] disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
>
|
||||
{t("home.openHours.reuse")}
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
disabled={createSubmission.pending}
|
||||
class="rounded-md border border-[#70421E] bg-[#8E4F24] px-4 py-2 text-[#FFF7EE] hover:bg-[#70421E] disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
>
|
||||
{createSubmission.pending ? t("home.openHours.saving") : t("home.openHours.submit")}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<Show when={createSubmission.result}>
|
||||
<p class="text-sm text-[#4C250E]">{t("home.openHours.saved")}</p>
|
||||
</Show>
|
||||
<Show when={deleteSubmission.result}>
|
||||
<p class="text-sm text-[#4C250E]">{t("home.openHours.deleted")}</p>
|
||||
</Show>
|
||||
<Show when={createSubmission.error} keyed>
|
||||
{error => <p class="text-sm text-[#8E4F24]">{error.message}</p>}
|
||||
</Show>
|
||||
<Show when={deleteSubmission.error} keyed>
|
||||
{error => <p class="text-sm text-[#8E4F24]">{error.message}</p>}
|
||||
</Show>
|
||||
</form>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -15,9 +15,26 @@ const translations = {
|
||||
"nav.language.en": "EN",
|
||||
"meta.description": "SolidStart with-auth example",
|
||||
"home.title": "Home",
|
||||
"home.heading": "Hello World",
|
||||
"home.heading": "KlAPI",
|
||||
"home.signedInAs": "You are signed in as",
|
||||
"home.logoAlt": "logo",
|
||||
"home.openHours.heading": "Open hours versions",
|
||||
"home.openHours.latest": "Latest",
|
||||
"home.openHours.new": "New version",
|
||||
"home.openHours.reuse": "Reuse selected",
|
||||
"home.openHours.delete": "Delete selected",
|
||||
"home.openHours.empty": "No open-hours versions found yet",
|
||||
"home.openHours.name": "Version name",
|
||||
"home.openHours.nameRequired": "Version name is required",
|
||||
"home.openHours.paragraph1": "Paragraph 1",
|
||||
"home.openHours.paragraph2": "Paragraph 2",
|
||||
"home.openHours.paragraph3": "Paragraph 3",
|
||||
"home.openHours.paragraph4": "Paragraph 4",
|
||||
"home.openHours.kitchenNotice": "Kitchen notice",
|
||||
"home.openHours.submit": "Add new version",
|
||||
"home.openHours.saving": "Saving...",
|
||||
"home.openHours.saved": "New version saved",
|
||||
"home.openHours.deleted": "Version deleted",
|
||||
"about.title": "About",
|
||||
"about.apiVersion": "API version",
|
||||
"about.loading": "Loading...",
|
||||
@@ -47,9 +64,26 @@ const translations = {
|
||||
"nav.language.en": "EN",
|
||||
"meta.description": "SolidStart with-auth -esimerkki",
|
||||
"home.title": "Etusivu",
|
||||
"home.heading": "Hei maailma",
|
||||
"home.heading": "KlAPI",
|
||||
"home.signedInAs": "Olet kirjautunut käyttäjänä",
|
||||
"home.logoAlt": "logo",
|
||||
"home.openHours.heading": "Aukioloaikaversiot",
|
||||
"home.openHours.latest": "Viimeisin",
|
||||
"home.openHours.new": "Uusi versio",
|
||||
"home.openHours.reuse": "Käytä valittua uudelleen",
|
||||
"home.openHours.delete": "Poista valittu",
|
||||
"home.openHours.empty": "Aukioloaikaversioita ei vielä löytynyt",
|
||||
"home.openHours.name": "Version nimi",
|
||||
"home.openHours.nameRequired": "Version nimi on pakollinen",
|
||||
"home.openHours.paragraph1": "Kappale 1",
|
||||
"home.openHours.paragraph2": "Kappale 2",
|
||||
"home.openHours.paragraph3": "Kappale 3",
|
||||
"home.openHours.paragraph4": "Kappale 4",
|
||||
"home.openHours.kitchenNotice": "Keittiöhuomio",
|
||||
"home.openHours.submit": "Lisää uusi versio",
|
||||
"home.openHours.saving": "Tallennetaan...",
|
||||
"home.openHours.saved": "Uusi versio tallennettu",
|
||||
"home.openHours.deleted": "Versio poistettu",
|
||||
"about.title": "Tietoja",
|
||||
"about.apiVersion": "API-versio",
|
||||
"about.loading": "Ladataan...",
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
import { Title } from "@solidjs/meta";
|
||||
import { useAuth } from "~/components/Context";
|
||||
import OpenHoursForm from "~/components/OpenHoursForm";
|
||||
import { t } from "~/i18n";
|
||||
|
||||
export default function Home() {
|
||||
const { session } = useAuth();
|
||||
|
||||
return (
|
||||
<main>
|
||||
<Title>{t("home.title")}</Title>
|
||||
<h1 class="text-center">{t("home.heading")}</h1>
|
||||
<img src="/favicon.svg" alt={t("home.logoAlt")} class="w-28" />
|
||||
<OpenHoursForm />
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user