Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Collections Backend #243

Merged
merged 18 commits into from
Oct 7, 2023
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
16 changes: 11 additions & 5 deletions apps/resources/app/(home)/page.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
import { About } from './About/About';
import { Header } from './Header/Header';
import { Page } from 'components/Page/Page';
import { SearchParams } from 'lib/types';
import { NewResources } from '../../components/NewResources/NewResources';
import { Newsletter } from '../../components/Newsletter/Newsletter';
import { About } from './About/About';
import { Header } from './Header/Header';

interface Props {
searchParams: SearchParams;
}

const Home = () => {
const Home = ({ searchParams }: Props) => {
return (
<>
<Page searchParams={searchParams}>
<Header />
<NewResources />
<Newsletter />
<About />
</>
</Page>
);
};

Expand Down
76 changes: 76 additions & 0 deletions apps/resources/app/collections/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { auth } from '@clerk/nextjs';
import { Resources } from 'app/resources/Resources/Resources';
import { Await } from 'components/Await/Await';
import { Page } from 'components/Page/Page';
import { Heading, Text } from 'design-system';
import { getCollectionCached } from 'lib/cache';
import { SearchParams } from 'lib/types';
import { DeleteCollectionButton } from '../../../components/Collections/DeleteCollectionButton/DeleteCollectionButton';
import { UpdateBollectionButton } from '../../../components/Collections/UpdateBollectionButton';

interface Props {
params: {
id: string;
};
searchParams: SearchParams;
}

const CollectionPage = async ({ params, searchParams }: Props) => {
const { id } = params;
const promise = getCollectionCached(Number(id));
const { userId } = auth();

return (
<Page searchParams={searchParams}>
<div>
<Heading>Collection Page</Heading>
{userId && (
<div className="flex flex-col items-start gap-4">
<UpdateBollectionButton collectionId={Number(id)} />
<DeleteCollectionButton collectionId={Number(id)} />
</div>
)}
</div>
<Await promise={promise}>
{(collection) => {
if (!collection) return <div>No collection found</div>;
const isOwnCollection = collection.user?.id === userId;

return (
<div className="flex flex-col gap-4">
<div className="flex flex-col gap-2">
<Heading>Title: {collection.title}</Heading>
<Text>Description: {collection.description}</Text>
<Text>Username: {collection.user?.username ?? 'anonymos'}</Text>
</div>
{collection.resources.length === 0 ? (
<div>No resources in collection</div>
) : (
<div>
Resources:
<ul className="flex flex-col gap-2">
{collection.resources.map((resource) => {
return (
<>
<li key={`${resource.id}-${resource.type}`}>
{'title' in resource
? resource.title
: resource.name}
</li>
<div>----------------------------------</div>
</>
);
})}
</ul>
</div>
)}
{isOwnCollection && <Resources searchParams={searchParams} />}
</div>
);
}}
</Await>
</Page>
);
};

export default CollectionPage;
46 changes: 46 additions & 0 deletions apps/resources/app/collections/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { auth } from '@clerk/nextjs';
import { Await } from 'components/Await/Await';
import { Page } from 'components/Page/Page';
import { Heading, Text } from 'design-system';
import { getCollectionsCached } from 'lib/cache';
import { SearchParams } from 'lib/types';
import Link from 'next/link';
import { AddCollectionButton } from '../../components/Collections/AddCollectionButton';

interface Props {
searchParams: SearchParams;
}

const CollectionsPage = async ({ searchParams }: Props) => {
const promise = getCollectionsCached();
const { userId } = auth();
return (
<Page searchParams={searchParams}>
<Heading level="2">Collections</Heading>
{userId && <AddCollectionButton />}
<Await promise={promise}>
{(collections) => {
return (
<ul>
{collections.map(({ id, title, description, user }) => (
<li key={id}>
<Link
href={`/collections/${id}`}
className="flex flex-col gap-2"
>
<Heading level="3">Title: {title}</Heading>
<Text>Description: {description}</Text>
<Text>Username: {user?.username ?? 'anonymos'}</Text>
</Link>
<div>----------------------------------</div>
</li>
))}
</ul>
);
}}
</Await>
</Page>
);
};

export default CollectionsPage;
29 changes: 19 additions & 10 deletions apps/resources/app/imprint/page.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,32 @@
import { Page } from 'components/Page/Page';
import { allPages } from 'contentlayer/generated';
import { Heading } from 'design-system';
import { SearchParams } from 'lib/types';
import { Metadata } from 'next';

export const metadata: Metadata = {
title: 'Imprint',
};

const ImprintPage = () => {
interface Props {
searchParams: SearchParams;
}

const ImprintPage = ({ searchParams }: Props) => {
const content = allPages.find((page) => page.title === 'Imprint');
return (
<section className="mx-auto max-w-prose space-y-20">
<Heading level="1" className="mb-6">
{content?.title}
</Heading>
<div
className="prose"
dangerouslySetInnerHTML={{ __html: content?.body.html ?? '' }}
/>
</section>
<Page searchParams={searchParams}>
<section className="mx-auto max-w-prose space-y-20">
<Heading level="1" className="mb-6">
{content?.title}
</Heading>
<div
className="prose"
dangerouslySetInnerHTML={{ __html: content?.body.html ?? '' }}
/>
</section>
</Page>
);
};

export default ImprintPage;
28 changes: 18 additions & 10 deletions apps/resources/app/privacy/page.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,31 @@
import { Page } from 'components/Page/Page';
import { allPages } from 'contentlayer/generated';
import { Heading } from 'design-system';
import { SearchParams } from 'lib/types';
import { Metadata } from 'next';

export const metadata: Metadata = {
title: 'Privacy Policy',
};

const PrivacyPage = () => {
interface Props {
searchParams: SearchParams;
}

const PrivacyPage = ({ searchParams }: Props) => {
const content = allPages.find((page) => page.title === 'Privacy');
return (
<section className="mx-auto max-w-prose space-y-20">
<Heading level="1" className="mb-6">
{content?.title}
</Heading>
<div
className="prose"
dangerouslySetInnerHTML={{ __html: content?.body.html ?? '' }}
/>
</section>
<Page searchParams={searchParams}>
<section className="mx-auto max-w-prose space-y-20">
<Heading level="1" className="mb-6">
{content?.title}
</Heading>
<div
className="prose"
dangerouslySetInnerHTML={{ __html: content?.body.html ?? '' }}
/>
</section>
</Page>
);
};

Expand Down
2 changes: 1 addition & 1 deletion apps/resources/app/profile/DeleteAccountButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { useAuth } from '@clerk/nextjs';
import { Alert, Button, InfoBox } from 'design-system';
import { AlertTriangle, CheckCircle2, Loader2, XCircle } from 'lucide-react';
import { useAction } from '../../lib/actions/useAction';
import { useAction } from '../../lib/serverActions/client';
import { deleteAccount } from './actions';

export const DeleteAccountButton = () => {
Expand Down
8 changes: 2 additions & 6 deletions apps/resources/app/profile/actions.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
'use server';

import { clerkClient } from '@clerk/nextjs';
import { createProtectedAction } from 'lib/serverActions/create';
import { revalidatePath } from 'next/cache';
import { createAction } from '../../lib/actions/createAction';
import { deleteUserData } from '../../lib/resources';

export const deleteAccount = createAction({
export const deleteAccount = createProtectedAction({
action: async ({ ctx }) => {
const { userId } = ctx;

if (!userId) {
throw new Error('You must be logged in to delete your account.');
}

try {
await clerkClient.users.deleteUser(userId);
await deleteUserData(userId);
Expand Down
58 changes: 33 additions & 25 deletions apps/resources/app/profile/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,37 +4,45 @@ import {
SignedOut,
UserProfile,
} from '@clerk/nextjs';
import { Page } from 'components/Page/Page';
import { Heading } from 'design-system';
import { SearchParams } from 'lib/types';
import { DeleteAccountButton } from './DeleteAccountButton';

const ProfilePage = () => {
interface Props {
searchParams: SearchParams;
}

const ProfilePage = ({ searchParams }: Props) => {
return (
<section className="mx-auto max-w-4xl">
<Heading level="1" className="mb-8">
Profile
</Heading>
<SignedIn>
<div className="flex flex-col items-center justify-center gap-10">
<UserProfile
appearance={{
variables: {
colorPrimary: '#101b2c',
borderRadius: 'none',
},
elements: {
card: 'shadow-none',
},
}}
/>
<Page searchParams={searchParams}>
<section className="mx-auto max-w-4xl">
<Heading level="1" className="mb-8">
Profile
</Heading>
<SignedIn>
<div className="flex flex-col items-center justify-center gap-10">
<DeleteAccountButton />
<UserProfile
appearance={{
variables: {
colorPrimary: '#101b2c',
borderRadius: 'none',
},
elements: {
card: 'shadow-none',
},
}}
/>
<div className="flex flex-col items-center justify-center gap-10">
<DeleteAccountButton />
</div>
</div>
</div>
</SignedIn>
<SignedOut>
<RedirectToSignIn />
</SignedOut>
</section>
</SignedIn>
<SignedOut>
<RedirectToSignIn />
</SignedOut>
</section>
</Page>
);
};

Expand Down
24 changes: 21 additions & 3 deletions apps/resources/app/resources/Resources/Resources.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,31 @@
import { Heading, Text } from 'design-system';
import { SearchParams } from 'lib/types';
import { z } from 'zod';
import { formateDate } from '../../../lib/utils';
import { ReseourcesFilter } from '../page';
import { ResourcesTable } from './ResourcesTable/ResourcesTable';

export type ReseourcesFilter = z.infer<typeof reseourcesFilterSchema>;
const reseourcesFilterSchema = z.object({
type: z.coerce.string().optional(),
category: z.coerce.string().optional(),
topic: z.coerce.string().optional(),
sort: z.coerce.string().optional(),
search: z.coerce.string().optional(),
likes: z.coerce.boolean().optional(),
comments: z.coerce.boolean().optional(),
from: z.coerce.string().optional(),
till: z.coerce.string().optional(),
limit: z.coerce.number().optional(),
title: z.coerce.string().optional(),
});

interface Props {
resourcesFilter: ReseourcesFilter;
searchParams: SearchParams;
}

export const Resources = async ({ resourcesFilter }: Props) => {
export const Resources = async ({ searchParams }: Props) => {
const resourcesFilter = reseourcesFilterSchema.parse(searchParams);

const title = resourcesFilter.title;
const from = resourcesFilter.from;
const till = resourcesFilter.till;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
LikedResources,
Resource,
} from '../../../../../lib/resources';
import { ReseourcesFilter } from '../../../page';
import { ReseourcesFilter } from '../../Resources';
import { ClearAllButton } from './ClearAllButton';
import { DownloadButton } from './DownloadButton/DownloadButton';
import { ResourcesListTop } from './ResourcesListTop';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
getResourcesCached,
getTopicsCached,
} from '../../../../lib/cache';
import { ReseourcesFilter } from '../../page';
import { ReseourcesFilter } from '../Resources';
import { ResourcesFilter } from './ResourcesFilter/ResourcesFilter';
import { ResourcesList } from './ResourcesList/ResourcesList';
import { ResourcesTableProvider } from './ResourcesTableProvider';
Expand Down
2 changes: 1 addition & 1 deletion apps/resources/app/resources/Suggestion/SuggestionForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
inputStyles,
} from '../../../components/ForrestSection/ForrestSection';
import { useZodForm } from '../../../hooks/useZodForm';
import { useAction } from '../../../lib/actions/useAction';
import { useAction } from '../../../lib/serverActions/client';
import { submit } from './actions';
import { SuggestionFormSchema, suggestionFormSchema } from './schemas';

Expand Down
Loading