dolls list UI

This commit is contained in:
2025-12-21 16:00:27 +08:00
parent e1de05de7a
commit e730751433
5 changed files with 104 additions and 71 deletions

View File

@@ -0,0 +1,17 @@
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="lucide lucide-backpack-icon lucide-backpack"
><path
d="M4 10a4 4 0 0 1 4-4h8a4 4 0 0 1 4 4v10a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2z"
/><path d="M8 10h8" /><path d="M8 18h8" /><path
d="M8 22v-6a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v6"
/><path d="M9 6V4a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2v2" /></svg
>

After

Width:  |  Height:  |  Size: 502 B

View File

@@ -0,0 +1,19 @@
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="lucide lucide-paw-print-icon lucide-paw-print"
><circle cx="11" cy="4" r="2" /><circle cx="18" cy="8" r="2" /><circle
cx="20"
cy="16"
r="2"
/><path
d="M9 10a5 5 0 0 1 5 5v3.5a3.5 3.5 0 0 1-6.84 1.045Q6.52 17.48 4.46 16.84A3.5 3.5 0 0 1 5.5 10Z"
/></svg
>

After

Width:  |  Height:  |  Size: 485 B

View File

@@ -15,7 +15,7 @@
type="radio" type="radio"
name="app_menu_tabs" name="app_menu_tabs"
class="tab" class="tab"
aria-label="Your Dolls" aria-label="Your Nekos"
checked checked
/> />
<div class="tab-content bg-base-100 border-base-300 p-4"> <div class="tab-content bg-base-100 border-base-300 p-4">

View File

@@ -152,7 +152,7 @@
}); });
</script> </script>
<div class="scale-150 p-2"> <div class="scale-200 p-4">
<div class="size-8"> <div class="size-8">
{#if error} {#if error}
<div <div

View File

@@ -7,6 +7,8 @@
import type { CreateDollDto } from "../../../types/bindings/CreateDollDto"; import type { CreateDollDto } from "../../../types/bindings/CreateDollDto";
import type { UpdateDollDto } from "../../../types/bindings/UpdateDollDto"; import type { UpdateDollDto } from "../../../types/bindings/UpdateDollDto";
import DollPreview from "./DollPreview.svelte"; import DollPreview from "./DollPreview.svelte";
import PawPrint from "../../../assets/icons/paw-print.svelte";
import Backpack from "../../../assets/icons/backpack.svelte";
let dolls: DollDto[] = []; let dolls: DollDto[] = [];
let user: UserProfile | null = null; let user: UserProfile | null = null;
@@ -139,11 +141,11 @@
} }
</script> </script>
<div class="dolls-page flex flex-col gap-4 p-4"> <div class="dolls-page flex flex-col gap-4">
<div class="flex justify-between items-center"> <div class="flex justify-between items-center">
<h2 class="text-xl font-bold">Your Dolls</h2> <h2 class="text-lg font-bold">Your Nekos</h2>
<button class="btn btn-primary btn-sm" on:click={openCreateModal}> <button class="btn btn-primary btn-sm" on:click={openCreateModal}>
Create Doll Add a Neko
</button> </button>
</div> </div>
@@ -156,77 +158,72 @@
</div> </div>
{/if} {/if}
{#if loading} <div class="flex flex-col relative">
<div class="flex justify-center p-4"> {#if loading}
<span class="loading loading-spinner loading-md"></span> <progress class="progress w-full h-px absolute inset-0 z-10"></progress>
</div> {/if}
{:else if dolls.length === 0}
<div class="text-center text-base-content/70 py-8"> {#if dolls.length === 0}
<p>No dolls found. Create your first doll!</p> <div class="text-center text-base-content/70 py-8">
</div> <p>No dolls found. Create your first doll!</p>
{:else} </div>
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-4"> {:else}
{#each dolls as doll (doll.id)} <div class="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-4">
<div class="card border border-base-200 bg-base-100 relative"> {#each dolls as doll (doll.id)}
{#if user?.activeDollId === doll.id} <div
<div class="card border border-base-200 bg-linear-to-b from-base-100 to-base-300 relative"
class="absolute top-2 right-2 badge badge-success badge-sm gap-1 z-10" >
> <div class="flex flex-col w-full">
Active
</div>
{/if}
<div class="card-body">
<h3 class="card-title text-base">{doll.name}</h3>
<div class="flex justify-center mb-2">
<DollPreview
bodyColor={doll.configuration.colorScheme.body}
outlineColor={doll.configuration.colorScheme.outline}
/>
</div>
<div class="flex gap-2 text-sm text-base-content/70">
<div class="flex items-center gap-1">
<div
class="w-4 h-4 rounded border border-base-content/20"
style="background-color: {doll.configuration.colorScheme
.body};"
></div>
<span>Body</span>
</div>
<div class="flex items-center gap-1">
<div
class="w-4 h-4 rounded border border-base-content/20"
style="background-color: {doll.configuration.colorScheme
.outline};"
></div>
<span>Outline</span>
</div>
</div>
<div class="card-actions justify-end mt-2">
{#if user?.activeDollId === doll.id}
<button
class="btn btn-xs btn-ghost text-warning"
on:click={handleRemoveActiveDoll}>Deactivate</button
>
{:else}
<button
class="btn btn-xs btn-ghost text-success"
on:click={() => handleSetActiveDoll(doll.id)}>Activate</button
>
{/if}
<button <button
class="btn btn-xs btn-ghost" on:click={() => openEditModal(doll)}
on:click={() => openEditModal(doll)}>Edit</button class="flex flex-col w-full text-center py-6 gap-2 *:mx-auto hover:opacity-70 hover:cursor-pointer"
> >
<button <div class="flex justify-center">
class="btn btn-xs btn-ghost text-error" <DollPreview
on:click={() => handleDeleteDoll(doll.id)}>Delete</button bodyColor={doll.configuration.colorScheme.body}
outlineColor={doll.configuration.colorScheme.outline}
/>
</div>
<p
style:background-color={doll.configuration.colorScheme.body}
style:color={doll.configuration.colorScheme.outline}
class="badge border-none text-xs w-max mx-auto"
>
{doll.name}
</p>
</button>
<div class="*:btn *:btn-block *:rounded-t-none">
{#if user?.activeDollId === doll.id}
<button
class="btn-primary text-accent flex-1"
on:click={handleRemoveActiveDoll}
>
<div class="scale-60"><Backpack /></div>
Recall
</button>
{:else}
<button
class="flex-1 text-primary"
on:click={() => handleSetActiveDoll(doll.id)}
>
<div class="scale-60"><PawPrint /></div>
Deploy
</button>
{/if}
</div>
<!-- <button
class=" text-error"
on:click={() => handleDeleteDoll(doll.id)}
> >
<div class="scale-60"><Trash /></div>
</button> -->
</div> </div>
</div> </div>
</div> {/each}
{/each} </div>
</div> {/if}
{/if} </div>
<!-- Create Modal --> <!-- Create Modal -->
{#if isCreateModalOpen} {#if isCreateModalOpen}