Skip to content

Commit

Permalink
Feature/#381 - 자잘한 UI 에러 수정 (#385)
Browse files Browse the repository at this point in the history
  • Loading branch information
baegyeong authored Dec 5, 2024
2 parents db28e9f + 6c8265d commit 366abf8
Show file tree
Hide file tree
Showing 17 changed files with 79 additions and 53 deletions.
1 change: 1 addition & 0 deletions packages/frontend/src/apis/queries/alarm/useGetAlarm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ export const useGetAlarm = ({ isLoggedIn }: { isLoggedIn: boolean }) => {
queryFn: getAlarm,
enabled: isLoggedIn,
staleTime: 1000 * 60 * 5,
select: (data) => data.reverse(),
});
};
10 changes: 7 additions & 3 deletions packages/frontend/src/apis/queries/alarm/usePostCreateAlarm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,13 @@ export const usePostCreateAlarm = () => {
alarmExpiredDate,
}: PostCreateAlarmRequest) =>
postCreateAlarm({ stockId, targetPrice, targetVolume, alarmExpiredDate }),
onSuccess: () =>
onSuccess: () => {
queryClient.invalidateQueries({
queryKey: ['getStockAlarm', 'getAlarm'],
}),
queryKey: ['getStockAlarm'],
});
queryClient.invalidateQueries({
queryKey: ['getAlarm'],
});
},
});
};
5 changes: 3 additions & 2 deletions packages/frontend/src/apis/queries/chat/useGetChatList.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useSuspenseInfiniteQuery } from '@tanstack/react-query';
import { keepPreviousData, useInfiniteQuery } from '@tanstack/react-query';
import { GetChatListRequest } from './schema';
import { get } from '@/apis/utils/get';
import { ChatDataResponse, ChatDataResponseSchema } from '@/sockets/schema';
Expand Down Expand Up @@ -26,7 +26,7 @@ export const useGetChatList = ({
pageSize,
order,
}: GetChatListRequest) => {
return useSuspenseInfiniteQuery({
return useInfiniteQuery({
queryKey: ['chatList', stockId, order],
queryFn: ({ pageParam }) =>
getChatList({
Expand All @@ -47,5 +47,6 @@ export const useGetChatList = ({
pageParams: [...data.pageParams],
}),
staleTime: 1000 * 60 * 3,
placeholderData: keepPreviousData,
});
};
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,10 @@ export const useGetStocksPriceSeries = ({
: undefined,
initialPageParam: { lastStartTime },
select: (data) => ({
priceDtoList: [...data.pages]
.reverse()
.flatMap((page) => page.priceDtoList),
volumeDtoList: [...data.pages]
.reverse()
.flatMap((page) => page.volumeDtoList),
pages: [...data.pages].reverse(),
pageParams: [...data.pageParams].reverse(),
}),
refetchOnWindowFocus: false,
// refetchOnWindowFocus: false,
staleTime: 10 * 1000,
placeholderData: keepPreviousData,
});
Expand Down
4 changes: 1 addition & 3 deletions packages/frontend/src/apis/queries/user/usePatchUserTheme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ export const usePatchUserTheme = () => {
return useMutation({
mutationKey: ['patchTheme'],
mutationFn: ({ theme }: PatchUserThemeRequest) => patchUserTheme({ theme }),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['userTheme'] });
},
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['userTheme'] }),
});
};
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ export const usePostUserNickname = ({ nickname }: { nickname: string }) => {
return useMutation({
mutationKey: ['userNickname'],
mutationFn: () => postUserNickname({ nickname }),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['userInfo'] });
},
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['userInfo'] }),
});
};
1 change: 1 addition & 0 deletions packages/frontend/src/components/lottie/dark-skeleton.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"v":"4.8.0","meta":{"g":"LottieFiles AE ","a":"","k":"","d":"","tc":""},"fr":24,"ip":0,"op":48,"w":650,"h":611,"nm":"Artboard 1","ddd":0,"assets":[{"id":"image_0","w":650,"h":611,"u":"","p":"data:image/png;base64,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","e":1}],"layers":[{"ddd":0,"ind":1,"ty":2,"nm":"Artboard 1.png","cl":"png","refId":"image_0","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":24,"s":[14]},{"t":48,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[325,305.5,0],"ix":2},"a":{"a":0,"k":[325,305.5,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ip":0,"op":48,"st":0,"bm":0}],"markers":[]}
1 change: 1 addition & 0 deletions packages/frontend/src/hooks/useSubscribeAlarm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export const useSubscribeAlarm = () => {
if ('Notification' in window && navigator.serviceWorker) {
try {
if (Notification.permission === 'default') {
alert('알림 허용을 먼저 해주세요.');
const permission = await Notification.requestPermission();
if (permission === 'granted') {
const registration = await navigator.serviceWorker.ready;
Expand Down
16 changes: 10 additions & 6 deletions packages/frontend/src/pages/login/Login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,14 @@ import { Button } from '@/components/ui/button';
const GOOGLE_LOGIN = '/api/auth/google/login';
export const Login = () => {
const queryClient = useQueryClient();
const { refetch } = useGetTestLogin({ password: 'test', username: 'test' });
const { refetch, isSuccess } = useGetTestLogin({
password: 'test',
username: 'test',
});

if (isSuccess) {
queryClient.invalidateQueries({ queryKey: ['loginStatus'] });
}

return (
<div className="flex h-[calc(100vh-8rem)] flex-col items-center justify-center">
Expand All @@ -24,12 +31,9 @@ export const Login = () => {
<span>구글 로그인</span>
</Button>
</Link>
<Link to="/">
<Link to="/" reloadDocument>
<Button
onClick={() => {
refetch();
queryClient.invalidateQueries({ queryKey: ['loginStatus'] });
}}
onClick={() => refetch()}
className="h-10 w-full dark:bg-black"
>
게스트로 로그인
Expand Down
7 changes: 4 additions & 3 deletions packages/frontend/src/pages/stock-detail/AddAlarmForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,16 @@ export const AddAlarmForm = ({ className }: AddAlarmFormProps) => {
endDate: null,
});

const handleSubmit = (event: FormEvent<HTMLFormElement>) => {
const handleSubmit = async (event: FormEvent<HTMLFormElement>) => {
event.preventDefault();

if (!isLoggedIn) {
alert('로그인 후 이용 가능해요.');
return;
}

subscribeAlarm();
await subscribeAlarm();

const { option, value, endDate } = alarmInfo;

const requestData: PostCreateAlarmRequest = {
Expand All @@ -50,7 +51,7 @@ export const AddAlarmForm = ({ className }: AddAlarmFormProps) => {
alarmExpiredDate: endDate,
};

mutate(requestData, {
await mutate(requestData, {
onSuccess: () => {
alert('알림이 등록되었어요!');
setAlarmInfo({
Expand Down
4 changes: 3 additions & 1 deletion packages/frontend/src/pages/stock-detail/ChatPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,9 @@ export const ChatPanel = ({ isOwnerStock }: ChatPanelProps) => {
<div className="border-light-gray display-medium12 text-dark-gray flex items-center justify-between gap-1 border-b-2 pb-2">
<span>{isConnected ? '🟢 접속 중' : '❌ 연결 끊김'}</span>
<div className="flex items-center gap-2" onClick={handleOrderType}>
<p>{order === 'latest' ? '최신순' : '좋아요순'}</p>
<span className="cursor-pointer">
{order === 'latest' ? '최신순' : '좋아요순'}
</span>
<DownArrow
className={cn(
'cursor-pointer',
Expand Down
12 changes: 8 additions & 4 deletions packages/frontend/src/pages/stock-detail/StockDetail.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
import { lazy, Suspense } from 'react';
import { Suspense } from 'react';
import { ErrorBoundary } from 'react-error-boundary';
import { useParams } from 'react-router-dom';
import { StockDetailHeader } from './components';
import { AddAlarmForm, ChatPanel, NotificationPanel, TradingChart } from '.';
import {
AddAlarmForm,
ChatPanel,
NotificationPanel,
TradingChart,
StockMetricsPanel,
} from '.';
import {
useGetOwnership,
useGetStockDetail,
} from '@/apis/queries/stock-detail';
import { Loader } from '@/components/ui/loader';

const StockMetricsPanel = lazy(() => import('./StockMetricsPanel'));

export const StockDetail = () => {
const { stockId = '' } = useParams();

Expand Down
23 changes: 14 additions & 9 deletions packages/frontend/src/pages/stock-detail/StockMetricsPanel.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
import { useEffect, useState } from 'react';
import { useContext, useEffect, useState } from 'react';
import Lottie from 'react-lottie-player';
import { useParams } from 'react-router-dom';
import { MetricItem, Title } from './components';
import darkSkeleton from '@/components/lottie/dark-skeleton.json';
import skeleton from '@/components/lottie/skeleton.json';
import { METRICS_DATA } from '@/constants/metricDetail';
import { ThemeContext } from '@/contexts/theme';
import { socketStock } from '@/sockets/config';
import { useWebsocket } from '@/sockets/useWebsocket';
import { type StockMetricsPanelProps } from '@/types/metrics';
import { cn } from '@/utils/cn';

interface RealTimeStockData {
price: number;
change: number;
volume: number;
}

const StockMetricsPanel = ({
export const StockMetricsPanel = ({
eps,
high52w,
low52w,
Expand All @@ -23,6 +26,7 @@ const StockMetricsPanel = ({
}: Partial<StockMetricsPanelProps>) => {
const { stockId } = useParams();
const { isConnected } = useWebsocket(socketStock);
const { theme } = useContext(ThemeContext);
const [realTimeData, setRealTimeData] = useState<RealTimeStockData>({
price: 0,
change: 0,
Expand Down Expand Up @@ -60,11 +64,14 @@ const StockMetricsPanel = ({
return (
<article className="flex flex-1 flex-col gap-10 rounded-md bg-white p-6 shadow">
{!price || !change || !volume ? (
<section className="grid w-9/12 grid-cols-2 grid-rows-2">
<Lottie animationData={skeleton} play className="w-64" />
<Lottie animationData={skeleton} play className="w-64" />
<Lottie animationData={skeleton} play className="w-64" />
<Lottie animationData={skeleton} play className="w-64" />
<section className="grid w-9/12 lg:grid-cols-2 lg:grid-rows-2">
{Array.from({ length: 4 }, () => (
<Lottie
animationData={theme === 'light' ? skeleton : darkSkeleton}
play
className={cn(theme === 'light' ? 'w-64' : 'w-36')}
/>
))}
</section>
) : (
Object.values(metricsData).map((section) => (
Expand All @@ -86,5 +93,3 @@ const StockMetricsPanel = ({
</article>
);
};

export default StockMetricsPanel;
15 changes: 10 additions & 5 deletions packages/frontend/src/pages/stock-detail/TradingChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,14 @@ export const TradingChart = () => {
timeunit,
});

const { priceDtoList: priceData = [], volumeDtoList: volumeData = [] } =
data || {};
const chart = useChart({ priceData, volumeData, containerRef });
const allPriceData = data?.pages.flatMap((page) => page.priceDtoList) ?? [];
const allVolumeData = data?.pages.flatMap((page) => page.volumeDtoList) ?? [];

const chart = useChart({
priceData: allPriceData,
volumeData: allVolumeData,
containerRef,
});

const fetchGraphData = useCallback(
async (logicalRange: LogicalRange | null) => {
Expand Down Expand Up @@ -56,7 +61,7 @@ export const TradingChart = () => {
useChartResize({ containerRef, chart });

return (
<div className="flex min-h-[35rem] flex-col">
<div className="flex h-[30rem] flex-col xl:h-full">
<section className="flex justify-end gap-5">
{TIME_UNIT.map((option) => (
<RadioButton
Expand All @@ -70,7 +75,7 @@ export const TradingChart = () => {
</RadioButton>
))}
</section>
<div ref={containerRef} className="min-h-0 w-full flex-1" />
<div ref={containerRef} className="h-0 w-full flex-grow" />
</div>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export const StockDetailHeader = ({
const { mutate: postStockUser } = usePostStockUser({
onSuccess: () => {
setUserStatus(UserStatus.OWNERSHIP);
queryClient.invalidateQueries({ queryKey: ['userStock'] });
queryClient.invalidateQueries({ queryKey: ['loginStatus'] });
queryClient.invalidateQueries({ queryKey: ['stockOwnership', stockId] });
},
Expand All @@ -54,6 +55,7 @@ export const StockDetailHeader = ({
const { mutate: deleteStockUser } = useDeleteStockUser({
onSuccess: () => {
setUserStatus(UserStatus.NOT_OWNERSHIP);
queryClient.invalidateQueries({ queryKey: ['userStock'] });
queryClient.invalidateQueries({ queryKey: ['loginStatus'] });
queryClient.invalidateQueries({ queryKey: ['stockOwnership', stockId] });
},
Expand Down
11 changes: 7 additions & 4 deletions packages/frontend/src/pages/stocks/StockRankingTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,17 @@ const StockRankingTable = () => {
<tr className="display-medium12 text-dark-gray border-light-gray border-b text-left [&>*]:p-4 [&>*]:py-3">
<th>종목</th>
<th className="text-right">현재가</th>
<th className="flex items-center justify-end gap-1 text-right">
<p>등락률({sortType === 'increase' ? '상승순' : '하락순'})</p>
<th
className="flex cursor-pointer items-center justify-end gap-1 text-right"
onClick={handleSortType}
>
<span>
등락률({sortType === 'increase' ? '상승순' : '하락순'})
</span>
<DownArrow
className={cn(
'cursor-pointer',
sortType === 'increase' ? 'rotate-0' : 'rotate-180',
)}
onClick={handleSortType}
/>
</th>
<th className="hidden lg:table-cell lg:text-right">거래대금</th>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@ export const StockIndexCard = ({
<div className="text-gray flex flex-col gap-3 xl:grid xl:grid-cols-2 xl:grid-rows-2 [&_div]:flex [&_div]:gap-4">
<div>
<span className="display-bold14">시가</span>
<span className="display-medium14">{open?.toLocaleString()}</span>
<span className="display-medium14">{open?.toLocaleString()}</span>
</div>
<div>
<span className="display-bold14">고가</span>
<span className="display-medium14">{high?.toLocaleString()}</span>
<span className="display-medium14">{high?.toLocaleString()}</span>
</div>
<div>
<span className="display-bold14">저가</span>
<span className="display-medium14">{low?.toLocaleString()}</span>
<span className="display-medium14">{low?.toLocaleString()}</span>
</div>
</div>
</div>
Expand Down

0 comments on commit 366abf8

Please sign in to comment.