Skip to content

Commit ed91c8d

Browse files
authored
Merge pull request #32 from pdnode-team/feat/delete-cps-chars
feat: delete cps & chars
2 parents 930bbb7 + 71cad18 commit ed91c8d

File tree

1 file changed

+136
-79
lines changed

1 file changed

+136
-79
lines changed
Lines changed: 136 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,90 +1,147 @@
11
<script lang="ts">
2-
import pb from '$lib/pocketbase';
3-
import { goto } from '$app/navigation';
4-
5-
type ViewMode = 'cps' | 'characters';
6-
let mode = $state<ViewMode>('cps');
7-
let items = $state<any[]>([]);
8-
let isLoading = $state(true);
9-
10-
async function fetchMyData(currentMode: ViewMode) {
11-
// 安全守卫:如果没有登录,直接跳走
12-
if (!pb.authStore.isValid || !pb.authStore.record) {
13-
goto('/login');
14-
return;
15-
}
2+
import pb from '$lib/pocketbase';
3+
import { goto } from '$app/navigation';
4+
5+
type ViewMode = 'cps' | 'characters';
6+
let mode = $state<ViewMode>('cps');
7+
let items = $state<any[]>([]);
8+
let isLoading = $state(true);
9+
let deleteModal = $state() as HTMLDialogElement;
10+
let itemToDelete = $state<null | any>(null);
1611
17-
isLoading = true;
18-
const userId = pb.authStore.record.id;
12+
const handleDelete = (item: any) => {
13+
itemToDelete = item
14+
deleteModal.showModal()
15+
};
1916
17+
const confirmDelete = async () => {
2018
try {
21-
const collection = currentMode === 'cps' ? 'cps' : 'characters';
22-
const options = {
23-
// 关键点:只获取 owner 是当前用户的记录
24-
filter: `owner = "${userId}"`,
25-
sort: '-created',
26-
expand: currentMode === 'cps' ? 'characters' : ''
27-
};
28-
29-
items = await pb.collection(collection).getFullList(options);
19+
await pb.collection(itemToDelete.collectionName).delete(itemToDelete.id);
20+
deleteModal.close();
21+
fetchMyData(mode);
3022
} catch (err) {
31-
console.error("Fetch error:", err);
32-
} finally {
33-
isLoading = false;
23+
alert('Delete failed. Please try again.')
24+
console.error('Delete error:', err);
3425
}
3526
}
3627
37-
// 监听 mode 变化自动刷新
38-
$effect(() => {
39-
fetchMyData(mode);
40-
});
28+
async function fetchMyData(currentMode: ViewMode) {
29+
// 安全守卫:如果没有登录,直接跳走
30+
if (!pb.authStore.isValid || !pb.authStore.record) {
31+
goto('/login');
32+
return;
33+
}
34+
35+
isLoading = true;
36+
const userId = pb.authStore.record.id;
37+
38+
try {
39+
const collection = currentMode === 'cps' ? 'cps' : 'characters';
40+
const options = {
41+
// 关键点:只获取 owner 是当前用户的记录
42+
filter: `owner = "${userId}"`,
43+
sort: '-created',
44+
expand: currentMode === 'cps' ? 'characters' : ''
45+
};
46+
47+
items = await pb.collection(collection).getFullList(options);
48+
} catch (err) {
49+
console.error('Fetch error:', err);
50+
} finally {
51+
isLoading = false;
52+
}
53+
}
54+
55+
// 监听 mode 变化自动刷新
56+
$effect(() => {
57+
fetchMyData(mode);
58+
});
4159
</script>
4260

4361
<div class="mx-auto max-w-6xl px-6 py-16">
44-
<div class="mb-12">
45-
<h1 class="text-4xl font-bold md:text-5xl">My Stuff</h1>
46-
<p class="text-base-content/60 mt-2">Manage the CPs and Characters you've created.</p>
47-
48-
<div role="tablist" class="tabs tabs-boxed mt-6 w-fit">
49-
<button
50-
role="tab"
51-
class="tab {mode === 'cps' ? 'tab-active' : ''}"
52-
onclick={() => mode = 'cps'}
53-
>My CPs</button>
54-
<button
55-
role="tab"
56-
class="tab {mode === 'characters' ? 'tab-active' : ''}"
57-
onclick={() => mode = 'characters'}
58-
>My Characters</button>
59-
</div>
60-
</div>
61-
62-
{#if isLoading}
63-
<div class="flex justify-center py-20">
64-
<span class="loading loading-spinner loading-lg text-primary"></span>
65-
</div>
66-
{:else if items.length === 0}
67-
<div class="card bg-base-200 py-20 text-center border-2 border-dashed border-base-300">
68-
<div class="card-body items-center">
69-
<h2 class="card-title text-2xl opacity-40">You haven't created any {mode === 'cps' ? 'CP' : 'characters'} yet.</h2>
70-
<div class="card-actions mt-4">
71-
<a href="/create" class="btn btn-primary">Create Your First {mode === 'cps' ? 'CP' : 'character'}</a>
72-
</div>
73-
</div>
74-
</div>
75-
{:else}
76-
<div class="grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3">
77-
{#each items as item}
78-
<div class="card bg-base-100 shadow-xl border border-base-200">
79-
<div class="card-body p-5">
80-
<h2 class="card-title">{item.name}</h2>
81-
<div class="card-actions justify-end mt-4">
82-
<a href="/edit/{mode}/{item.id}" class="btn btn-sm btn-ghost">Edit</a>
83-
<a href="/{mode}/{item.id}" class="btn btn-sm btn-primary">View</a>
84-
</div>
85-
</div>
86-
</div>
87-
{/each}
88-
</div>
89-
{/if}
90-
</div>
62+
<div class="mb-12">
63+
<h1 class="text-4xl font-bold md:text-5xl">My Stuff</h1>
64+
<p class="mt-2 text-base-content/60">Manage the CPs and Characters you've created.</p>
65+
66+
<div role="tablist" class="tabs-boxed mt-6 tabs w-fit">
67+
<button
68+
role="tab"
69+
class="tab {mode === 'cps' ? 'tab-active' : ''}"
70+
onclick={() => (mode = 'cps')}>My CPs</button
71+
>
72+
<button
73+
role="tab"
74+
class="tab {mode === 'characters' ? 'tab-active' : ''}"
75+
onclick={() => (mode = 'characters')}>My Characters</button
76+
>
77+
</div>
78+
</div>
79+
80+
{#if isLoading}
81+
<div class="flex justify-center py-20">
82+
<span class="loading loading-lg loading-spinner text-primary"></span>
83+
</div>
84+
{:else if items.length === 0}
85+
<div class="card border-2 border-dashed border-base-300 bg-base-200 py-20 text-center">
86+
<div class="card-body items-center">
87+
<h2 class="card-title text-2xl opacity-40">
88+
You haven't created any {mode === 'cps' ? 'CP' : 'characters'} yet.
89+
</h2>
90+
<div class="mt-4 card-actions">
91+
<a href="/create" class="btn btn-primary"
92+
>Create Your First {mode === 'cps' ? 'CP' : 'character'}</a
93+
>
94+
</div>
95+
</div>
96+
</div>
97+
{:else}
98+
<div class="grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3">
99+
{#each items as item}
100+
<div class="card border border-base-200 bg-base-100 shadow-xl">
101+
<div class="card-body p-5">
102+
<h2 class="card-title">{item.name}</h2>
103+
<div class="mt-4 card-actions flex justify-end gap-1">
104+
<button class="btn w-14 btn-soft btn-sm btn-error" onclick={() => handleDelete(item)}>
105+
Delete
106+
</button>
107+
108+
<a href="/edit/{mode}/{item.id}" class="btn w-14 btn-ghost btn-sm"> Edit </a>
109+
110+
<a href="/{mode}/{item.id}" class="btn w-14 btn-sm btn-primary"> View </a>
111+
</div>
112+
</div>
113+
</div>
114+
{/each}
115+
</div>
116+
{/if}
117+
</div>
118+
119+
<dialog bind:this={deleteModal} class="modal">
120+
<div class="modal-box border border-red-200 bg-base-100">
121+
<h3 class="text-base-content text-lg font-bold">Confirm Deletion</h3>
122+
<p class="text-base-content py-4">
123+
Are you sure you want to delete this? This action cannot be undone.
124+
</p>
125+
{#if itemToDelete?.collectionName! == 'cps'}
126+
<p class="text-base-content py-4">
127+
CP cannot be restored after deletion; the character still exists.
128+
</p>
129+
{:else}
130+
<p class="text-base-content py-4">
131+
Once a character is deleted, it cannot be recovered, and the associated CP will also be
132+
deleted.
133+
</p>
134+
{/if}
135+
136+
<div class="modal-action">
137+
<form method="dialog">
138+
<button class="btn btn-ghost">Cancel</button>
139+
</form>
140+
<button class="btn text-white btn-soft btn-error" onclick={confirmDelete}> Delete </button>
141+
</div>
142+
</div>
143+
144+
<form method="dialog" class="modal-backdrop">
145+
<button>close</button>
146+
</form>
147+
</dialog>

0 commit comments

Comments
 (0)