Compare commits

...

2 Commits

Author SHA1 Message Date
f6b2247cc6 GUI 5 - CRUD 2025-03-10 21:51:47 +01:00
e6d65bb368 Allow unused _ variable in Typescript 2025-03-10 21:40:23 +01:00
4 changed files with 115 additions and 12 deletions

View File

@@ -5,6 +5,7 @@ import globals from 'globals';
import { fileURLToPath } from 'node:url';
import ts from 'typescript-eslint';
import svelteConfig from './svelte.config.js';
const gitignorePath = fileURLToPath(new URL("./.gitignore", import.meta.url));
export default ts.config(
@@ -14,23 +15,32 @@ export default ts.config(
...svelte.configs.recommended,
{
languageOptions: {
globals: {
...globals.browser,
...globals.node
}
}
globals: {
...globals.browser,
...globals.node
}
}
},
{
files: ["**/*.svelte", "**/*.svelte.ts", "**/*.svelte.js"],
ignores: ["eslint.config.js", "svelte.config.js"],
languageOptions: {
parserOptions: {
projectService: true,
extraFileExtensions: ['.svelte'],
parser: ts.parser,
svelteConfig
}
}
parserOptions: {
projectService: true,
extraFileExtensions: ['.svelte'],
parser: ts.parser,
svelteConfig
}
},
rules: {
"@typescript-eslint/no-unused-vars": [
"error",
{
"varsIgnorePattern": "^_",
"argsIgnorePattern": "^_"
}
]
}
}
);

View File

@@ -21,6 +21,7 @@
<li><a href="/2_temperature_converter">2. Temperature Converter</a></li>
<li><a href="/3_flight_broker">3. Flight Broker</a></li>
<li><a href="/4_timer">4. Timer</a></li>
<li><a href="/5_crud">5. CRUD</a></li>
</ul>
</div>
</div>

View File

@@ -0,0 +1,79 @@
<script lang="ts">
import type { AppState, Entry } from "./types";
// APP STATE
let appState: AppState = $state({
entries: {
"1": { name: "Hans", surname: "Wittenberg" },
"2": { name: "Max", surname: "Neumann" },
"3": { name: "Romano", surname: "Prodi" }
},
nextIndex: 4
});
function createEntry(entry: Entry) {
appState.entries[appState.nextIndex++] = entry; // Post-Increment! Yay!
}
function updateEntry(entryId: string, newEntry: Entry) {
appState.entries[entryId] = newEntry;
}
function deleteEntry(entryId: string) {
delete appState.entries[entryId];
}
let entryOptions = $derived(Object.entries(appState.entries).filter(([_, e]) => {
return e.name.includes(filterStr) || e.surname.includes(filterStr);
}));
// GUI STATE
let selectedId = $state("none");
let inputEntry: Entry = $state({ name: "", surname: "" });
let filterStr: string = $state("");
</script>
<div class="card card-border shadow-xl w-200 mx-auto">
<div class="card-body">
<h2 class="card-title">5. CRUD</h2>
<div class="grid grid-cols-2 gap-2">
<div class="inline-flex">
<span class="label text-nowrap mr-2">Filter prefix:</span>
<input type="text" class="input w-fill" bind:value={filterStr}/>
</div>
<p></p>
<div>
<span class="label">Surname, Name</span>
<select class="input h-auto cursor-auto w-full" size="10" bind:value={
() => selectedId,
(v) => {
selectedId = v;
inputEntry = $state.snapshot(appState.entries[v]); // BRUTTO RISCHIO!
}
}>
<option hidden value="none">None</option>
{#each entryOptions as [key, e] (key)}
<option value={key}>{e.surname}, {e.name}</option>
{/each}
</select>
</div>
<div class="grid grid-cols-[min-content_auto] gap-2 mb-auto">
<span class="label">Name:</span>
<input class="input" type="text" bind:value={inputEntry.name}/>
<span class="label">Surname:</span>
<input class="input" type="text" bind:value={inputEntry.surname}/>
</div>
</div>
<div class="card-actions">
<button class="btn btn-primary" onclick={() => createEntry(inputEntry)}>
Create
</button>
<button class="btn btn-warning" disabled={selectedId === "none"}
onclick={() => updateEntry(selectedId, inputEntry)}>
Update
</button>
<button class="btn btn-error" disabled={selectedId === "none"} onclick={() => deleteEntry(selectedId)}>
Delete
</button>
</div>
</div>
</div>

View File

@@ -0,0 +1,13 @@
export interface Entry {
name: string,
surname: string,
}
export interface DB {
[entryId: string]: Entry;
}
export type AppState = {
entries: DB;
nextIndex: number;
}