deleting fn

This commit is contained in:
Thomas G. Lopes 2025-06-17 13:25:50 +01:00
parent ef6aead37a
commit bb9ec7095c
5 changed files with 106 additions and 11 deletions

View file

@ -153,3 +153,28 @@ export const togglePin = mutation({
return { pinned: !conversation.pinned };
},
});
export const remove = mutation({
args: {
conversation_id: v.id('conversations'),
session_token: v.string(),
},
handler: async (ctx, args) => {
const session = await ctx.runQuery(api.betterAuth.publicGetSession, {
session_token: args.session_token,
});
if (!session) {
throw new Error('Unauthorized');
}
// Verify the conversation belongs to the user
const conversation = await ctx.db.get(args.conversation_id);
if (!conversation || conversation.user_id !== session.userId) {
throw new Error('Conversation not found or unauthorized');
}
await ctx.db.delete(args.conversation_id);
},
});

View file

@ -1,4 +1,5 @@
<script lang="ts" module>
import { iterate } from '$lib/utils/array';
import type { ButtonVariant } from '../button';
// We can extend the generics to include form fields if needed
@ -44,9 +45,18 @@
<p class="py-4">{modalArgs?.description}</p>
{#if modalArgs?.actions}
<div class="modal-action">
{#each Object.entries(modalArgs.actions) as [action, variant] (action)}
{#each iterate(Object.entries(modalArgs.actions)) as [[action, variant], { isFirst }] (action)}
<form method="dialog" onsubmit={() => resolve(action)}>
<Button {variant} type="submit" class="capitalize">
<Button
{variant}
type="submit"
class="capitalize"
{@attach (node) => {
setTimeout(() => {
if (isFirst) node.focus();
}, 100);
}}
>
{action}
</Button>
</form>

View file

@ -42,6 +42,8 @@
});
</script>
<svelte:window onblur={() => (open = false)} />
{@render trigger(tooltip)}
<div {...tooltip.content} class="bg-popover border-border rounded border p-0 shadow-xl">

View file

@ -78,3 +78,37 @@ export function toMap<T, V>(
return map;
}
type IterateReturn<T> = [
T,
{
isFirst: boolean;
isLast: boolean;
array: T[];
index: number;
length: number;
},
];
/**
* Returns an an iterator that iterates over the given array.
* Each returned item contains helpful properties, such as
* `isFirst`, `isLast`, `array`, `index`, and `length`
*
* @param array The array to iterate over.
* @returns An iterator that iterates over the given array.
*/
export function* iterate<T>(array: T[]): Generator<IterateReturn<T>> {
for (let i = 0; i < array.length; i++) {
yield [
array[i]!,
{
isFirst: i === 0,
isLast: i === array.length - 1,
array,
index: i,
length: array.length,
},
];
}
}

View file

@ -21,6 +21,7 @@
import { TextareaAutosize } from '$lib/spells/textarea-autosize.svelte.js';
import Tooltip from '$lib/components/ui/tooltip.svelte';
import { useConvexClient } from 'convex-svelte';
import { callModal } from '$lib/components/ui/modal/global-modal.svelte';
const client = useConvexClient();
@ -110,15 +111,30 @@
async function togglePin(conversationId: string) {
if (!session.current?.session.token) return;
try {
await client.mutation(api.conversations.togglePin, {
conversation_id: conversationId as Id<'conversations'>,
session_token: session.current.session.token,
});
} catch (error) {
console.error('Failed to toggle pin:', error);
}
await client.mutation(api.conversations.togglePin, {
conversation_id: conversationId as Id<'conversations'>,
session_token: session.current.session.token,
});
}
async function deleteConversation(conversationId: string) {
const res = await callModal({
title: 'Delete conversation',
description: 'Are you sure you want to delete this conversation?',
actions: { cancel: 'outline', delete: 'destructive' },
});
if (res !== 'delete') return;
if (!session.current?.session.token) return;
await client.mutation(api.conversations.remove, {
conversation_id: conversationId as Id<'conversations'>,
session_token: session.current.session.token,
});
goto(`/chat`);
}
const templateConversations = $derived([
{ key: 'pinned', label: 'Pinned', conversations: groupedConversations.pinned, icon: PinIcon },
{ key: 'today', label: 'Today', conversations: groupedConversations.today },
@ -202,7 +218,15 @@
</Tooltip>
<Tooltip>
{#snippet trigger(tooltip)}
<button {...tooltip.trigger} class="hover:bg-muted rounded-md p-1">
<button
{...tooltip.trigger}
class="hover:bg-muted rounded-md p-1"
onclick={(e) => {
e.preventDefault();
e.stopPropagation();
deleteConversation(conversation._id);
}}
>
<XIcon class="size-4" />
</button>
{/snippet}