Skip to content

Commit

Permalink
Feature/#318 - 다크모드 api 적용 (#319)
Browse files Browse the repository at this point in the history
  • Loading branch information
baegyeong authored Dec 2, 2024
2 parents 5fcb65d + a9bb130 commit 8d14d70
Show file tree
Hide file tree
Showing 13 changed files with 117 additions and 20 deletions.
1 change: 1 addition & 0 deletions packages/frontend/src/apis/queries/stocks/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export const GetStockSchema = z.object({
volume: z.number(),
marketCap: z.string(),
rank: z.number(),
isRising: z.boolean(),
});

export const GetStockListResponseSchema = z.object({
Expand Down
2 changes: 2 additions & 0 deletions packages/frontend/src/apis/queries/user/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ export * from './schema';
export * from './useGetUserInfo';
export * from './useGetUserStock';
export * from './usePostUserNickname';
export * from './useGetUserTheme';
export * from './usePatchUserTheme';
13 changes: 11 additions & 2 deletions packages/frontend/src/apis/queries/user/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,17 @@ export const PostUserNicknameSchema = z.object({

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

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

export type GetUserTheme = z.infer<typeof GetUserThemeSchema>;
export type GetUserTheme = z.infer<typeof UserThemeSchema>;

export type PatchUserThemeRequest = z.infer<typeof UserThemeSchema>;

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

export type PatchUserTheme = z.infer<typeof PatchUserThemeSchema>;
17 changes: 17 additions & 0 deletions packages/frontend/src/apis/queries/user/useGetUserTheme.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { useQuery } from '@tanstack/react-query';
import { UserThemeSchema, type GetUserTheme } from './schema';
import { get } from '@/apis/utils/get';

const getUserTheme = () =>
get<GetUserTheme>({
schema: UserThemeSchema,
url: '/api/user/theme',
});

export const useGetUserTheme = () => {
return useQuery({
queryKey: ['userTheme'],
queryFn: getUserTheme,
staleTime: 1000 * 60 * 5,
});
};
26 changes: 26 additions & 0 deletions packages/frontend/src/apis/queries/user/usePatchUserTheme.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { useMutation, useQueryClient } from '@tanstack/react-query';
import {
type PatchUserTheme,
type PatchUserThemeRequest,
UserThemeSchema,
} from './schema';
import { patch } from '@/apis/utils/patch';

const patchUserTheme = ({ theme }: PatchUserThemeRequest) =>
patch<PatchUserTheme>({
params: { theme },
schema: UserThemeSchema,
url: '/api/user/theme',
});

export const usePatchUserTheme = () => {
const queryClient = useQueryClient();

return useMutation({
mutationKey: ['patchTheme'],
mutationFn: ({ theme }: PatchUserThemeRequest) => patchUserTheme({ theme }),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['userTheme'] });
},
});
};
25 changes: 25 additions & 0 deletions packages/frontend/src/apis/utils/patch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { AxiosRequestConfig } from 'axios';
import { z } from 'zod';
import { instance } from '../config';
import { formatZodError } from './formatZodError';

interface PatchParams {
params?: AxiosRequestConfig['params'];
schema: z.ZodType;
url: string;
}

export const patch = async <T>({
params,
schema,
url,
}: PatchParams): Promise<T> => {
const { data } = await instance.patch(url, params);
const result = schema.safeParse(data);

if (!result.success) {
throw new Error(formatZodError(result.error));
}

return data;
};
23 changes: 21 additions & 2 deletions packages/frontend/src/components/layouts/Sidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { useState } from 'react';
import { useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import logoCharacter from '/logoCharacter.png';
import logoTitle from '/logoTitle.png';
import { Alarm } from './alarm';
import { MenuList } from './MenuList';
import { Search } from './search';
import { useGetUserTheme } from '@/apis/queries/user/useGetUserTheme';
import { usePatchUserTheme } from '@/apis/queries/user/usePatchUserTheme';
import { BOTTOM_MENU_ITEMS, TOP_MENU_ITEMS } from '@/constants/menuItems';
import { useOutsideClick } from '@/hooks/useOutsideClick';
import { type MenuSection } from '@/types/menu';
Expand All @@ -20,6 +22,17 @@ export const Sidebar = () => {
alarm: false,
});

const { data } = useGetUserTheme();
const { mutate } = usePatchUserTheme();

useEffect(() => {
if (data?.theme === 'light') {
document.body.classList.remove('dark');
return;
}
document.body.classList.add('dark');
}, [data]);

const ref = useOutsideClick(() => {
setShowTabs({ search: false, alarm: false });
});
Expand All @@ -44,7 +57,13 @@ export const Sidebar = () => {
}

if (item.text === '다크모드') {
document.body.classList.toggle('dark');
if (data?.theme === 'dark') {
mutate({ theme: 'light' });
}

if (data?.theme === 'light') {
mutate({ theme: 'dark' });
}
}
};

Expand Down
1 change: 1 addition & 0 deletions packages/frontend/src/components/layouts/search/Search.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export const Search = ({ className }: SearchProps) => {
</p>
<form className="mb-8 flex gap-4" onSubmit={handleSubmit}>
<Input
className="bg-white"
placeholder="검색어"
onChange={(e) => setStockName(e.target.value)}
autoFocus
Expand Down
2 changes: 1 addition & 1 deletion packages/frontend/src/components/ui/button/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { cva, VariantProps } from 'class-variance-authority';
import { cn } from '@/utils/cn';

export const ButtonVariants = cva(
`display-bold12 border rounded shadow-black py-1 border-orange`,
`display-bold14 border rounded shadow-black py-1 border-orange`,
{
variants: {
backgroundColor: {
Expand Down
4 changes: 2 additions & 2 deletions packages/frontend/src/pages/login/Login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ export const Login = () => {

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 dark:from-[#e35f5f] dark:to-[#ead16b]">
<div className="absolute inset-0 rounded-md bg-white/40 backdrop-blur-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-[#e26262] dark:to-[#f3d55d]">
<div className="bg-white/4 absolute inset-0 rounded-md backdrop-blur-sm" />
<section className="relative z-10">
<h2 className="display-bold24">스마트한 투자의 첫걸음,</h2>
<p className="display-medium20">주춤주춤과 함께해요!</p>
Expand Down
8 changes: 1 addition & 7 deletions packages/frontend/src/pages/stock-detail/TradingChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,8 @@ import {
useGetStocksPriceSeries,
} from '@/apis/queries/stocks';
import { TIME_UNIT } from '@/constants/timeUnit';
import { ChartTheme, lightTheme } from '@/styles/theme';

interface TradingChartProps {
theme?: ChartTheme;
}

export const TradingChart = ({ theme = lightTheme }: TradingChartProps) => {
export const TradingChart = () => {
const { stockId } = useParams();
const [timeunit, setTimeunit] =
useState<StockTimeSeriesRequest['timeunit']>('day');
Expand All @@ -29,7 +24,6 @@ export const TradingChart = ({ theme = lightTheme }: TradingChartProps) => {
priceData: data?.priceDtoList ?? [],
volumeData: data?.volumeDtoList ?? [],
containerRef,
theme,
});

useChartResize({ containerRef, chart });
Expand Down
14 changes: 8 additions & 6 deletions packages/frontend/src/pages/stock-detail/hooks/useChart.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import type { ChartTheme } from '@/styles/theme';
import { createChart, type IChartApi } from 'lightweight-charts';
import { useEffect, useRef, RefObject } from 'react';
import {
PriceSchema,
StockTimeSeriesResponse,
VolumeSchema,
} from '@/apis/queries/stocks';
import { useGetUserTheme } from '@/apis/queries/user';
import { darkTheme, lightTheme } from '@/styles/theme';
import {
createCandlestickOptions,
createChartOptions,
Expand All @@ -15,7 +16,6 @@ import { getHistogramColorData } from '@/utils/getHistogramColorData';

interface UseChartProps {
containerRef: RefObject<HTMLDivElement>;
theme: ChartTheme;
priceData: StockTimeSeriesResponse['priceDtoList'];
volumeData: StockTimeSeriesResponse['volumeDtoList'];
}
Expand All @@ -35,19 +35,21 @@ const TransformVolumeData = VolumeSchema.transform((item) => ({

export const useChart = ({
containerRef,
theme,
priceData,
volumeData,
}: UseChartProps) => {
const chart = useRef<IChartApi>();

const { data } = useGetUserTheme();
const graphTheme = data?.theme === 'light' ? lightTheme : darkTheme;

useEffect(() => {
if (!containerRef.current) return;

chart.current = createChart(containerRef.current, {
width: containerRef.current.clientWidth,
height: containerRef.current.clientHeight,
...createChartOptions(theme),
...createChartOptions(graphTheme),
handleScroll: {
mouseWheel: false,
pressedMouseMove: false,
Expand All @@ -74,7 +76,7 @@ export const useChart = ({
volumeSeries.setData(histogramData);

const candleSeries = chart.current.addCandlestickSeries(
createCandlestickOptions(theme),
createCandlestickOptions(graphTheme),
);
const transformedPriceData = priceData.map((item) =>
TransformPriceData.parse(item),
Expand All @@ -84,7 +86,7 @@ export const useChart = ({
return () => {
chart.current?.remove();
};
}, [containerRef, theme, priceData, volumeData]);
}, [containerRef, graphTheme, priceData, volumeData]);

return chart;
};
1 change: 1 addition & 0 deletions packages/frontend/tailwind.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const config: Config = {
extend: {
backgroundColor: {
'black/4': 'rgba(0, 0, 0, 0.4)',
'white/4': 'rgba(255,255,255,0.4)',
},
},
colors: {
Expand Down

0 comments on commit 8d14d70

Please sign in to comment.