Skip to content
Open
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
196 changes: 172 additions & 24 deletions apps/nextjs-app/src/app/app/_components/dashboard-info.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,178 @@ import { useUser } from '@/lib/auth';
export const DashboardInfo = () => {
const user = useUser();

if (!user.data) return null;

const isAdmin = user.data?.role === 'ADMIN';
const isUser = user.data?.role === 'USER';

return (
<>
<h1 className="text-xl">
Welcome <b>{`${user.data?.firstName} ${user.data?.lastName}`}</b>
</h1>
<h4 className="my-3">
Your role is : <b>{user.data?.role}</b>
</h4>
<p className="font-medium">In this application you can:</p>
{user.data?.role === 'USER' && (
<ul className="my-4 list-inside list-disc">
<li>Create comments in discussions</li>
<li>Delete own comments</li>
</ul>
)}
{user.data?.role === 'ADMIN' && (
<ul className="my-4 list-inside list-disc">
<li>Create discussions</li>
<li>Edit discussions</li>
<li>Delete discussions</li>
<li>Comment on discussions</li>
<li>Delete all comments</li>
</ul>
)}
</>
<div className="space-y-6">
<div className="rounded-lg bg-gradient-to-r from-blue-500 to-purple-600 p-6 text-white shadow-lg">
<h1 className="text-3xl font-bold">
Welcome back, {`${user.data?.firstName} ${user.data?.lastName}`}! 👋
</h1>
<div className="mt-3 flex items-center gap-2">
<svg
className="size-5"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"
/>
</svg>
<span className="text-lg font-medium">Role: {user.data?.role}</span>
</div>
</div>

<div className="rounded-lg border border-gray-200 bg-white p-6 shadow-md">
<div className="mb-4 flex items-center gap-2">
<svg
className="size-6 text-blue-600"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"
/>
</svg>
<h2 className="text-xl font-semibold text-gray-800">
Available Features
</h2>
</div>
<p className="mb-4 text-gray-600">
In this application you can:
</p>
{isUser && (
<ul className="space-y-2">
<li className="flex items-center gap-3 rounded-md bg-gray-50 p-3 transition-colors hover:bg-gray-100">
<svg
className="size-5 text-green-600"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M12 4v16m8-8H4"
/>
</svg>
<span>Create comments in discussions</span>
</li>
<li className="flex items-center gap-3 rounded-md bg-gray-50 p-3 transition-colors hover:bg-gray-100">
<svg
className="size-5 text-red-600"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
/>
</svg>
<span>Delete own comments</span>
</li>
</ul>
)}
{isAdmin && (
<ul className="space-y-2">
<li className="flex items-center gap-3 rounded-md bg-gray-50 p-3 transition-colors hover:bg-gray-100">
<svg
className="size-5 text-green-600"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M12 4v16m8-8H4"
/>
</svg>
<span>Create discussions</span>
</li>
<li className="flex items-center gap-3 rounded-md bg-gray-50 p-3 transition-colors hover:bg-gray-100">
<svg
className="size-5 text-blue-600"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"
/>
</svg>
<span>Edit discussions</span>
</li>
<li className="flex items-center gap-3 rounded-md bg-gray-50 p-3 transition-colors hover:bg-gray-100">
<svg
className="size-5 text-red-600"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
/>
</svg>
<span>Delete discussions</span>
</li>
<li className="flex items-center gap-3 rounded-md bg-gray-50 p-3 transition-colors hover:bg-gray-100">
<svg
className="size-5 text-purple-600"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z"
/>
</svg>
<span>Comment on discussions</span>
</li>
<li className="flex items-center gap-3 rounded-md bg-gray-50 p-3 transition-colors hover:bg-gray-100">
<svg
className="size-5 text-orange-600"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
/>
</svg>
<span>Delete all comments</span>
</li>
</ul>
)}
</div>
</div>
);
};
32 changes: 24 additions & 8 deletions apps/nextjs-app/src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,28 @@ const HomePage = () => {
const isLoggedIn = checkLoggedIn();

return (
<div className="flex h-screen items-center bg-white">
<div className="flex min-h-screen items-center bg-gradient-to-br from-blue-50 via-white to-purple-50">
<div className="mx-auto max-w-7xl px-4 py-12 text-center sm:px-6 lg:px-8 lg:py-16">
<h2 className="text-3xl font-extrabold tracking-tight text-gray-900 sm:text-4xl">
<span className="block">Bulletproof React</span>
<div className="mb-8 flex justify-center">
<img
src="/logo.svg"
alt="react"
className="h-24 w-24 animate-pulse"
/>
</div>
<h2 className="text-4xl font-extrabold tracking-tight text-gray-900 sm:text-5xl lg:text-6xl">
<span className="block bg-gradient-to-r from-blue-600 to-purple-600 bg-clip-text text-transparent">
Bulletproof React
</span>
</h2>
<img src="/logo.svg" alt="react" />
<p>Showcasing Best Practices For Building React Applications</p>
<div className="mt-8 flex justify-center">
<div className="inline-flex rounded-md shadow">
<p className="mt-4 text-lg text-gray-600 sm:text-xl">
Showcasing Best Practices For Building React Applications
</p>
<p className="mt-2 text-sm text-gray-500">
Production-ready patterns and architectural decisions
</p>
<div className="mt-10 flex flex-col items-center justify-center gap-4 sm:flex-row">
<div className="inline-flex rounded-lg shadow-lg transition-transform hover:scale-105">
<Link
href={
isLoggedIn
Expand All @@ -24,6 +37,7 @@ const HomePage = () => {
}
>
<Button
className="px-8 py-3 text-base"
icon={
<svg
xmlns="http://www.w3.org/2000/svg"
Expand All @@ -45,14 +59,16 @@ const HomePage = () => {
</Button>
</Link>
</div>
<div className="ml-3 inline-flex">
<div className="inline-flex">
<a
href="https://github.com/alan2207/bulletproof-react"
target="_blank"
rel="noreferrer"
className="transition-transform hover:scale-105"
>
<Button
variant="outline"
className="px-8 py-3 text-base border-2"
icon={
<svg
fill="currentColor"
Expand Down
7 changes: 6 additions & 1 deletion apps/nextjs-app/src/testing/mocks/handlers/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,12 @@ export const authHandlers = [

try {
const { user } = requireAuth(cookies);
return HttpResponse.json({ data: user });
return HttpResponse.json({
data: user,
meta: {
lastLogin: Date.now(),
},
});
} catch (error: any) {
return HttpResponse.json(
{ message: error?.message || 'Server Error' },
Expand Down
1 change: 1 addition & 0 deletions apps/react-vite/src/components/ui/button/button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
const Comp = asChild ? Slot : 'button';
return (
<Comp
data-testid="btn"
className={cn(buttonVariants({ variant, size, className }))}
ref={ref}
{...props}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export const LoginForm = ({ onSuccess }: LoginFormProps) => {
type="submit"
className="w-full"
>
Log in
Sign In
</Button>
</div>
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export const createComment = ({
}: {
data: CreateCommentInput;
}): Promise<Comment> => {
console.log('Creating comment for discussion:', data.discussionId);
return api.post('/comments', data);
};

Expand Down