Skip to content
Merged
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
72 changes: 1 addition & 71 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -1,71 +1 @@
<<<<<<< HEAD
<<<<<<< HEAD
pnpm lint-staged
=======
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

echo "๐Ÿ”Ž pre-commit: lint-staged ์‹คํ–‰ ๋ฐ ์ตœ์ข… ์ ๊ฒ€ ์‹œ์ž‘"

# 0) ์ปค๋ฐ‹์— ํฌํ•จ๋œ ํŒŒ์ผ ๋ชฉ๋ก (์ถ”๊ฐ€/๋ณต์‚ฌ/์ˆ˜์ •)
STAGED_FILES="$(git diff --name-only --cached --diff-filter=ACMR)"
if [ -z "$STAGED_FILES" ]; then
echo "โ„น๏ธ ์Šคํ…Œ์ด์ง•๋œ ํŒŒ์ผ์ด ์—†์Šต๋‹ˆ๋‹ค. ๊ฑด๋„ˆ๋œ๋‹ˆ๋‹ค."
exit 0
fi

# 1) ๋ณ€๊ฒฝ ํŒŒ์ผ๋งŒ ์ž๋™ ์ˆ˜์ • (eslint --fix, prettier --write)
if ! pnpm lint-staged; then
echo
echo "โŒ lint-staged ๋‹จ๊ณ„์—์„œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค."
echo " - ์ž๋™์ˆ˜์ • ๋ถˆ๊ฐ€ํ•œ ๋ฆฐํŠธ ์—๋Ÿฌ๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์–ด์š”."
echo " - ๋กœ์ปฌ์—์„œ 'pnpm lint'๋กœ ์—๋Ÿฌ๋ฅผ ํ™•์ธํ•˜๊ณ  ์ˆ˜์ •ํ•œ ๋’ค ๋‹ค์‹œ ์ปค๋ฐ‹ํ•˜์„ธ์š”."
exit 1
fi

# 2) ์ตœ์ข… ์ ๊ฒ€: ์Šคํ…Œ์ด์ง•๋œ ํŒŒ์ผ๋งŒ ๋Œ€์ƒ์œผ๋กœ ๊ฒ€์‚ฌ(์ˆ˜์ • ์—†์ด ์‹คํŒจ๋งŒ ๊ฐ์ง€)
PRETTIER_FAIL=0
ESLINT_FAIL=0

# ๊ฐœํ–‰๋งŒ ๊ตฌ๋ถ„์ž๋กœ ์‚ฌ์šฉ (๊ณต๋ฐฑ ํฌํ•จ ํŒŒ์ผ๋ช… ์•ˆ์ „)
IFS="$(printf '\n')"
for f in $STAGED_FILES; do
case "$f" in
*.js|*.jsx|*.ts|*.tsx|*.json|*.css|*.md)
# Prettier ํฌ๋งท ์ค€์ˆ˜ ํ™•์ธ (์ˆ˜์ • ์—†์ด ๊ฒ€์‚ฌ)
pnpm -s prettier --check "$f" || PRETTIER_FAIL=1
;;
esac
done

for f in $STAGED_FILES; do
case "$f" in
*.js|*.jsx|*.ts|*.tsx)
# ESLint ์ตœ์ข… ํ™•์ธ (์ˆ˜์ • ์—†์ด ๊ฒ€์‚ฌ)
pnpm -s eslint --max-warnings=0 "$f" || ESLINT_FAIL=1
;;
esac
done
unset IFS

if [ "$PRETTIER_FAIL" -ne 0 ]; then
echo
echo "โŒ Prettier ํฌ๋งท ์œ„๋ฐ˜์ด ๋‚จ์•„ ์žˆ์Šต๋‹ˆ๋‹ค."
echo " - 'pnpm format' ํ›„ ๋‹ค์‹œ ์ปค๋ฐ‹ํ•˜์„ธ์š”."
exit 1
fi

if [ "$ESLINT_FAIL" -ne 0 ]; then
echo
echo "โŒ ESLint ์œ„๋ฐ˜์ด ๋‚จ์•„ ์žˆ์Šต๋‹ˆ๋‹ค."
echo " - 'pnpm lint:fix' ๋˜๋Š” ์ˆ˜๋™ ์ˆ˜์ • ํ›„ ๋‹ค์‹œ ์ปค๋ฐ‹ํ•˜์„ธ์š”."
exit 1
fi

COUNT="$(printf '%s\n' "$STAGED_FILES" | wc -l | tr -d ' ')"
echo "โœ… pre-commit ํ†ต๊ณผ: ${COUNT}๊ฐœ ํŒŒ์ผ ์ ๊ฒ€ ์™„๋ฃŒ"
exit 0
>>>>>>> 382ffc3 (Chore/code style commit convention)
=======
pnpm lint-staged
>>>>>>> 103f47c (Chore/lucide react)
pnpm lint-staged

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Restore interpreter and husky bootstrap in pre-commit hook

The hook now consists of a single pnpm lint-staged line and no longer declares a shebang or sources Huskyโ€™s husky.sh. Git executes hook files directly, so without an interpreter header the hook can raise Exec format error on platforms that donโ€™t automatically fall back to /bin/sh. In addition, removing the bootstrap script drops the local node_modules/.bin from PATH, so pnpm (and lint-staged) may not be found for contributors who rely on Corepack or non-global installations. As a result pre-commit checks can fail or be silently skipped across environments.

Useful? React with ๐Ÿ‘ย / ๐Ÿ‘Ž.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,15 @@
"dependencies": {
"@fontsource/pretendard": "^5.2.5",
"@radix-ui/react-slot": "^1.2.3",
"@tanstack/react-query": "^5.90.2",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"lucide-react": "^0.544.0",
"next": "15.5.3",
"react": "19.1.0",
"react-dom": "19.1.0",
"tailwind-merge": "^3.3.1"
"tailwind-merge": "^3.3.1",
"zustand": "^5.0.8"
},
"devDependencies": {
"@commitlint/cli": "^19.8.1",
Expand Down
53 changes: 53 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 18 additions & 1 deletion src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { Metadata } from "next";
import "./globals.css";
import { Providers } from "./providers";

export const metadata: Metadata = {
title: "Custom Daily Planner",
Expand All @@ -9,7 +10,23 @@ export const metadata: Metadata = {
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="ko">
<body>{children}</body>
<body>
{/*
Providers๋กœ ๊ฐ์‹ธ๋Š” ์ด์œ :
- React Query์˜ QueryClientProvider๋ฅผ ์ „์—ญ ์ ์šฉ
- ๋ชจ๋“  ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋™์ผํ•œ client & cache ๊ณต์œ 
- useQuery, useMutation ํ›…์ด ์–ด๋””์„œ๋“  ์ •์ƒ ๋™์ž‘
*/}
{/*
โœ… ์ถ”ํ›„ ํ™•์žฅ ์˜ˆ์‹œ:
<AuthProvider>
<ThemeProvider>
<Providers>{children}</Providers>
</ThemeProvider>
</AuthProvider>
*/}
<Providers>{children}</Providers>
</body>
</html>
);
}
17 changes: 17 additions & 0 deletions src/app/providers.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
"use client";

import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { ReactNode, useState } from "react";

export function Providers({ children }: { children: ReactNode }) {
const [client] = useState(
() =>
new QueryClient({
defaultOptions: {
queries: { retry: 2, refetchOnWindowFocus: false, staleTime: 30_000, gcTime: 5 * 60_000 },
},
}),
);

return <QueryClientProvider client={client}>{children}</QueryClientProvider>;
}
2 changes: 1 addition & 1 deletion src/components/ui/input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ function Input({ className, type, ...props }: React.ComponentProps<"input">) {
data-slot="input"
className={cn(
// ํฌ๊ธฐ/๋ ˆ์ด์•„์›ƒ
"h-10 w-full min-w-0 rounded-md px-3 py-2 text-sm outline-none transition-colors",
"h-12 w-full min-w-0 rounded-md px-3 py-2 text-sm outline-none transition-colors",
// ๊ธฐ๋ณธ ํ…์ŠคํŠธ/๋ฐฐ๊ฒฝ
"bg-white text-[#111827]",
// ๊ธฐ๋ณธ ํ…Œ๋‘๋ฆฌ(1px, ํšŒ์ƒ‰)
Expand Down
18 changes: 18 additions & 0 deletions src/stores/useUserStore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { create } from "zustand";

type UserState = {
userId: string | null;
setUserId: (id: string | null) => void;
reset: () => void;
// ์•ž์œผ๋กœ ํ™•์žฅ๋  ์ˆ˜ ์žˆ๋Š” ์ „์—ญ UI ์ƒํƒœ ์˜ˆ์‹œ
theme: "light" | "dark";
toggleTheme: () => void;
};

export const useUserStore = create<UserState>((set) => ({
userId: null,
setUserId: (id) => set({ userId: id }),
reset: () => set({ userId: null }),
theme: "light",
toggleTheme: () => set((s) => ({ theme: s.theme === "light" ? "dark" : "light" })),
}));