Skip to content

Commit

Permalink
feat: add board page (#25)
Browse files Browse the repository at this point in the history
* fix: withauth hoc

* feat: add slicing status board component

* feat: integrate board page
  • Loading branch information
ainunns authored Mar 9, 2024
1 parent 3df31b6 commit 7aa7c9e
Show file tree
Hide file tree
Showing 16 changed files with 359 additions and 151 deletions.
6 changes: 1 addition & 5 deletions next.config.mjs
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
experimental: {
missingSuspenseWithCSRBailout: false,
},
};
const nextConfig = {};

export default nextConfig;
37 changes: 0 additions & 37 deletions src/app/(auth)/login/container/LoginPage.tsx

This file was deleted.

31 changes: 29 additions & 2 deletions src/app/(auth)/login/page.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,39 @@
import { Metadata } from 'next';
import * as React from 'react';

import LoginContainer from '@/app/(auth)/login/container/LoginPage';
import LoginForm from '@/app/(auth)/login/container/LoginForm';
import PrimaryLink from '@/components/links/PrimaryLink';
import NextImage from '@/components/NextImage';
import Typography from '@/components/Typography';

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

export default function LoginPage() {
return <LoginContainer />;
return (
<main className='flex min-h-screen w-full flex-col items-center justify-center'>
<div className='mx-auto flex w-10/12 flex-row items-center justify-between'>
<section className='flex w-full flex-col gap-12 lg:w-2/5'>
<Typography variant='h3' color='primary-typo' weight='semibold'>
Sign In
</Typography>
<LoginForm />
<Typography variant='c1' color='secondary' weight='regular'>
Belum punya akun?{' '}
<PrimaryLink href='/register'>Register</PrimaryLink>
</Typography>
</section>
<section className='hidden w-2/5 lg:block'>
<NextImage
src='/auth/sign-up.png'
alt='hero'
width='609'
height='575'
className='mx-auto w-[90%]'
/>
</section>
</div>
</main>
);
}
36 changes: 0 additions & 36 deletions src/app/(auth)/register/container/RegisterPage.tsx

This file was deleted.

31 changes: 29 additions & 2 deletions src/app/(auth)/register/page.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,38 @@
import { Metadata } from 'next';
import * as React from 'react';

import RegisterContainer from '@/app/(auth)/register/container/RegisterPage';
import RegisterForm from '@/app/(auth)/register/container/RegisterForm';
import PrimaryLink from '@/components/links/PrimaryLink';
import NextImage from '@/components/NextImage';
import Typography from '@/components/Typography';

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

export default function RegisterPage() {
return <RegisterContainer />;
return (
<main className='flex min-h-screen w-full flex-col items-center justify-center'>
<div className='mx-auto flex w-10/12 flex-row items-center justify-between'>
<section className='hidden w-2/5 lg:block'>
<NextImage
src='/auth/sign-up.png'
alt='hero'
width='609'
height='575'
className='mx-auto w-[90%]'
/>
</section>
<section className='flex w-full flex-col gap-12 lg:w-2/5'>
<Typography variant='h3' color='primary-typo' weight='semibold'>
Sign Up
</Typography>
<RegisterForm />
<Typography variant='c1' color='secondary' weight='regular'>
Sudah punya akun? <PrimaryLink href='/login'>Login</PrimaryLink>
</Typography>
</section>
</div>
</main>
);
}
71 changes: 71 additions & 0 deletions src/app/board/components/StatusBoard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import * as React from 'react';
import { FaPlus } from 'react-icons/fa';

import TicketBoard from '@/app/board/components/TicketBoard';
import IconButton from '@/components/buttons/IconButton';
import Typography from '@/components/Typography';
import clsxm from '@/lib/clsxm';
import { taskType } from '@/types/entities/task';

type StatusBoardProps = {
title: string;
data: taskType[] | null;
};

export default function StatusBoard({ title, data }: StatusBoardProps) {
const ticketCount = data?.length;
return (
<div
className={clsxm(
'flex h-[70vh] w-full flex-col gap-y-3 rounded-xl border-t-[12px] bg-typo-light',
title === 'Backlog' && 'border-primary-300',
title === 'Ready' && 'border-success-300',
title === 'In Progress' && 'border-warning-300',
title === 'Done' && 'border-danger-300',
)}
>
<div className='flex w-full flex-row items-center justify-between p-4'>
<div className='flex flex-row items-center gap-x-3'>
<Typography as='h2' variant='t' weight='semibold'>
{title}
</Typography>
<Typography
variant='c1'
weight='regular'
className={clsxm(
'inline rounded-md px-2 py-1',
title === 'Backlog' &&
'bg-primary-300 hover:bg-primary-400 active:bg-primary-400',
title === 'Ready' &&
'bg-success-300 hover:bg-success-400 active:bg-success-400',
title === 'In Progress' &&
'bg-warning-300 hover:bg-warning-400 active:bg-warning-400',
title === 'Done' &&
'bg-danger-300 hover:bg-danger-400 active:bg-danger-400',
)}
>
{ticketCount}
</Typography>
</div>
<IconButton
icon={FaPlus}
variant='outline'
className={clsxm(
'size-4 border-none font-normal',
title === 'Backlog' &&
'bg-primary-300 hover:bg-primary-400 active:bg-primary-400',
title === 'Ready' &&
'bg-success-300 hover:bg-success-400 active:bg-success-400',
title === 'In Progress' &&
'bg-warning-300 hover:bg-warning-400 active:bg-warning-400',
title === 'Done' &&
'bg-danger-300 hover:bg-danger-400 active:bg-danger-400',
)}
/>
</div>
<div className='flex w-full flex-col gap-y-3 overflow-y-auto px-4 pb-4'>
{data?.map((task) => <TicketBoard key={task._id} data={task} />)}
</div>
</div>
);
}
48 changes: 48 additions & 0 deletions src/app/board/components/TicketBoard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import * as React from 'react';
import { FaCalendar, FaEdit } from 'react-icons/fa';

import IconButton from '@/components/buttons/IconButton';
import Chips from '@/components/Chips';
import UnderlineLink from '@/components/links/UnderlineLink';
import Typography from '@/components/Typography';
import { randomColor, showFormattedDate } from '@/lib/helper';
import { taskType } from '@/types/entities/task';

export default function TicketBoard({ data }: { data: taskType | null }) {
const tags = data?.tags;
return (
<div className='flex w-full flex-col gap-y-4 rounded-xl bg-typo-white p-4 shadow-md'>
<div className='flex flex-row items-center justify-between gap-x-6'>
<div className='flex flex-row flex-wrap gap-x-2'>
{tags?.map((tag) => (
<Chips key={tag} color={randomColor()} size='sm'>
{tag}
</Chips>
))}
</div>
<IconButton
icon={FaEdit}
variant='outline'
iconClassName='size-4'
className='border-2 border-primary-500 font-normal'
/>
</div>
<div className='flex flex-col gap-1'>
<UnderlineLink href={`/board/${data?._id}`} className='w-fit'>
<Typography as='h3' variant='bt' weight='semibold'>
{data?.title}
</Typography>
</UnderlineLink>
<Typography variant='c1' weight='regular' color='icon'>
{data?.description}
</Typography>
</div>
<div className='flex flex-row items-center gap-2'>
<FaCalendar className='size-4 text-typo-icon' />
<Typography variant='c1' weight='regular' color='secondary'>
{showFormattedDate(data?.dueDate ?? new Date())}
</Typography>
</div>
</div>
);
}
60 changes: 60 additions & 0 deletions src/app/board/container/BoardPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
'use client';
import * as React from 'react';
import { FaGithub } from 'react-icons/fa';

import StatusBoard from '@/app/board/components/StatusBoard';
import { useGetTickets } from '@/app/board/hooks/query';
import withAuth from '@/components/hoc/withAuth';
import PrimaryLink from '@/components/links/PrimaryLink';
import Loading from '@/components/Loading';
import Typography from '@/components/Typography';

export default withAuth(BoardContainer, ['user']);
function BoardContainer() {
const { boardData, isLoading } = useGetTickets();

if (isLoading) {
return <Loading />;
}

const unarchivedTickets =
boardData && boardData.data
? boardData.data.tasks.filter((ticket) => !ticket.deletedAt)
: [];

const [backlogTickets, readyTickets, inProgressTickets, doneTickets] = [
unarchivedTickets.filter((ticket) => ticket.status === 'backlog'),
unarchivedTickets.filter((ticket) => ticket.status === 'ready'),
unarchivedTickets.filter((ticket) => ticket.status === 'in progress'),
unarchivedTickets.filter((ticket) => ticket.status === 'done'),
];

return (
<main className='my-16 flex min-h-screen w-full flex-col gap-8 bg-typo-surface'>
<section className='mx-auto flex w-11/12 flex-col gap-2'>
<Typography as='h1' variant='h5' color='primary-typo' weight='bold'>
Kanban Board
</Typography>
<Typography
as='p'
variant='bt'
color='icon'
weight='regular'
className='flex items-end gap-1'
>
A board to keep track of projects and tasks. Built with Next.js,
TypeScript, and Tailwind CSS by{' '}
<PrimaryLink href='https://github.com/ainunns'>
<FaGithub /> {'ainunns'}
</PrimaryLink>
</Typography>
</section>
<section className='mx-auto grid w-11/12 grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-4'>
<StatusBoard title='Backlog' data={backlogTickets} />
<StatusBoard title='Ready' data={readyTickets} />
<StatusBoard title='In Progress' data={inProgressTickets} />
<StatusBoard title='Done' data={doneTickets} />
</section>
</main>
);
}
14 changes: 14 additions & 0 deletions src/app/board/hooks/query.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
'use client';
import { useQuery } from '@tanstack/react-query';

import { ApiResponse } from '@/types/api';
import { tasksType } from '@/types/entities/task';

export const useGetTickets = () => {
const { data: boardData, isPending: isLoading } = useQuery<
ApiResponse<tasksType>
>({
queryKey: ['/task'],
});
return { boardData, isLoading };
};
11 changes: 11 additions & 0 deletions src/app/board/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Metadata } from 'next';
import * as React from 'react';

import BoardContainer from '@/app/board/container/BoardPage';

export const metadata: Metadata = {
title: 'Home',
};
export default function BoardPage() {
return <BoardContainer />;
}
18 changes: 3 additions & 15 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,5 @@
import * as React from 'react';
import { redirect } from 'next/navigation';

import Chips from '@/components/Chips';
import ArrowLink from '@/components/links/ArrowLink';
import Typography from '@/components/Typography';

export default function Home() {
return (
<main className='w-full'>
<ArrowLink href='/'>Go to the homepage</ArrowLink>
<Chips color='primary'>Chips</Chips>
<Typography as='h1' variant='h5' weight='bold'>
Kanban board
</Typography>
</main>
);
export default function HomePage() {
redirect('/board');
}
Loading

0 comments on commit 7aa7c9e

Please sign in to comment.