Skip to content

Commit

Permalink
feat(web,ui): implements greeting feature for dashboard
Browse files Browse the repository at this point in the history
  • Loading branch information
ixahmedxi committed Jul 31, 2023
1 parent e2a2ee3 commit e4ef956
Show file tree
Hide file tree
Showing 10 changed files with 335 additions and 41 deletions.
33 changes: 33 additions & 0 deletions apps/web/src/components/Greeting.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { ErrorPanel, Skeleton, Typography } from '@noodle/ui';

import { api } from '@/utils/api';

const Greeting = () => {
const { data, isLoading, error } = api.greeting.get.useQuery(undefined, {
refetchOnWindowFocus: false,
refetchOnMount: false,
});

if (isLoading) {
return (
<div className="space-y-3">
<Skeleton className="h-11 w-72" />
<Skeleton className="h-5 w-96" />
<Skeleton className="h-5 w-96" />
</div>
);
}

if (error) {
return <ErrorPanel errorMessage={error.message} className="h-36" />;
}

return (
<div className="space-y-3">
<Typography.H3 as="h1">{data.greeting}</Typography.H3>
<Typography.P className="max-w-[57ch]">{data.quote}</Typography.P>
</div>
);
};

export { Greeting };
14 changes: 3 additions & 11 deletions apps/web/src/pages/app/index.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,11 @@
import { Typography } from '@noodle/ui';

import { Greeting } from '@/components/Greeting';
import { DashboardLayout } from '@/layouts/dashboard';
import { type NextPageWithLayout } from '@/utils/NextPageWithLayout';

const AppPage: NextPageWithLayout = () => {
return (
<main className="flex flex-1 items-center justify-center">
<div className="text-center">
<Typography.H1>😪</Typography.H1>
<Typography.H1>It&apos;s a bit lonely here</Typography.H1>
<Typography.P className="max-w-[50ch]">
We are hard at work getting the dashboard up and running, we are still
in very much early days of the development of Noodle.
</Typography.P>
</div>
<main className="flex-1 pt-4">
<Greeting />
</main>
);
};
Expand Down
2 changes: 2 additions & 0 deletions packages/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
"@noodle/db": "workspace:^",
"@trpc/next": "^10.36.0",
"@trpc/server": "^10.36.0",
"got": "^13.0.0",
"node-fetch": "^3.3.2",
"superjson": "^1.13.1",
"zod": "^3.21.4"
},
Expand Down
2 changes: 2 additions & 0 deletions packages/api/src/root.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { feedbackRouter } from './routers/feedback';
import { greetingRouter } from './routers/greeting';
import { waitListRouter } from './routers/wait-list';
import { createRouter } from './setup/trpc';

export const appRouter = createRouter({
waitlist: waitListRouter,
feedback: feedbackRouter,
greeting: greetingRouter,
});

export type AppRouter = typeof appRouter;
44 changes: 44 additions & 0 deletions packages/api/src/routers/greeting.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { clerkClient, currentUser } from '@clerk/nextjs';
import fetch from 'node-fetch';

import { protectedProcedure } from '../middlewares/auth';
import { createRouter } from '../setup/trpc';

type QuoteType = {
_id: string;
content: string;
author: string;
tags: string[];
authorSlug: string;
length: number;
dateAdded: string;
dateModified: string;
};

export const greetingRouter = createRouter({
get: protectedProcedure.query(async ({ ctx }) => {
const userId = ctx.auth.userId;
const user = userId ? await clerkClient.users.getUser(userId) : null;

const name = user?.firstName;

const quote = await fetch(
'https://api.quotable.io/random?minLength=100&maxLength=140',
).then((res) => res.json() as Promise<QuoteType>);

const date = new Date();
const currentHour = date.getHours();
let greeting = 'Good evening';

if (currentHour < 12) {
greeting = 'Good morning';
} else if (currentHour < 18) {
greeting = 'Good afternoon';
}

return {
greeting: `${greeting}${name ? `, ${name}` : ''}!`,
quote: `"${quote.content}" - ${quote.author}`,
};
}),
});
4 changes: 3 additions & 1 deletion packages/api/src/setup/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ export const createInnerContext = (opts: ContextOptions) => {
};

export const createContext = ({ req }: CreateNextContextOptions) => {
return createInnerContext({ auth: getAuth(req) });
const auth = getAuth(req);

return createInnerContext({ auth });
};

export type Context = typeof createContext;
35 changes: 35 additions & 0 deletions packages/ui/src/error-panel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { type FC } from 'react';
import { AlertTriangle } from 'lucide-react';

import { cn } from '@noodle/utils';

import { Typography } from './typography';

type ErrorPanelProps = {
errorMessage: string;
className?: string;
};

const ErrorPanel: FC<ErrorPanelProps> = ({ errorMessage, className }) => {
return (
<div
className={cn(
'relative flex h-36 w-full items-center justify-center',
className,
)}
>
<div className="bg-red-4 dark:bg-reddark-1 border-red-6 dark:border-reddark-6 absolute left-0 top-0 z-0 h-full w-full animate-pulse rounded-xl border" />
<div className="z-10 flex flex-col space-y-4">
<Typography.P
as="h1"
className="text-red-10 dark:text-reddark-10 flex items-center gap-4 text-lg"
>
<AlertTriangle size={20} strokeWidth={1.5} /> Error: {errorMessage}
message
</Typography.P>
</div>
</div>
);
};

export { ErrorPanel };
1 change: 1 addition & 0 deletions packages/ui/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ export * from './input';
export * from './label';
export * from './textarea';
export * from './form';
export * from './error-panel';
38 changes: 26 additions & 12 deletions packages/ui/src/typography.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,82 +4,96 @@ import { cn } from '@noodle/utils';

type TypographyProps = {
className?: string;
as?: 'h1' | 'h2' | 'h3' | 'h4' | 'p';
};

const H1: FC<PropsWithChildren<TypographyProps>> = ({
children,
className,
as = 'h1',
}) => {
const As = as;
return (
<h1
<As
className={cn(
'scroll-m-20 text-5xl font-extrabold tracking-tighter lg:text-6xl',
className,
)}
>
{children}
</h1>
</As>
);
};

const H2: FC<PropsWithChildren<TypographyProps>> = ({
children,
className,
as = 'h2',
}) => {
const As = as;
return (
<h2
<As
className={cn(
'scroll-m-20 text-4xl font-extrabold tracking-tighter lg:text-5xl',
className,
)}
>
{children}
</h2>
</As>
);
};

const H3: FC<PropsWithChildren<TypographyProps>> = ({
children,
className,
as = 'h3',
}) => {
const As = as;
return (
<h3
<As
className={cn(
'scroll-m-20 text-3xl font-bold tracking-tight lg:text-4xl',
className,
)}
>
{children}
</h3>
</As>
);
};

const H4: FC<PropsWithChildren<TypographyProps>> = ({
children,
className,
as = 'h4',
}) => {
const As = as;
return (
<h4
<As
className={cn(
'scroll-m-20 text-2xl font-bold tracking-tight lg:text-3xl',
className,
)}
>
{children}
</h4>
</As>
);
};

const P: FC<PropsWithChildren<TypographyProps>> = ({ children, className }) => {
const P: FC<PropsWithChildren<TypographyProps>> = ({
children,
className,
as = 'p',
}) => {
const As = as;
return (
<p
<As
className={cn(
'text-gray-11 dark:text-graydark-11 leading-6 tracking-tight [&:not(:first-child)]:mt-6',
'text-gray-11 dark:text-graydark-11 leading-7 tracking-tight',
className,
)}
>
{children}
</p>
</As>
);
};

Expand Down
Loading

0 comments on commit e4ef956

Please sign in to comment.