Skip to content

Commit

Permalink
feat(mini-toasts) trying to introduce mini toast notifs at the bottom…
Browse files Browse the repository at this point in the history
… right for delete operations
  • Loading branch information
rishikanthc committed Oct 14, 2024
1 parent 6daa13a commit 0fbfcda
Show file tree
Hide file tree
Showing 5 changed files with 164 additions and 24 deletions.
25 changes: 24 additions & 1 deletion src/lib/components/FilePanel.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import { Trash, Pencil } from 'lucide-svelte';
import { Loader2, Check, X } from 'lucide-svelte';
import StatusSpinner from './StatusSpinner.svelte';
let isLoading = false;
let isUploaded = false;
let isError = false;
Expand Down Expand Up @@ -116,6 +117,10 @@
dispatcher('onUpload');
}
let deleting = false;
let delMessage = null;
let success = -1;
async function deleteRecording(event) {
const delId = event.currentTarget.id;
Expand All @@ -125,6 +130,8 @@
}
try {
delMessage = `Deleting record ${delId}`;
deleting = true;
// Delete the template
const deleteResponse = await fetch(`/api/records?id=${delId}`, {
method: 'DELETE'
Expand All @@ -133,15 +140,26 @@
if (deleteResponse.ok) {
const deleteResult = await deleteResponse.json();
console.log('Record deleted successfully:', deleteResult);
delMessage = 'Deleted';
success = 1;
// dispatch('templatesModified');
dispatcher('recordsModified');
} else {
const error = await deleteResponse.json();
console.error('Error deleting record:', error);
delMessage = `Delete failed`;
success = 0;
}
} catch (err) {
console.error('Error during API call:', err);
delMessage = `Delete failed`;
success = 0;
} finally {
setInterval(() => {
deleting = false;
success = -1;
}, 3000);
}
}
Expand Down Expand Up @@ -252,8 +270,13 @@
</script>

<div
class="items-top z-0 h-[704px] w-full justify-start gap-2 p-1 lg:flex lg:h-[700px] 2xl:h-[900px]"
class="items-top relative z-0 h-[704px] w-full justify-start gap-2 p-1 lg:flex lg:h-[700px] 2xl:h-[900px]"
>
{#if deleting}
<div class="absolute bottom-0 right-0">
<StatusSpinner bind:msg={delMessage} {success} />
</div>
{/if}
<div
class="flex h-full w-full flex-shrink-0 rounded bg-carbongray-50 p-2 text-lg dark:bg-carbongray-700 lg:w-[300px]"
>
Expand Down
16 changes: 12 additions & 4 deletions src/lib/components/StatusSpinner.svelte
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
<script lang="ts">
import { Loader } from 'lucide-svelte';
import { Loader, CircleCheck, CircleX } from 'lucide-svelte';
export let msg;
export let size = 15;
export let size = 13;
export let success = -1;
</script>

<div class="flex w-fit items-center justify-center gap-1 p-2">
<Loader {size} class="animate-spin" />
<div class="flex w-fit items-center justify-center gap-2 p-2">
<div class="text-base">{msg}</div>
{#if success < 0}
<Loader {size} class="animate-spin text-carbonblue-500" />
{:else if success > 0}
<CircleCheck {size} class="animate-pulse text-[#24a147]" />
{:else}
<CircleX {size} class="animate-pulse" />
{/if}
</div>
36 changes: 32 additions & 4 deletions src/lib/components/TemplatesPane.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import { createEventDispatcher } from 'svelte';
import { ContextMenu } from 'bits-ui';
import { Plus, Trash } from 'lucide-svelte';
import StatusSpinner from './StatusSpinner.svelte';
export let templates;
let dispatch = createEventDispatcher();
Expand All @@ -26,15 +27,25 @@
}
}
let deleting = false;
let delMessage = null;
let success = -1;
async function deleteTemplate(event) {
const delId = event.target.id;
const delId = event.currentTarget.id;
if (!delId) {
console.error('Template ID is missing');
return;
}
if (delId === clickedId) {
dispatch('onTemplateClick', null);
}
try {
delMessage = `Deleting record ${delId}`;
deleting = true;
// Delete the template
const deleteResponse = await fetch(`/api/templates?id=${delId}`, {
method: 'DELETE'
Expand All @@ -43,19 +54,35 @@
if (deleteResponse.ok) {
const deleteResult = await deleteResponse.json();
console.log('Template deleted successfully:', deleteResult);
delMessage = `Deleted`;
success = 1;
dispatch('templatesModified');
} else {
const error = await deleteResponse.json();
console.error('Error deleting template:', error);
delMessage = `Delete failed`;
success = 0;
}
} catch (err) {
console.error('Error during API call:', err);
delMessage = `Delete failed`;
success = 0;
} finally {
setInterval(() => {
deleting = false;
success = -1;
}, 3000);
}
}
</script>

<ScrollArea.Root class="h-[480px] w-full px-0 2xl:h-[784px]">
{#if deleting}
<div class="absolute bottom-0 right-0">
<StatusSpinner bind:msg={delMessage} {success} />
</div>
{/if}
<ScrollArea.Root class=" h-[480px] w-full px-0 2xl:h-[784px]">
<ScrollArea.Viewport class="h-full w-full">
<div class="flex w-full justify-end">
<Button.Root
Expand Down Expand Up @@ -88,10 +115,11 @@
<Button.Root
class="flex items-center justify-center gap-3"
on:click={deleteTemplate}
id={rec.id}
>
<Trash size={15} id={rec.id} />
<Trash size={15} />

<div class="text-base" id={rec.id}>Delete</div>
<div class="text-base">Delete</div>
</Button.Root>
</ContextMenu.Item>
</ContextMenu.Content>
Expand Down
79 changes: 64 additions & 15 deletions src/lib/components/UploadPane.svelte
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
<script lang="ts">
import { AudioLines, Upload } from 'lucide-svelte';
import { CircleX, AudioLines, CircleCheck, Upload } from 'lucide-svelte';
import { createEventDispatcher } from 'svelte';
import { Button, Progress } from 'bits-ui';
import StatusSpinner from './StatusSpinner.svelte';
let draggedFiles: File[] = [];
let selectedFiles: File[] = [];
const dispatch = createEventDispatcher();
let uploading = false;
let error = false;
// Function to validate if the file is an audio file
function isValidAudioFile(file: File): boolean {
Expand All @@ -25,33 +27,41 @@
});
if (!response.ok) {
error = true;
throw new Error(`Failed to upload ${file.name}`);
}
const result = await response.json();
console.log(`Upload successful for ${file.name}:`, result);
} catch (error) {
console.log('hit api ');
error = true;
console.error(`Error uploading file ${file.name}:`, error);
}
}
let nfiles = 0;
let ctr = 0;
let currFile;
// Function to iterate over all files and upload only valid audio files
async function uploadFiles(files: File[]) {
nfiles = files.length;
uploading = true;
for (const file of files) {
currFile = file.name;
if (isValidAudioFile(file)) {
uploading = true;
await uploadFile(file); // Upload only if the file is valid
uploading = false;
} else {
error = true;
console.error(`Invalid file type: ${file.name} (${file.type})`);
}
ctr = ctr + 1;
}
setTimeout(() => {
uploading = false;
ctr = 0;
nfiles = 0;
}, 1000); // Delay for 2 seconds
}
// Drag & Drop Handlers
Expand All @@ -69,30 +79,69 @@
await uploadFiles(draggedFiles);
dispatch('onUpload');
}
// Handle file selection from input dialog
function handleFileSelect(event: Event) {
const input = event.target as HTMLInputElement;
if (input.files) {
selectedFiles = Array.from(input.files); // Get files from the input
uploadFiles(selectedFiles);
dispatch('onUpload');
}
}
// Trigger the file input dialog when the box is clicked
function triggerFileInput() {
document.getElementById('fileInput')!.click(); // Simulate click on hidden input
}
</script>

<div class="w-full">
<!-- Drag and Drop Area -->
<div
class="my-4 flex h-[150px] w-full items-center justify-center border border-dashed border-carbongray-200 text-carbongray-300 dark:border-carbongray-600"
class="my-4 flex h-[150px] w-full cursor-pointer items-center justify-center border border-dashed border-carbongray-200 text-carbongray-300 dark:border-carbongray-600"
on:dragover={handleDragOver}
on:drop={handleDrop}
on:click={triggerFileInput}
>
<div class="flex flex-col items-center justify-center">
<div>Drag and Drop audio</div>
{#if uploading}
<StatusSpinner msg={'Uploading'} />
{#if ctr < nfiles}
<StatusSpinner msg={'Uploading'} />
<Progress.Root
bind:value={ctr}
max={nfiles}
class="relative h-1 w-[100px] overflow-hidden rounded-full bg-carbongray-100"
>
<div
class="h-full w-full bg-carbongray-700 transition-all duration-1000 ease-in-out"
style={`transform: translateX(-${100 - (100 * (ctr ?? 0)) / nfiles}%)`}
></div>
</Progress.Root>
<div class="text-sm">
Uploading {currFile}
</div>
{:else if !error}
<CircleCheck size={40} class="animate-ping" />
{:else}
<div class="flex flex-col items-center gap-2">
<div class="text-base">Upload failed</div>
<CircleX size={40} class="animate-pulse" color={'red'} />
</div>
{/if}
{:else}
<div>Drag and Drop audio</div>
<Upload size={40} />
<div class="mt-6">Or click to select</div>
{/if}
</div>
</div>

<!-- Upload Button -->
<Button.Root
class="flex items-center gap-1 rounded-md bg-black p-1 text-white hover:bg-carbongray-600 dark:bg-carbongray-700 dark:hover:bg-carbongray-600"
>
<div class="text-base">Upload</div>
<AudioLines size={20} />
</Button.Root>
<input
id="fileInput"
type="file"
accept="audio/*"
class="hidden"
on:change={handleFileSelect}
multiple
/>
</div>
32 changes: 32 additions & 0 deletions src/routes/api/templates/+server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,35 @@ export const POST: RequestHandler = async ({ request, locals }) => {
});
}
};

export const DELETE: RequestHandler = async ({ url, locals }) => {
const pb = locals.pb;
await ensureCollectionExists(pb);

try {
// Extract the 'id' query parameter from the request URL
const id = url.searchParams.get('id');

if (!id) {
return new Response(JSON.stringify({ error: 'Record ID is required' }), {
status: 400,
headers: { 'Content-Type': 'application/json' }
});
}

// Delete the record from the PocketBase collection 'templates'
await pb.collection('templates').delete(id);

// Respond with a success message
return new Response(JSON.stringify({ message: 'Record deleted successfully' }), {
status: 200,
headers: { 'Content-Type': 'application/json' }
});
} catch (err) {
console.log('API records | Error deleting record', err);
return new Response(JSON.stringify({ error: err.message }), {
status: 500,
headers: { 'Content-Type': 'application/json' }
});
}
};

0 comments on commit 0fbfcda

Please sign in to comment.