feat: add editing and deleting flags

This commit is contained in:
Sam 2023-05-29 01:27:17 +02:00
parent 8b03521382
commit 67d275f15b
Signed by: sam
GPG key ID: B4EF20DDE721CAA1
2 changed files with 92 additions and 12 deletions

View file

@ -7,7 +7,7 @@
import { addToast } from "$lib/toast"; import { addToast } from "$lib/toast";
import { encode } from "base64-arraybuffer"; import { encode } from "base64-arraybuffer";
import unknownFlag from "./unknown_flag.png"; import unknownFlag from "./unknown_flag.png";
import { apiFetchClient } from "$lib/api/fetch"; import { apiFetchClient, fastFetchClient } from "$lib/api/fetch";
import ErrorAlert from "$lib/components/ErrorAlert.svelte"; import ErrorAlert from "$lib/components/ErrorAlert.svelte";
const MAX_FLAG_BYTES = 500_000; const MAX_FLAG_BYTES = 500_000;
@ -18,11 +18,13 @@
let error: APIError | null = null; let error: APIError | null = null;
let filtered: PrideFlag[]; let filtered: PrideFlag[];
$: filtered = search $: filtered = filterFlags(search, data.flags);
? data.flags.filter((flag) =>
flag.name.toLocaleLowerCase().includes(search.toLocaleLowerCase()), const filterFlags = (search: string, flags: PrideFlag[]) => {
) return search
: data.flags; ? flags.filter((flag) => flag.name.toLocaleLowerCase().includes(search.toLocaleLowerCase()))
: flags;
};
// NEW FLAG UPLOADING CODE // NEW FLAG UPLOADING CODE
let modalOpen = false; let modalOpen = false;
@ -81,6 +83,20 @@
error = e as APIError; error = e as APIError;
} }
}; };
// DELETE FLAG CODE
const deleteFlag = async (id: string) => {
try {
await fastFetchClient(`/users/@me/flags/${id}`, "DELETE");
error = null;
addToast({ header: "Deleted flag", body: "Successfully deleted flag!" });
data.flags = data.flags.filter((entry) => entry.id !== id);
} catch (e) {
error = e as APIError;
}
};
</script> </script>
<h1>Pride flags ({data.flags.length})</h1> <h1>Pride flags ({data.flags.length})</h1>
@ -98,13 +114,13 @@
</div> </div>
<div class="p-2"> <div class="p-2">
{#each filtered as flag} {#each filtered as flag (flag.id)}
<Flag {flag} /> <Flag bind:flag {deleteFlag} />
{:else} {:else}
{#if data.flags.length === 0} {#if data.flags.length === 0}
You haven't uploaded any flags yet, press the button above to do so. You haven't uploaded any flags yet, press the button above to do so.
{:else} {:else}
There are no flags matching your search <strong>{search}</strong> There are no flags matching your search <strong>{search}</strong>.
{/if} {/if}
{/each} {/each}
</div> </div>

View file

@ -1,15 +1,75 @@
<script lang="ts"> <script lang="ts">
import { flagURL, type PrideFlag } from "$lib/api/entities"; import { flagURL, type APIError, type PrideFlag } from "$lib/api/entities";
import { Button } from "sveltestrap"; import { apiFetchClient } from "$lib/api/fetch";
import { addToast } from "$lib/toast";
import { Button, Input, Modal, ModalBody, ModalFooter, ModalHeader } from "sveltestrap";
export let flag: PrideFlag; export let flag: PrideFlag;
export let deleteFlag: (id: string) => Promise<void>;
let error: APIError | null = null;
let modalOpen = false;
const toggleModal = () => (modalOpen = !modalOpen);
let deleteModalOpen = false;
const toggleDeleteModal = () => (deleteModalOpen = !deleteModalOpen);
let name = flag.name;
let description = flag.description;
const updateFlag = async () => {
try {
const resp = await apiFetchClient<PrideFlag>(`/users/@me/flags/${flag.id}`, "PATCH", {
name,
description: description || null,
});
error = null;
flag = resp;
addToast({ header: "Updated flag", body: "Successfully updated flag!" });
toggleModal();
} catch (e) {
error = e as APIError;
}
};
</script> </script>
<Button outline class="m-1"> <Button outline class="m-1" on:click={toggleModal}>
<img class="flag" src={flagURL(flag)} alt={flag.description ?? flag.name} /> <img class="flag" src={flagURL(flag)} alt={flag.description ?? flag.name} />
{flag.name} {flag.name}
</Button> </Button>
<Modal isOpen={modalOpen} toggle={toggleModal}>
<ModalHeader toggle={toggleModal}>Edit {flag.name} flag</ModalHeader>
<ModalBody>
<p>
<label for="name" class="form-label">Name</label>
<Input id="name" bind:value={name} />
</p>
<p>
<label for="description" class="form-label">Description</label>
<textarea id="description" class="form-control" bind:value={description} />
</p>
</ModalBody>
<ModalFooter>
<Button color="danger" on:click={toggleDeleteModal}>Delete flag</Button>
<Button disabled={!name} color="success" on:click={() => updateFlag()}>Edit flag</Button>
</ModalFooter>
</Modal>
<Modal isOpen={deleteModalOpen} toggle={toggleDeleteModal}>
<ModalHeader toggle={toggleDeleteModal}>Delete {flag.name} flag</ModalHeader>
<ModalBody>
Are you sure you want to delete the {flag.name} flag? <strong>This cannot be undone!</strong>
</ModalBody>
<ModalFooter>
<Button color="danger" on:click={() => deleteFlag(flag.id)}>Delete flag</Button>
<Button color="secondary" on:click={toggleDeleteModal}>Cancel</Button>
</ModalFooter>
</Modal>
<style> <style>
.flag { .flag {
height: 2rem; height: 2rem;
@ -17,4 +77,8 @@
border-radius: 3px; border-radius: 3px;
margin-left: -5px; margin-left: -5px;
} }
textarea {
height: 100px;
}
</style> </style>