Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 2 additions & 23 deletions apps/app/src/app/[locale]/(main)/decisions/page.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,10 @@
import { DecisionProfileList, ProcessStatus } from '@op/api/encoders';
import { createClient } from '@op/api/serverClient';

import { AllDecisions } from '@/components/decisions/AllDecisions';
import {
ListPageLayout,
ListPageLayoutHeader,
} from '@/components/layout/ListPageLayout';

export const dynamic = 'force-dynamic';

const DecisionsListingPage = async () => {
let decisions: DecisionProfileList = {
items: [],
next: null,
};

try {
const client = await createClient();
decisions = await client.decision.listDecisionProfiles({
limit: 20,
status: ProcessStatus.PUBLISHED,
});
} catch (error) {
// log error but return the empty list
console.log(error);
}

const DecisionsListingPage = () => {
return (
<ListPageLayout className="gap-4 pt-8 sm:gap-6 sm:pt-12">
<div className="flex flex-col gap-2">
Expand All @@ -34,7 +13,7 @@ const DecisionsListingPage = async () => {
Discover new ways to collectively decide together.
</p>
</div>
<AllDecisions initialData={decisions} />
<AllDecisions />
</ListPageLayout>
);
};
Expand Down
82 changes: 47 additions & 35 deletions apps/app/src/components/decisions/AllDecisions/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

import { useUser } from '@/utils/UserProvider';
import { trpc } from '@op/api/client';
import { DecisionProfileList, ProcessStatus } from '@op/api/encoders';
import { ProcessStatus } from '@op/api/encoders';
import { useInfiniteScroll } from '@op/hooks';
import { SkeletonLine } from '@op/ui/Skeleton';
import { Skeleton } from '@op/ui/Skeleton';
import { Tab, TabList, TabPanel, Tabs } from '@op/ui/Tabs';
import { Suspense } from 'react';

Expand All @@ -14,13 +14,44 @@ import ErrorBoundary from '@/components/ErrorBoundary';

import { DecisionListItem } from '../DecisionListItem';

const DecisionListItemSkeleton = () => (
<div className="flex flex-col gap-4 rounded-lg border p-4 sm:flex-row sm:items-center sm:justify-between sm:rounded-none sm:border-0 sm:border-b sm:border-b-neutral-gray1">
<div className="flex flex-col gap-2">
<div className="flex items-center gap-2">
<Skeleton className="h-5 w-48" />
<Skeleton className="h-5 w-16 rounded" />
</div>
<div className="flex items-center gap-1">
<Skeleton className="size-4 rounded" />
<Skeleton className="h-3.5 w-24" />
</div>
</div>
<div className="flex items-center gap-12">
<div className="flex flex-col items-center gap-1">
<Skeleton className="h-5 w-6" />
<Skeleton className="h-3.5 w-16" />
</div>
<div className="flex flex-col items-center gap-1">
<Skeleton className="h-5 w-6" />
<Skeleton className="h-3.5 w-14" />
</div>
</div>
</div>
);

const DecisionsListSkeleton = () => (
<div className="flex flex-col gap-4 sm:gap-0">
{Array.from({ length: 3 }).map((_, i) => (
<DecisionListItemSkeleton key={i} />
))}
</div>
);

const DecisionsListSuspense = ({
status,
initialData,
ownerProfileId,
}: {
status: ProcessStatus;
initialData?: DecisionProfileList;
ownerProfileId?: string;
}) => {
const {
Expand All @@ -34,17 +65,9 @@ const DecisionsListSuspense = ({
status,
ownerProfileId,
},
initialData
? {
initialData: {
pages: [initialData],
pageParams: [null],
},
getNextPageParam: (lastPage) => lastPage.next,
}
: {
getNextPageParam: (lastPage) => lastPage.next,
},
{
getNextPageParam: (lastPage) => lastPage.next,
},
);

const { ref, shouldShowTrigger } = useInfiniteScroll(fetchNextPage, {
Expand Down Expand Up @@ -75,18 +98,14 @@ const DecisionsListSuspense = ({
ref={ref as React.RefObject<HTMLDivElement>}
className="flex justify-center py-4"
>
{isFetchingNextPage ? <SkeletonLine lines={3} /> : null}
{isFetchingNextPage ? <DecisionListItemSkeleton /> : null}
</div>
)}
</div>
);
};

const AllDecisionsTabs = ({
initialData,
}: {
initialData?: DecisionProfileList;
}) => {
const AllDecisionsTabs = () => {
const t = useTranslations();
const { user } = useUser();
const ownerProfileId = user.currentProfile?.id;
Expand Down Expand Up @@ -115,16 +134,16 @@ const AllDecisionsTabs = ({
</Tab>
</TabList>
<TabPanel id="active" className="p-0 sm:p-0">
<Suspense fallback={<SkeletonLine lines={5} />}>
<Suspense fallback={<DecisionsListSkeleton />}>
<DecisionsListSuspense
status={ProcessStatus.PUBLISHED}
initialData={initialData}
ownerProfileId={ownerProfileId}
/>
</Suspense>
</TabPanel>
{hasDrafts && (
<TabPanel id="drafts" className="p-0 sm:p-0">
<Suspense fallback={<SkeletonLine lines={5} />}>
<Suspense fallback={<DecisionsListSkeleton />}>
<DecisionsListSuspense
status={ProcessStatus.DRAFT}
ownerProfileId={ownerProfileId}
Expand All @@ -133,28 +152,21 @@ const AllDecisionsTabs = ({
</TabPanel>
)}
<TabPanel id="other" className="p-0 sm:p-0">
<Suspense fallback={<SkeletonLine lines={5} />}>
<Suspense fallback={<DecisionsListSkeleton />}>
<DecisionsListSuspense status={ProcessStatus.COMPLETED} />
</Suspense>
</TabPanel>
</Tabs>
);
};

export const AllDecisions = ({
initialData,
}: {
initialData?: DecisionProfileList;
}) => {
export const AllDecisions = () => {
const { user } = useUser();

return (
<ErrorBoundary fallback={<div>Could not load decisions</div>}>
<Suspense fallback={<SkeletonLine lines={5} />}>
<AllDecisionsTabs
key={user.currentProfile?.id}
initialData={initialData}
/>
<Suspense fallback={<DecisionsListSkeleton />}>
<AllDecisionsTabs key={user.currentProfile?.id} />
</Suspense>
</ErrorBoundary>
);
Expand Down