Skip to content

Commit

Permalink
Refactor/app group layout (#34)
Browse files Browse the repository at this point in the history
  • Loading branch information
bepyan authored Feb 2, 2024
2 parents 25a6246 + abf6a6a commit 2d5d681
Show file tree
Hide file tree
Showing 18 changed files with 155 additions and 103 deletions.
7 changes: 7 additions & 0 deletions apps/back-office/src/app/(auth)/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import BaseLayout from "~/components/base-layout";

export default function RootLayout({
children,
}: { children: React.ReactNode }) {
return <BaseLayout>{children}</BaseLayout>;
}
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { ProfileForm } from "~/components/form-example";

export default function Page() {
return (
<div className="space-y-7">
<div className="px-6 py-8 pb-[126px] space-y-7">
<ProfileForm />
</div>
);
Expand Down
File renamed without changes.
File renamed without changes.
5 changes: 1 addition & 4 deletions apps/back-office/src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import BaseLayout from "~/components/base-layout";
import { Toaster } from "~/components/ui/sonner";
import { cn } from "~/libs/utils";
import QueryProvider from "~/providers/query-provider";
Expand All @@ -18,9 +17,7 @@ export default function RootLayout({
/>
</head>
<body className={cn("bg-background font-pretendard antialiased")}>
<QueryProvider>
<BaseLayout>{children}</BaseLayout>
</QueryProvider>
<QueryProvider>{children}</QueryProvider>
<Toaster />
</body>
</html>
Expand Down
15 changes: 2 additions & 13 deletions apps/back-office/src/components/base-layout/base-layout.meta.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { LayoutOption, LayoutRoute } from "./base-layout.type";
import { LayoutRoute } from "./base-layout.type";

const layoutRoutes = [
export const authRoutes = [
{
pathname: "/",
title: "서비스 관리",
Expand All @@ -10,14 +10,3 @@ const layoutRoutes = [
title: "테스트",
},
] satisfies LayoutRoute[];

const layoutOptions: LayoutOption[] = [
{ pathname: "/login", hasSidebar: false },
];

const defaultLayoutOption: Omit<LayoutOption, "pathname"> = {
hasHeader: true,
hasSidebar: true,
};

export { layoutRoutes, layoutOptions, defaultLayoutOption };
87 changes: 35 additions & 52 deletions apps/back-office/src/components/base-layout/base-layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,72 +4,55 @@ import { ChevronRightIcon, TargetIcon } from "lucide-react";
import Link from "next/link";
import { cn } from "~/libs/utils";
import { Button, buttonVariants } from "../ui/button";
import {
defaultLayoutOption,
layoutOptions,
layoutRoutes,
} from "./base-layout.meta";
import { authRoutes } from "./base-layout.meta";
import useLayoutPathname from "./hooks";

export interface BaseLayoutProps {
children?: React.ReactNode;
}

export default function BaseLayout({ children }: BaseLayoutProps) {
const { hasHeader, hasSidebar, currentRoute } = useLayoutPathname(
layoutRoutes,
{ layoutOptions, defaultLayoutOption },
);
const { currentRoute } = useLayoutPathname(authRoutes);

return (
<div className="relative flex min-h-screen flex-col">
{hasHeader && (
<header className="fixed top-0 z-50 w-full border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
<div className="flex items-center h-20 px-12 py-5">
<Button variant="ghost" size="icon">
<TargetIcon className="h-7 w-7" />
</Button>
<div className="ml-auto">
<Button variant="ghost">로그아웃</Button>
</div>
<header className="fixed top-0 z-50 w-full border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
<div className="flex items-center h-20 px-12 py-5">
<Button variant="ghost" size="icon">
<TargetIcon className="h-7 w-7" />
</Button>
<div className="ml-auto">
<Button variant="ghost">로그아웃</Button>
</div>
</header>
)}
</div>
</header>

{hasSidebar && (
<aside className="fixed left-0 top-20 bottom-0 w-[220px] border-r">
<nav className="grid gap-1 py-8 px-6">
{layoutRoutes.map((route, index) => {
const isActive = route.pathname === currentRoute?.pathname;
<aside className="fixed left-0 top-20 bottom-0 w-[220px] border-r">
<nav className="grid gap-1 py-8 px-6">
{authRoutes.map((route, index) => {
const isActive = route.pathname === currentRoute?.pathname;

return (
<Link
key={index}
href={route.pathname}
className={cn(
buttonVariants({
variant: isActive ? "secondary" : "ghost",
size: "default",
}),
"justify-start",
)}
>
{route.title}
{isActive && <ChevronRightIcon className="ml-auto h-4 w-4" />}
</Link>
);
})}
</nav>
</aside>
)}
return (
<Link
key={index}
href={route.pathname}
className={cn(
buttonVariants({
variant: isActive ? "secondary" : "ghost",
size: "default",
}),
"justify-start",
)}
>
{route.title}
{isActive && <ChevronRightIcon className="ml-auto h-4 w-4" />}
</Link>
);
})}
</nav>
</aside>

<main
className={`${hasSidebar ? "ml-[220px]" : ""} ${
hasHeader ? "mt-20" : ""
}`}
>
{children}
</main>
<main className="ml-[220px] mt-20">{children}</main>
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,3 @@ export interface LayoutRoute {
pathname: string;
title: string;
}

export interface LayoutOption {
pathname: string;
hasHeader?: boolean;
hasSidebar?: boolean;
}
Original file line number Diff line number Diff line change
@@ -1,31 +1,17 @@
"use client";

import { usePathname } from "next/navigation";
import { LayoutOption, LayoutRoute } from "../base-layout.type";
import { LayoutRoute } from "../base-layout.type";

const getBoolean = (value: boolean | undefined | null, defaultValue: boolean) =>
typeof value === "boolean" ? value : defaultValue;

const useLayoutPathname = (
layoutRoutes: Array<LayoutRoute>,
options: {
layoutOptions: Array<LayoutOption>;
defaultLayoutOption: Omit<LayoutOption, "pathname">;
},
) => {
const useLayoutPathname = (layoutRoutes: Array<LayoutRoute>) => {
const pathname = usePathname();
const currentRoute = layoutRoutes.find((route) =>
pathname === "/"
? route.pathname === pathname
: route.pathname.startsWith(pathname),
);
const layoutOption =
options.layoutOptions.find((layout) => layout.pathname === pathname) ||
options.defaultLayoutOption;
const hasHeader = getBoolean(layoutOption.hasHeader, true);
const hasSidebar = getBoolean(layoutOption.hasSidebar, true);

return { currentRoute, hasHeader, hasSidebar };
return { currentRoute };
};

export default useLayoutPathname;
10 changes: 5 additions & 5 deletions apps/back-office/src/components/manage-service/manage-drawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { Form, FormControl, FormField, FormItem } from "~/components/ui/form";
import { Input } from "~/components/ui/input";
import { Label } from "~/components/ui/label";
import { Separator } from "~/components/ui/separator";
import { Textarea } from "~/components/ui/textarea";
import { ClearTextArea, Textarea } from "~/components/ui/textarea";
import { useManageDrawer } from "./hooks/use-manage-drawer";
import { ManageValues, manageFormProps } from "./manage-drawer.meta";

Expand Down Expand Up @@ -68,7 +68,7 @@ export function ManageDrawerContent() {
render={({ field }) => (
<FormItem>
<FormControl>
<Textarea
<ClearTextArea
className="min-h-9 text-2xl font-bold"
placeholder="제목 없음"
{...field}
Expand Down Expand Up @@ -101,11 +101,11 @@ export function ManageDrawerContent() {
control={form.control}
name="content"
render={({ field }) => (
<FormItem>
<FormItem className="h-full">
<FormControl>
<Textarea
<ClearTextArea
placeholder="텍스트를 작성해 주세요"
className="h-full"
className="h-full text-base"
{...field}
/>
</FormControl>
Expand Down
2 changes: 1 addition & 1 deletion apps/back-office/src/components/ui/input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
<input
type={type}
className={cn(
"flex h-10 w-full rounded-md bg-background px-3 py-2 text-sm file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50",
"flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",
className,
)}
ref={ref}
Expand Down
20 changes: 18 additions & 2 deletions apps/back-office/src/components/ui/textarea.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
return (
<textarea
className={cn(
"flex min-h-[80px] w-full border-input bg-background text-base resize-none placeholder:text-muted-foreground focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50",
"flex min-h-[60px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",
className,
)}
ref={ref}
Expand All @@ -21,4 +21,20 @@ const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
);
Textarea.displayName = "Textarea";

export { Textarea };
const ClearTextArea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
({ className, ...props }, ref) => {
return (
<Textarea
className={cn(
"p-0 resize-none border-none shadow-none focus-visible:ring-0",
className,
)}
ref={ref}
{...props}
/>
);
},
);
ClearTextArea.displayName = "ClearTextArea";

export { Textarea, ClearTextArea };
1 change: 1 addition & 0 deletions apps/web/.babelrc.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module.exports = {
presets: ["next/babel"],
plugins: [
"@babel/plugin-transform-private-methods",
[
"@stylexjs/babel-plugin",
{
Expand Down
1 change: 1 addition & 0 deletions apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"react-remove-scroll": "^2.5.7"
},
"devDependencies": {
"@babel/plugin-transform-private-methods": "^7.23.3",
"@babel/runtime": "^7.23.8",
"@stylexjs/nextjs-plugin": "^0.4.1",
"@tanstack/react-query-devtools": "^5.17.21",
Expand Down
8 changes: 8 additions & 0 deletions apps/web/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@ export default function RootLayout({
}>) {
return (
<html lang="ko">
<head>
<link
rel="stylesheet"
as="style"
crossOrigin="anonymous"
href="https://cdn.jsdelivr.net/gh/orioncactus/[email protected]/dist/web/variable/pretendardvariable-dynamic-subset.css"
/>
</head>
<body {...stylex.props()}>
<QueryProvider>{children}</QueryProvider>
</body>
Expand Down
2 changes: 0 additions & 2 deletions apps/web/src/styles/globals.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
@import url('https://cdn.jsdelivr.net/gh/orioncactus/[email protected]/dist/web/static/pretendard.min.css');

* {
box-sizing: border-box;
margin: 0;
Expand Down
Loading

0 comments on commit 2d5d681

Please sign in to comment.