Skip to content

Commit

Permalink
Feature/#30 - 다크모드 구현 (#305)
Browse files Browse the repository at this point in the history
  • Loading branch information
baegyeong authored Nov 30, 2024
2 parents f2f7242 + e547153 commit 4938093
Show file tree
Hide file tree
Showing 22 changed files with 186 additions and 139 deletions.
34 changes: 0 additions & 34 deletions packages/frontend/src/apis/queries/auth/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,42 +14,8 @@ export const GetTestLoginSchema = z.object({

export type GetTestLogin = z.infer<typeof GetTestLoginSchema>;

export const GetUserInfoSchema = z.object({
nickname: z.string(),
subName: z.string(),
createdAt: z.string().datetime(),
email: z.string(),
type: z.string(),
});

export type GetUserInfo = z.infer<typeof GetUserInfoSchema>;

export const PostUserNicknameSchema = z.object({
message: z.string(),
date: z.string().datetime(),
});

export type PostUserNickname = z.infer<typeof PostUserNicknameSchema>;

export const PostLogoutSchema = z.object({
message: z.string(),
});

export type PostLogout = z.infer<typeof PostLogoutSchema>;

export const GetUserStockSchema = z.object({
id: z.number(),
stockId: z.string(),
name: z.string(),
isTrading: z.boolean(),
groupCode: z.string(),
createdAt: z.string().datetime(),
});

export type GetUserStock = z.infer<typeof GetUserStockSchema>;

export const GetUserStockResponseSchema = z.object({
userStocks: z.array(GetUserStockSchema),
});

export type GetUserStockResponse = z.infer<typeof GetUserStockResponseSchema>;
4 changes: 4 additions & 0 deletions packages/frontend/src/apis/queries/user/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export * from './schema';
export * from './useGetUserInfo';
export * from './useGetUserStock';
export * from './usePostUserNickname';
41 changes: 41 additions & 0 deletions packages/frontend/src/apis/queries/user/schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { z } from 'zod';

export const GetUserInfoSchema = z.object({
nickname: z.string(),
subName: z.string(),
createdAt: z.string().datetime(),
email: z.string(),
type: z.string(),
});

export type GetUserInfo = z.infer<typeof GetUserInfoSchema>;

export const GetUserStockSchema = z.object({
id: z.number(),
stockId: z.string(),
name: z.string(),
isTrading: z.boolean(),
groupCode: z.string(),
createdAt: z.string().datetime(),
});

export type GetUserStock = z.infer<typeof GetUserStockSchema>;

export const GetUserStockResponseSchema = z.object({
userStocks: z.array(GetUserStockSchema),
});

export type GetUserStockResponse = z.infer<typeof GetUserStockResponseSchema>;

export const PostUserNicknameSchema = z.object({
message: z.string(),
date: z.string().datetime(),
});

export type PostUserNickname = z.infer<typeof PostUserNicknameSchema>;

export const GetUserThemeSchema = z.object({
theme: z.enum(['light', 'dark']),
});

export type GetUserTheme = z.infer<typeof GetUserThemeSchema>;
Binary file removed packages/frontend/src/assets/google.png
Binary file not shown.
1 change: 1 addition & 0 deletions packages/frontend/src/assets/google.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion packages/frontend/src/components/layouts/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Sidebar } from './Sidebar';

export const Layout = () => {
return (
<div className="flex min-h-screen">
<div className="bg-extra-light-gray flex min-h-screen">
<Sidebar />
<main className="ml-20 flex-1">
<div className="h-full overflow-auto px-16 py-16 md:px-24 lg:px-28 xl:px-44">
Expand Down
57 changes: 38 additions & 19 deletions packages/frontend/src/components/layouts/Sidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import logoCharacter from '/logoCharacter.png';
import logoTitle from '/logoTitle.png';
import { Alarm } from './alarm';
Expand All @@ -9,30 +10,41 @@ import { useOutsideClick } from '@/hooks/useOutsideClick';
import { type MenuSection } from '@/types/menu';
import { cn } from '@/utils/cn';

type TabKey = 'search' | 'alarm';

export const Sidebar = () => {
const navigate = useNavigate();
const [isHovered, setIsHovered] = useState(false);
const [showSearch, setShowSearch] = useState(false);
const [showAlarm, setShowAlarm] = useState(false);
const [showTabs, setShowTabs] = useState<Record<TabKey, boolean>>({
search: false,
alarm: false,
});

const ref = useOutsideClick(() => {
if (showSearch) {
setShowSearch(false);
}

if (showAlarm) {
setShowAlarm(false);
}
setShowTabs({ search: false, alarm: false });
});

const handleMenuItemClick = (item: MenuSection) => {
if (item.text === '검색') {
setShowSearch(true);
setShowAlarm(false);
const tab: Record<string, TabKey> = {
검색: 'search',
알림: 'alarm',
};

const tabKey = tab[item.text];
if (tabKey) {
setShowTabs((prev) =>
Object.keys(prev).reduce(
(acc, key) => ({
...acc,
[key]: key === tabKey,
}),
{} as Record<TabKey, boolean>,
),
);
}

if (item.text === '알림') {
setShowSearch(false);
setShowAlarm(true);
if (item.text === '다크모드') {
document.body.classList.toggle('dark');
}
};

Expand All @@ -48,7 +60,10 @@ export const Sidebar = () => {
onMouseLeave={() => setIsHovered(false)}
>
<section className="flex flex-col justify-center gap-8">
<header className="flex items-center gap-4">
<header
className="flex items-center gap-4"
onClick={() => navigate('/')}
>
<img src={logoCharacter} alt="로고 캐릭터" className="w-20" />
<img
src={logoTitle}
Expand All @@ -68,7 +83,11 @@ export const Sidebar = () => {
isHovered={isHovered}
onItemClick={handleMenuItemClick}
/>
<MenuList items={BOTTOM_MENU_ITEMS} isHovered={isHovered} />
<MenuList
items={BOTTOM_MENU_ITEMS}
isHovered={isHovered}
onItemClick={handleMenuItemClick}
/>
</div>
</div>
</section>
Expand All @@ -79,8 +98,8 @@ export const Sidebar = () => {
isHovered ? 'left-60' : 'left-24',
)}
>
{showSearch && <Search className="h-screen" />}
{showAlarm && <Alarm className="h-screen" />}
{showTabs.search && <Search className="h-screen" />}
{showTabs.alarm && <Alarm className="h-screen" />}
</div>
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion packages/frontend/src/components/ui/alarm/Alarm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export interface AlarmProps {

export const Alarm = ({ goalPrice, method, date }: AlarmProps) => {
return (
<article className="display-medium14 text-dark-gray flex flex-col gap-2 rounded-md bg-[#f6f6f6] p-4">
<article className="display-medium14 text-dark-gray bg-extra-light-gray flex flex-col gap-2 rounded-md p-4">
<span className="flex items-center gap-2">
<Flag />
목표가: {goalPrice?.toLocaleString()}
Expand Down
2 changes: 1 addition & 1 deletion packages/frontend/src/components/ui/input/Input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export const Input = ({ placeholder, className, ...props }: InputProps) => {
<input
placeholder={placeholder}
className={cn(
'border-dark-gray w-36 border-b focus:outline-none',
'border-dark-gray w-36 border-b bg-white focus:outline-none',
className,
)}
{...props}
Expand Down
37 changes: 36 additions & 1 deletion packages/frontend/src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,42 @@
@layer base {
html {
font-family: 'Pretendard-Regular';
background-color: #f0f0f0;
}

body {
color: var(--black);
}
}

@layer base {
:root {
--extra-light-gray: #f0f0f0;
--light-gray: #d9d9d9;
--gray: #8c8c8c;
--dark-gray: #4f4f4f;
--black: #000000;
--white: #ffffff;
--light-yellow: #ffdcac;
--light-orange: #ffcfac;
--orange: #ffa868;
--red: #ff4d4d;
--green: #7eeb7e;
--blue: #1a75ff;
}

.dark {
--extra-light-gray: #1f1f1f;
--light-gray: #4f4f4f;
--gray: #8c8c8c;
--dark-gray: #d9d9d9;
--black: #ffffff;
--white: #121212;
--light-yellow: #7c4818;
--light-orange: #ecb172;
--orange: #ff9137;
--red: #ff6b6b;
--green: #4caf50;
--blue: #4d9eff;
}
}

Expand Down
46 changes: 17 additions & 29 deletions packages/frontend/src/pages/login/Login.tsx
Original file line number Diff line number Diff line change
@@ -1,49 +1,37 @@
import { Link, useNavigate } from 'react-router-dom';
import { Link } from 'react-router-dom';
import { useGetTestLogin } from '@/apis/queries/auth/useGetTestLogin';
import google from '@/assets/google.png';
import Google from '@/assets/google.svg?react';
import { Button } from '@/components/ui/button';

interface LoginButtonProps {
to: string;
src: string;
alt: string;
onClick?: () => void;
}

export const Login = () => {
const navigate = useNavigate();
const googleLoginUrl = '/api/auth/google/login';
const { refetch } = useGetTestLogin({ password: 'test', username: 'test' });

return (
<div className="flex h-[calc(100vh-8rem)] flex-col items-center justify-center">
<main className="relative flex flex-col gap-36 rounded-lg bg-gradient-to-br from-[#ffe259] to-[#ffa751] p-16 py-24 shadow-sm">
<main className="relative flex flex-col gap-36 rounded-lg bg-gradient-to-br from-[#ffe259] to-[#ffa751] p-16 py-24 shadow-sm dark:from-[#e35f5f] dark:to-[#ead16b]">
<div className="absolute inset-0 rounded-md bg-white/40 backdrop-blur-sm" />
<section className="relative z-10">
<h2 className="display-bold24">스마트한 투자의 첫걸음,</h2>
<p className="display-medium20">주춤주춤과 함께해요!</p>
</section>
<section className="relative z-10 flex flex-col gap-4">
<LoginButton to={googleLoginUrl} src={google} alt="구글 로그인" />
<Button
onClick={() => {
refetch();
navigate('/');
}}
className="h-10 w-full"
>
게스트로 로그인
</Button>
<Link to={googleLoginUrl} className="w-72" reloadDocument>
<Button className="flex h-10 w-full items-center justify-center gap-4 px-10 dark:bg-black">
<Google />
<span>구글 로그인</span>
</Button>
</Link>
<Link to="/">
<Button
onClick={() => refetch()}
className="h-10 w-full dark:bg-black"
>
게스트로 로그인
</Button>
</Link>
</section>
</main>
</div>
);
};

export const LoginButton = ({ to, src, alt, onClick }: LoginButtonProps) => {
return (
<Link to={to} className="w-72" onClick={onClick} reloadDocument>
<img src={src} alt={alt} />
</Link>
);
};
2 changes: 1 addition & 1 deletion packages/frontend/src/pages/my-page/StockInfo.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { useQueryClient } from '@tanstack/react-query';
import { useNavigate } from 'react-router-dom';
import { GetLoginStatus } from '@/apis/queries/auth/schema';
import { useGetUserStock } from '@/apis/queries/auth/useGetUserStock';
import { useDeleteStockUser } from '@/apis/queries/stock-detail';
import { useGetUserStock } from '@/apis/queries/user/useGetUserStock';
import { Button } from '@/components/ui/button';

interface StockInfoProps {
Expand Down
4 changes: 2 additions & 2 deletions packages/frontend/src/pages/my-page/UserInfo.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useState } from 'react';
import { useGetUserInfo } from '@/apis/queries/auth/useGetUserInfo';
import { usePostLogout } from '@/apis/queries/auth/usePostLogout';
import { usePostUserNickname } from '@/apis/queries/auth/usePostUserNickname';
import { useGetUserInfo } from '@/apis/queries/user/useGetUserInfo';
import { usePostUserNickname } from '@/apis/queries/user/usePostUserNickname';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';

Expand Down
Loading

0 comments on commit 4938093

Please sign in to comment.