Skip to content

Commit

Permalink
update frontend alter display order
Browse files Browse the repository at this point in the history
  • Loading branch information
cmintey committed Aug 26, 2024
1 parent 78b8471 commit 2a36545
Show file tree
Hide file tree
Showing 4 changed files with 158 additions and 31 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"pulltorefreshjs": "^0.1.22",
"svelte": "^4.2.19",
"svelte-check": "^3.8.6",
"svelte-dnd-action": "^0.9.50",
"svelte-preprocess": "^6.0.2",
"tailwindcss": "^3.4.10",
"ts-node": "^10.9.2",
Expand Down
11 changes: 11 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

71 changes: 53 additions & 18 deletions src/lib/components/wishlists/ItemCard/ItemCard.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,16 @@
import ApprovalButtons from "./ApprovalButtons.svelte";
import ClaimButtons from "./ClaimButtons.svelte";
import { invalidateAll } from "$app/navigation";
import { dragHandle } from "svelte-dnd-action";
export let item: FullItem;
export let user: (PartialUser & { id: string }) | undefined = undefined;
export let showClaimedName = false;
export let showFor = false;
export let onPublicList = false;
export let reorderActions = false;
export let onIncreasePriority: ((itemId: number) => void) | undefined = undefined;
export let onDecreasePriority: ((itemId: number) => void) | undefined = undefined;
const modalStore = getModalStore();
const toastStore = getToastStore();
Expand Down Expand Up @@ -222,23 +226,54 @@
</div>
</div>

<footer class="card-footer flex flex-row justify-between">
<ClaimButtons
{item}
{onPublicList}
showName={showClaimedName}
{user}
on:claim={() => handleClaim()}
on:unclaim={() => handleClaim(true)}
on:purchase={(event) => handlePurchased(event.detail.purchased)}
/>

<ApprovalButtons
{item}
{user}
on:approve={() => handleApproval(true)}
on:deny={() => handleApproval(false)}
on:delete={handleDelete}
/>
<footer
class="card-footer flex flex-row"
class:justify-between={!reorderActions}
class:justify-center={reorderActions}
>
{#if reorderActions}
<div class="w-max space-x-4">
<button
class="variant-outline-primary btn btn-icon btn-icon-sm md:btn-icon"
aria-label="lower priority for {item.name}"
on:click|stopPropagation={() => onDecreasePriority && onDecreasePriority(item.id)}
>
<iconify-icon icon="ion:arrow-down"></iconify-icon>
</button>
<button
class="variant-outline-primary btn md:btn-lg"
aria-label="drag-handle for {item.name}"
on:click|stopPropagation={() => {}}
use:dragHandle
>
<iconify-icon icon="ion:reorder-two"></iconify-icon>
</button>
<button
class="variant-outline-primary btn btn-icon btn-icon-sm md:btn-icon"
aria-label="increase priority for {item.name}"
on:click|stopPropagation={() => onIncreasePriority && onIncreasePriority(item.id)}
>
<iconify-icon icon="ion:arrow-up"></iconify-icon>
</button>
</div>
{:else}
<ClaimButtons
{item}
{onPublicList}
showName={showClaimedName}
{user}
on:claim={() => handleClaim()}
on:unclaim={() => handleClaim(true)}
on:purchase={(event) => handlePurchased(event.detail.purchased)}
/>

<ApprovalButtons
{item}
{user}
on:approve={() => handleApproval(true)}
on:deny={() => handleApproval(false)}
on:delete={handleDelete}
/>
{/if}
</footer>
</button>
106 changes: 93 additions & 13 deletions src/routes/wishlists/[username]/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,17 @@
import { SSEvents } from "$lib/schema";
import { PublicListAPI } from "$lib/api/lists";
import TokenCopy from "$lib/components/TokenCopy.svelte";
import { dragHandleZone } from "svelte-dnd-action";
import { ItemsAPI } from "$lib/api/items";
export let data: PageData;
type Item = PageData["items"][0];
$: allItems = data.items;
$: approvals = allItems.filter((item) => !item.approved);
$: items = allItems.filter((item) => item.approved);
const flipDurationMs = 200;
let reordering = false;
const itemsAPI = new ItemsAPI();
const [send, receive] = crossfade({
duration: (d) => Math.sqrt(d * 200),
Expand Down Expand Up @@ -110,15 +115,51 @@
}
publicListUrl = new URL(`/lists/${publicListId}`, window.location as unknown as URL);
};
const handleDnd = (e: CustomEvent) => {
allItems = e.detail.items;
};
const handleIncreasePriority = (itemId: number) => {
const itemIdx = allItems.findIndex((item) => item.id === itemId);
const oldItem = allItems[itemIdx - 1];
allItems[itemIdx - 1] = allItems[itemIdx];
allItems[itemIdx] = oldItem;
allItems = [...allItems];
};
const handleDecreasePriority = (itemId: number) => {
const itemIdx = allItems.findIndex((item) => item.id === itemId);
const oldItem = allItems[itemIdx + 1];
allItems[itemIdx + 1] = allItems[itemIdx];
allItems[itemIdx] = oldItem;
allItems = [...allItems];
};
const handleReorderFinalize = async () => {
reordering = false;
const displayOrderUpdate = allItems.map((item, idx) => ({
id: item.id,
displayOrder: idx
}));
const response = await itemsAPI.updateMany(displayOrderUpdate);
console.log(response);
};
</script>

<!-- chips -->
{#if allItems.length > 0}
<div class="flex flex-row flex-wrap space-x-4">
{#if !data.listOwner.isMe}
<ClaimFilterChip />
{/if}
<SortBy />
<div class="flex justify-between">
<div class="flex flex-row flex-wrap space-x-4">
{#if !data.listOwner.isMe}
<ClaimFilterChip />
{/if}
<SortBy />
</div>
<div>
{#if reordering}
<button class="variant-ghost-secondary chip" on:click={handleReorderFinalize}>Finish</button>
{:else}
<button class="variant-filled-primary chip" on:click={() => (reordering = true)}>Reorder</button>
{/if}
</div>
</div>
{/if}

Expand Down Expand Up @@ -153,23 +194,62 @@
</div>
{:else}
<!-- items -->
<div class="flex flex-col space-y-4">
<div
class="flex flex-col space-y-4 p-1 rounded-container-token"
on:consider={handleDnd}
on:finalize={handleDnd}
use:dragHandleZone={{
items,
flipDurationMs,
dragDisabled: !reordering,
dropTargetClasses: ["variant-ringed-primary"],
dropTargetStyle: {}
}}
>
{#if data.listOwner.isMe}
{#each items as item (item.id)}
<div in:receive={{ key: item.id }} out:send|local={{ key: item.id }} animate:flip={{ duration: 200 }}>
<ItemCard {item} showClaimedName={data.showClaimedName} user={data.user} />
</div>
{/each}
<!-- Workaround for svelte-dnd not playing nicely with transitions -->
{#if reordering}
{#each items as item (item.id)}
<div animate:flip={{ duration: flipDurationMs }}>
<ItemCard
{item}
onDecreasePriority={handleDecreasePriority}
onIncreasePriority={handleIncreasePriority}
reorderActions
showClaimedName={data.showClaimedName}
user={data.user}
/>
</div>
{/each}
{:else}
{#each items as item (item.id)}
<div
in:receive={{ key: item.id }}
out:send|local={{ key: item.id }}
animate:flip={{ duration: flipDurationMs }}
>
<ItemCard {item} showClaimedName={data.showClaimedName} user={data.user} />
</div>
{/each}
{/if}
{:else}
<!-- unclaimed-->
{#each items.filter((item) => !item.pledgedById) as item (item.id)}
<div in:receive={{ key: item.id }} out:send|local={{ key: item.id }} animate:flip={{ duration: 200 }}>
<div
in:receive={{ key: item.id }}
out:send|local={{ key: item.id }}
animate:flip={{ duration: flipDurationMs }}
>
<ItemCard {item} showClaimedName={data.showClaimedName} user={data.user} />
</div>
{/each}
<!-- claimed -->
{#each items.filter((item) => item.pledgedById) as item (item.id)}
<div in:receive={{ key: item.id }} out:send|local={{ key: item.id }} animate:flip={{ duration: 200 }}>
<div
in:receive={{ key: item.id }}
out:send|local={{ key: item.id }}
animate:flip={{ duration: flipDurationMs }}
>
<ItemCard {item} showClaimedName={data.showClaimedName} user={data.user} />
</div>
{/each}
Expand Down

0 comments on commit 2a36545

Please sign in to comment.