Skip to content

Commit

Permalink
feat: add detail page
Browse files Browse the repository at this point in the history
  • Loading branch information
theodorusclarence committed Jan 18, 2022
1 parent 1581daf commit 8e1e909
Show file tree
Hide file tree
Showing 7 changed files with 141 additions and 2 deletions.
11 changes: 11 additions & 0 deletions src/components/Skeleton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import * as React from 'react';

import clsxm from '@/lib/clsxm';

type SkeletonProps = React.ComponentPropsWithoutRef<'div'>;

export default function Skeleton({ className, ...rest }: SkeletonProps) {
return (
<div className={clsxm('bg-gray-400 animate-pulse', className)} {...rest} />
);
}
2 changes: 1 addition & 1 deletion src/components/links/PrimaryLink.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const PrimaryLink = React.forwardRef<HTMLAnchorElement, UnstyledLinkProps>(
{...rest}
className={clsxm(
'inline-flex items-center',
'font-medium text-primary-600 hover:text-primary-500',
'font-medium text-primary-400 hover:text-primary-500',
'focus:outline-none focus-visible:rounded focus-visible:ring focus-visible:ring-primary-500 focus-visible:ring-offset-2',
className
)}
Expand Down
40 changes: 40 additions & 0 deletions src/container/CopyBox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import * as React from 'react';
import CopyToClipboard from 'react-copy-to-clipboard';
import toast from 'react-hot-toast';
import { HiClipboard } from 'react-icons/hi';

import clsxm from '@/lib/clsxm';
import { trimHttps } from '@/lib/helper';

import PrimaryLink from '../components/links/PrimaryLink';

type CopyBoxProps = {
link: string;
} & React.ComponentPropsWithoutRef<'div'>;

export default function CopyBox({ className, link, ...rest }: CopyBoxProps) {
return (
<div
className={clsxm(
'flex gap-2 items-center p-2 pl-4 max-w-sm rounded border border-gray-600',
className
)}
{...rest}
>
<div className='flex-grow text-left'>
<PrimaryLink href={link} className='text-lg'>
{trimHttps(link)}
</PrimaryLink>
</div>

<CopyToClipboard
text={link}
onCopy={() => toast.success(`${trimHttps(link)} copied to clipboard`)}
>
<button className='p-2 rounded-full hover:text-primary-400 focus:ring focus:ring-primary-400 focus:outline-none'>
<HiClipboard className='text-lg' />
</button>
</CopyToClipboard>
</div>
);
}
22 changes: 22 additions & 0 deletions src/container/QRCode.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import * as React from 'react';
import ReactQRCode from 'react-qr-code';

export default function QRCode({
link,
className,
}: {
link: string;
className?: string;
}) {
return (
<div className={className}>
<ReactQRCode
value={link}
className='mx-auto'
bgColor='#222222'
fgColor='var(--clr-primary-400)'
id='QRCode'
/>
</div>
);
}
4 changes: 4 additions & 0 deletions src/lib/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,7 @@ export function openGraph({
ogTemplateTitle ? `&templateTitle=${ogTemplateTitle}` : ''
}`;
}

export function trimHttps(url: string) {
return url.replace(/^https?:\/\//, '');
}
55 changes: 55 additions & 0 deletions src/pages/[slug]/detail.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { useRouter } from 'next/router';
import * as React from 'react';

import Accent from '@/components/Accent';
import Layout from '@/components/layout/Layout';
import Seo from '@/components/Seo';
import Skeleton from '@/components/Skeleton';
import CopyBox from '@/container/CopyBox';
import QRCode from '@/container/QRCode';

export default function DetailPage() {
//#region //*=========== Get Route Param ===========
const router = useRouter();
const idParam = router.query.slug;
//#endregion //*======== Get Route Param ===========

//#region //*=========== Link ===========
const [link, setLink] = React.useState<string>();

React.useEffect(() => {
const origin = window.location.origin;
const slug = idParam;

setLink(origin + '/' + slug);
}, [idParam]);
//#endregion //*======== Link ===========

return (
<Layout>
<Seo templateTitle='Detail' />

<main>
<section className=''>
<div className='layout flex flex-col items-center py-20 min-h-screen'>
<h1 className='h0'>
<Accent>Shorten New Link</Accent>
</h1>

{link ? (
<QRCode link={link} className='mt-8' />
) : (
<Skeleton className='mt-8 w-64 h-64' />
)}

{link ? (
<CopyBox link={link} className='mt-8' />
) : (
<Skeleton className='mt-8 w-72 h-14 rounded' />
)}
</div>
</section>
</main>
</Layout>
);
}
9 changes: 8 additions & 1 deletion src/pages/_middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { getUrlBySlug } from '@/lib/notion';

export default async function middleware(req: NextRequest) {
const path = req.nextUrl.pathname.split('/')[1];

const whitelist = [
'favicons',
'fonts',
Expand All @@ -18,6 +17,14 @@ export default async function middleware(req: NextRequest) {
return;
}

/** Don't redirect if /:slug/detail */
const isDetailPage = req.nextUrl.pathname.split('/')[2]
? req.nextUrl.pathname.split('/')[2] === 'detail'
: false;
if (isDetailPage) {
return;
}

const url = await getUrlBySlug(path);

if (url.link) {
Expand Down

0 comments on commit 8e1e909

Please sign in to comment.