feat(collections): enhance collections page with sorting, filtering, and pagination features
- Updated the collections loading logic to include sorting and pagination parameters from the URL. - Refactored the collections page to manage owned, shared, and archived collections with a tabbed interface. - Added sorting functionality to allow users to sort collections by different attributes. - Implemented a sidebar for filtering and sorting options. - Improved the UI for better user experience, including a floating action button for creating new collections. - Added a not found page for collections that do not exist, enhancing error handling.
This commit is contained in:
@@ -112,7 +112,6 @@
|
||||
location: null,
|
||||
images: [],
|
||||
user_id: null,
|
||||
collection: collection?.id || null,
|
||||
category: {
|
||||
id: '',
|
||||
name: '',
|
||||
@@ -138,7 +137,6 @@
|
||||
location: adventureToEdit?.location || null,
|
||||
images: adventureToEdit?.images || [],
|
||||
user_id: adventureToEdit?.user_id || null,
|
||||
collection: adventureToEdit?.collection || collection?.id || null,
|
||||
visits: adventureToEdit?.visits || [],
|
||||
is_visited: adventureToEdit?.is_visited || false,
|
||||
category: adventureToEdit?.category || {
|
||||
@@ -628,7 +626,7 @@
|
||||
<p class="text-red-500">{wikiError}</p>
|
||||
</div>
|
||||
</div>
|
||||
{#if !adventure?.collection}
|
||||
{#if adventure.collections && adventure.collections.length == 0}
|
||||
<div>
|
||||
<div class="form-control flex items-start mt-1">
|
||||
<label class="label cursor-pointer flex items-start space-x-2">
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
|
||||
<ul
|
||||
tabindex="0"
|
||||
class="dropdown-content z-[1] text-neutral-200 menu p-2 shadow bg-neutral mt-2 rounded-box w-52"
|
||||
class="dropdown-content z-[999] text-neutral-200 menu p-2 shadow bg-neutral mt-2 rounded-box w-52"
|
||||
>
|
||||
<!-- svelte-ignore a11y-missing-attribute -->
|
||||
<!-- svelte-ignore a11y-missing-attribute -->
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
import ShareVariant from '~icons/mdi/share-variant';
|
||||
|
||||
import { goto } from '$app/navigation';
|
||||
import type { Adventure, Collection } from '$lib/types';
|
||||
import type { Adventure, Collection, User } from '$lib/types';
|
||||
import { addToast } from '$lib/toasts';
|
||||
import { t } from 'svelte-i18n';
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
export let type: String | undefined | null;
|
||||
export let linkedCollectionList: string[] | null = null;
|
||||
export let user: User | null;
|
||||
let isShareModalOpen: boolean = false;
|
||||
|
||||
function editAdventure() {
|
||||
@@ -168,76 +169,78 @@
|
||||
<Launch class="w-4 h-4" />
|
||||
{$t('adventures.open_details')}
|
||||
</button>
|
||||
<div class="dropdown dropdown-end">
|
||||
<button type="button" class="btn btn-square btn-sm btn-base-300">
|
||||
<DotsHorizontal class="w-5 h-5" />
|
||||
</button>
|
||||
<ul
|
||||
class="dropdown-content menu bg-base-100 rounded-box z-[1] w-64 p-2 shadow-xl border border-base-300"
|
||||
>
|
||||
{#if type != 'viewonly'}
|
||||
<li>
|
||||
<button class="flex items-center gap-2" on:click={editAdventure}>
|
||||
<FileDocumentEdit class="w-4 h-4" />
|
||||
{$t('adventures.edit_collection')}
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<button
|
||||
class="flex items-center gap-2"
|
||||
on:click={() => (isShareModalOpen = true)}
|
||||
>
|
||||
<ShareVariant class="w-4 h-4" />
|
||||
{$t('adventures.share')}
|
||||
</button>
|
||||
</li>
|
||||
{#if collection.is_archived}
|
||||
{#if user && user.uuid == collection.user_id}
|
||||
<div class="dropdown dropdown-end">
|
||||
<button type="button" class="btn btn-square btn-sm btn-base-300">
|
||||
<DotsHorizontal class="w-5 h-5" />
|
||||
</button>
|
||||
<ul
|
||||
class="dropdown-content menu bg-base-100 rounded-box z-[1] w-64 p-2 shadow-xl border border-base-300"
|
||||
>
|
||||
{#if type != 'viewonly'}
|
||||
<li>
|
||||
<button
|
||||
class="flex items-center gap-2"
|
||||
on:click={() => archiveCollection(false)}
|
||||
>
|
||||
<ArchiveArrowUp class="w-4 h-4" />
|
||||
{$t('adventures.unarchive')}
|
||||
<button class="flex items-center gap-2" on:click={editAdventure}>
|
||||
<FileDocumentEdit class="w-4 h-4" />
|
||||
{$t('adventures.edit_collection')}
|
||||
</button>
|
||||
</li>
|
||||
{:else}
|
||||
<li>
|
||||
<button
|
||||
class="flex items-center gap-2"
|
||||
on:click={() => archiveCollection(true)}
|
||||
on:click={() => (isShareModalOpen = true)}
|
||||
>
|
||||
<ArchiveArrowDown class="w-4 h-4" />
|
||||
{$t('adventures.archive')}
|
||||
<ShareVariant class="w-4 h-4" />
|
||||
{$t('adventures.share')}
|
||||
</button>
|
||||
</li>
|
||||
{#if collection.is_archived}
|
||||
<li>
|
||||
<button
|
||||
class="flex items-center gap-2"
|
||||
on:click={() => archiveCollection(false)}
|
||||
>
|
||||
<ArchiveArrowUp class="w-4 h-4" />
|
||||
{$t('adventures.unarchive')}
|
||||
</button>
|
||||
</li>
|
||||
{:else}
|
||||
<li>
|
||||
<button
|
||||
class="flex items-center gap-2"
|
||||
on:click={() => archiveCollection(true)}
|
||||
>
|
||||
<ArchiveArrowDown class="w-4 h-4" />
|
||||
{$t('adventures.archive')}
|
||||
</button>
|
||||
</li>
|
||||
{/if}
|
||||
<div class="divider my-1"></div>
|
||||
<li>
|
||||
<button
|
||||
id="delete_collection"
|
||||
data-umami-event="Delete Collection"
|
||||
class="text-error flex items-center gap-2"
|
||||
on:click={() => (isWarningModalOpen = true)}
|
||||
>
|
||||
<TrashCan class="w-4 h-4" />
|
||||
{$t('adventures.delete')}
|
||||
</button>
|
||||
</li>
|
||||
{/if}
|
||||
<div class="divider my-1"></div>
|
||||
<li>
|
||||
<button
|
||||
id="delete_collection"
|
||||
data-umami-event="Delete Collection"
|
||||
class="text-error flex items-center gap-2"
|
||||
on:click={() => (isWarningModalOpen = true)}
|
||||
>
|
||||
<TrashCan class="w-4 h-4" />
|
||||
{$t('adventures.delete')}
|
||||
</button>
|
||||
</li>
|
||||
{/if}
|
||||
{#if type == 'viewonly'}
|
||||
<li>
|
||||
<button
|
||||
class="flex items-center gap-2"
|
||||
on:click={() => goto(`/collections/${collection.id}`)}
|
||||
>
|
||||
<Launch class="w-4 h-4" />
|
||||
{$t('adventures.open_details')}
|
||||
</button>
|
||||
</li>
|
||||
{/if}
|
||||
</ul>
|
||||
</div>
|
||||
{#if type == 'viewonly'}
|
||||
<li>
|
||||
<button
|
||||
class="flex items-center gap-2"
|
||||
on:click={() => goto(`/collections/${collection.id}`)}
|
||||
>
|
||||
<Launch class="w-4 h-4" />
|
||||
{$t('adventures.open_details')}
|
||||
</button>
|
||||
</li>
|
||||
{/if}
|
||||
</ul>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -219,6 +219,28 @@
|
||||
{$t('about.close')}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{#if collection.is_public && collection.id}
|
||||
<div class="bg-neutral p-4 mt-2 rounded-md shadow-sm text-neutral-content">
|
||||
<p class=" font-semibold">{$t('adventures.share_collection')}</p>
|
||||
<div class="flex items-center justify-between">
|
||||
<p class="text-card-foreground font-mono">
|
||||
{window.location.origin}/collections/{collection.id}
|
||||
</p>
|
||||
<button
|
||||
type="button"
|
||||
on:click={() => {
|
||||
navigator.clipboard.writeText(
|
||||
`${window.location.origin}/collections/${collection.id}`
|
||||
);
|
||||
}}
|
||||
class="inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 h-10 px-4 py-2"
|
||||
>
|
||||
{$t('adventures.copy_link')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -277,7 +277,7 @@
|
||||
{#if data.user}
|
||||
<Avatar user={data.user} />
|
||||
{/if}
|
||||
<div class="dropdown dropdown-bottom dropdown-end">
|
||||
<div class="dropdown dropdown-bottom dropdown-end z-[999]">
|
||||
<div tabindex="0" role="button" class="btn m-1 p-2">
|
||||
<DotsHorizontal class="w-6 h-6" />
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user