diff --git a/frontend/.storybook/preview.tsx b/frontend/.storybook/preview.tsx
index 475fb7753..0bf11a65e 100644
--- a/frontend/.storybook/preview.tsx
+++ b/frontend/.storybook/preview.tsx
@@ -2,6 +2,10 @@ import type { Preview } from '@storybook/react';
import React from 'react';
import { MemoryRouter } from 'react-router-dom';
import GlobalStyles from '../src/style/GlobalStyles';
+import { AuthProvider, ToastProvider } from '../src/contexts';
+import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
+
+const queryClient = new QueryClient();
const preview: Preview = {
parameters: {
@@ -15,19 +19,16 @@ const preview: Preview = {
},
decorators: [
(Story) => (
- <>
-
-
-
-
- >
+
+
+
+
),
],
};
diff --git a/frontend/jest.config.ts b/frontend/jest.config.ts
index 1bf28965d..8ee304dd4 100644
--- a/frontend/jest.config.ts
+++ b/frontend/jest.config.ts
@@ -11,12 +11,13 @@ const config: Config = {
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json'],
transform: {
'^.+\\.tsx?$': 'ts-jest',
+ '\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
+ '/src/mocks/fileTransformer.js',
},
clearMocks: true,
moduleNameMapper: {
'^@/(.*)$': '/src/$1',
'\\.(css|less|scss|sass)$': 'identity-obj-proxy',
- '\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2)$': '/src/mocks/fileMock.js',
'react-syntax-highlighter/dist/esm': 'react-syntax-highlighter/dist/cjs',
},
transformIgnorePatterns: ['/node_modules/(?!react-syntax-highlighter)'],
diff --git a/frontend/package.json b/frontend/package.json
index 36c5c9d97..01053a986 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -1,6 +1,6 @@
{
"name": "code-zap",
- "version": "1.1.6",
+ "version": "1.1.7",
"description": "",
"main": "index.js",
"scripts": {
diff --git a/frontend/public/mockServiceWorker.js b/frontend/public/mockServiceWorker.js
index 15751fa19..ecabdda5d 100644
--- a/frontend/public/mockServiceWorker.js
+++ b/frontend/public/mockServiceWorker.js
@@ -8,8 +8,8 @@
* - Please do NOT serve this file on production.
*/
-const PACKAGE_VERSION = '2.3.5'
-const INTEGRITY_CHECKSUM = '26357c79639bfa20d64c0efca2a87423'
+const PACKAGE_VERSION = '2.5.2'
+const INTEGRITY_CHECKSUM = '07a8241b182f8a246a7cd39894799a9e'
const IS_MOCKED_RESPONSE = Symbol('isMockedResponse')
const activeClientIds = new Set()
@@ -62,7 +62,12 @@ self.addEventListener('message', async function (event) {
sendToClient(client, {
type: 'MOCKING_ENABLED',
- payload: true,
+ payload: {
+ client: {
+ id: client.id,
+ frameType: client.frameType,
+ },
+ },
})
break
}
@@ -155,6 +160,10 @@ async function handleRequest(event, requestId) {
async function resolveMainClient(event) {
const client = await self.clients.get(event.clientId)
+ if (activeClientIds.has(event.clientId)) {
+ return client
+ }
+
if (client?.frameType === 'top-level') {
return client
}
diff --git a/frontend/src/api/ApiClient.ts b/frontend/src/api/ApiClient.ts
index 9edcd031b..5a15edfdf 100644
--- a/frontend/src/api/ApiClient.ts
+++ b/frontend/src/api/ApiClient.ts
@@ -96,7 +96,7 @@ class ApiClient {
}
}
-const API_URL = process.env.REACT_APP_API_URL ?? '';
+const API_URL = process.env.REACT_APP_API_URL || 'https://default-url.com';
const httpHeader = {
'Content-Type': 'application/json',
diff --git a/frontend/src/api/authentication.ts b/frontend/src/api/authentication.ts
index 9250e63bc..a2397fac4 100644
--- a/frontend/src/api/authentication.ts
+++ b/frontend/src/api/authentication.ts
@@ -5,7 +5,7 @@ import { MemberInfo } from '@/types';
import { apiClient } from './ApiClient';
import { customFetch } from './customFetch';
-const API_URL = process.env.REACT_APP_API_URL ?? '';
+const API_URL = process.env.REACT_APP_API_URL || 'https://default-url.com';
export const SIGNUP_API_URL = `${API_URL}${END_POINTS.SIGNUP}`;
export const LOGIN_API_URL = `${API_URL}${END_POINTS.LOGIN}`;
diff --git a/frontend/src/api/categories.ts b/frontend/src/api/categories.ts
index 83956dd0d..8294f3876 100644
--- a/frontend/src/api/categories.ts
+++ b/frontend/src/api/categories.ts
@@ -12,7 +12,7 @@ import type {
import { customFetch } from './customFetch';
-const API_URL = process.env.REACT_APP_API_URL ?? '';
+const API_URL = process.env.REACT_APP_API_URL || 'https://default-url.com';
export const CATEGORY_API_URL = `${API_URL}${END_POINTS.CATEGORIES}`;
diff --git a/frontend/src/api/like.ts b/frontend/src/api/like.ts
index 95e1d0270..86ae1c466 100644
--- a/frontend/src/api/like.ts
+++ b/frontend/src/api/like.ts
@@ -5,7 +5,7 @@ import { LikeDeleteRequest, LikePostRequest } from '@/types';
import { customFetch } from './customFetch';
-const API_URL = process.env.REACT_APP_API_URL ?? '';
+const API_URL = process.env.REACT_APP_API_URL || 'https://default-url.com';
export const LIKE_API_URL = `${API_URL}${END_POINTS.LIKES}`;
diff --git a/frontend/src/api/members.ts b/frontend/src/api/members.ts
index 783f98dec..8330e4e19 100644
--- a/frontend/src/api/members.ts
+++ b/frontend/src/api/members.ts
@@ -3,7 +3,7 @@ import { GetMemberNameResponse } from '@/types';
import { customFetch } from './customFetch';
-const API_URL = process.env.REACT_APP_API_URL;
+const API_URL = process.env.REACT_APP_API_URL || 'https://default-url.com';
export const MEMBER_API_URL = `${API_URL}${END_POINTS.MEMBERS}`;
diff --git a/frontend/src/api/tags.ts b/frontend/src/api/tags.ts
index 28d9921f6..19ea86616 100644
--- a/frontend/src/api/tags.ts
+++ b/frontend/src/api/tags.ts
@@ -3,7 +3,7 @@ import { TagListResponse } from '@/types/api';
import { customFetch } from './customFetch';
-const API_URL = process.env.REACT_APP_API_URL ?? '';
+const API_URL = process.env.REACT_APP_API_URL || 'https://default-url.com';
export const TAG_API_URL = `${API_URL}${END_POINTS.TAGS}`;
diff --git a/frontend/src/api/templates.ts b/frontend/src/api/templates.ts
index 87f740ea8..a9c007fa4 100644
--- a/frontend/src/api/templates.ts
+++ b/frontend/src/api/templates.ts
@@ -12,7 +12,7 @@ import { SortingOption } from '@/types';
import { apiClient } from './ApiClient';
import { customFetch } from './customFetch';
-const API_URL = process.env.REACT_APP_API_URL ?? '';
+const API_URL = process.env.REACT_APP_API_URL || 'https://default-url.com';
export const TEMPLATE_API_URL = `${API_URL}${END_POINTS.TEMPLATES_EXPLORE}`;
diff --git a/frontend/src/components/PagingButtons/PagingButtons.stories.tsx b/frontend/src/components/PagingButtons/PagingButtons.stories.tsx
index 3001a6147..2e290738d 100644
--- a/frontend/src/components/PagingButtons/PagingButtons.stories.tsx
+++ b/frontend/src/components/PagingButtons/PagingButtons.stories.tsx
@@ -6,7 +6,7 @@ const meta: Meta = {
title: 'PagingButtons',
component: PagingButtons,
args: {
- totalPages: 6,
+ paginationSizes: 5,
onPageChange: () => {},
},
};
diff --git a/frontend/src/components/PagingButtons/PagingButtons.tsx b/frontend/src/components/PagingButtons/PagingButtons.tsx
index 7584a7ebb..6ef473830 100644
--- a/frontend/src/components/PagingButtons/PagingButtons.tsx
+++ b/frontend/src/components/PagingButtons/PagingButtons.tsx
@@ -6,28 +6,26 @@ import * as S from './PagingButtons.style';
interface Props {
currentPage: number;
- totalPages: number;
+ paginationSizes: number;
onPageChange: (page: number) => void;
}
-const PagingButtons = ({ currentPage, totalPages, onPageChange }: Props) => {
+const PagingButtons = ({ currentPage, paginationSizes, onPageChange }: Props) => {
const getPageNumbers = () => {
- const startPage = Math.max(1, Math.min(currentPage - 2, totalPages - 4));
- const endPage = Math.min(totalPages, startPage + 4);
+ const startPage = Math.max(1, Math.min(currentPage - 2, currentPage + paginationSizes - 5));
+ const endPage = Math.min(currentPage + paginationSizes - 1, startPage + 4);
return Array.from({ length: endPage - startPage + 1 }, (_, i) => startPage + i);
};
const handlePagingClick = (page: number, label: string) => {
- trackMyTemplatePaging({ page, totalPages, label });
+ trackMyTemplatePaging({ page, label });
onPageChange(page);
};
return (
-
-
{getPageNumbers().map((page) => (
{
label={String(page)}
/>
))}
-
-
-
+
);
};
@@ -59,7 +50,9 @@ interface PagingButtonProps {
const PagingButton = ({ page, isActive, disabled, onClick, label }: PagingButtonProps) => (
onClick(page ?? 1, label)}>
- {label}
+ {!disabled && (
+ {label}
+ )}
);
diff --git a/frontend/src/components/SelectList/SelectList.style.ts b/frontend/src/components/SelectList/SelectList.style.ts
index 5ce32eb8b..5cc4fb1f1 100644
--- a/frontend/src/components/SelectList/SelectList.style.ts
+++ b/frontend/src/components/SelectList/SelectList.style.ts
@@ -1,6 +1,7 @@
import styled from '@emotion/styled';
import { theme } from '@/style/theme';
+
import type { OptionProps } from './SelectList';
export const SelectListContainer = styled.div`
diff --git a/frontend/src/components/SelectList/SelectList.tsx b/frontend/src/components/SelectList/SelectList.tsx
index 5c4c23568..19af20f64 100644
--- a/frontend/src/components/SelectList/SelectList.tsx
+++ b/frontend/src/components/SelectList/SelectList.tsx
@@ -1,7 +1,7 @@
-import { useTheme } from '@emotion/react';
import { PropsWithChildren } from 'react';
import { Text } from '@/components';
+import { theme } from '@/style/theme';
import * as S from './SelectList.style';
@@ -12,19 +12,15 @@ export interface OptionProps {
const SelectListBase = ({ children }: PropsWithChildren) => {children};
-const SelectListOption = ({ children, isSelected, onClick }: PropsWithChildren) => {
- const theme = useTheme();
-
- return (
-
-
-
- {children}
-
-
-
- );
-};
+const SelectListOption = ({ children, isSelected, onClick }: PropsWithChildren) => (
+
+
+
+ {children}
+
+
+
+);
const SelectList = Object.assign(SelectListBase, {
Option: SelectListOption,
diff --git a/frontend/src/components/SourceCode/SourceCode.tsx b/frontend/src/components/SourceCode/SourceCode.tsx
index b00b75fe4..b6d7b8ae4 100644
--- a/frontend/src/components/SourceCode/SourceCode.tsx
+++ b/frontend/src/components/SourceCode/SourceCode.tsx
@@ -1,7 +1,6 @@
-import { ViewUpdate } from '@codemirror/view';
import { type LanguageName, loadLanguage } from '@uiw/codemirror-extensions-langs';
import { quietlight } from '@uiw/codemirror-theme-quietlight';
-import ReactCodeMirror, { EditorView, ReactCodeMirrorRef } from '@uiw/react-codemirror';
+import ReactCodeMirror, { EditorView, ReactCodeMirrorRef, type ViewUpdate } from '@uiw/react-codemirror';
import { useRef } from 'react';
import { useWindowWidth } from '@/hooks';
diff --git a/frontend/src/components/SourceCodeEditor/SourceCodeEditor.tsx b/frontend/src/components/SourceCodeEditor/SourceCodeEditor.tsx
index 0f0e61348..d192f325b 100644
--- a/frontend/src/components/SourceCodeEditor/SourceCodeEditor.tsx
+++ b/frontend/src/components/SourceCodeEditor/SourceCodeEditor.tsx
@@ -1,4 +1,4 @@
-import { ViewUpdate } from '@codemirror/view';
+import { type ViewUpdate } from '@uiw/react-codemirror';
import { useRef } from 'react';
import { TrashcanIcon } from '@/assets/images';
diff --git a/frontend/src/components/SourceCodeViewer/SourceCodeViewer.style.ts b/frontend/src/components/SourceCodeViewer/SourceCodeViewer.style.ts
index ec3ecb365..a1d2a55c5 100644
--- a/frontend/src/components/SourceCodeViewer/SourceCodeViewer.style.ts
+++ b/frontend/src/components/SourceCodeViewer/SourceCodeViewer.style.ts
@@ -1,6 +1,7 @@
import styled from '@emotion/styled';
import { Button } from '@/components';
+import { theme } from '@/style/theme';
export const SourceCodeViewerContainer = styled.div`
overflow: hidden;
@@ -17,7 +18,7 @@ export const FilenameContainer = styled.div`
height: 3rem;
padding: 1rem 1.5rem;
- background: ${({ theme }) => theme.color.light.tertiary_600};
+ background: ${theme.color.light.tertiary_600};
`;
export const ToggleButton = styled.button`
diff --git a/frontend/src/components/Toast/Toast.style.ts b/frontend/src/components/Toast/Toast.style.ts
index 9d8bef67c..3818a73ea 100644
--- a/frontend/src/components/Toast/Toast.style.ts
+++ b/frontend/src/components/Toast/Toast.style.ts
@@ -1,6 +1,8 @@
import { keyframes } from '@emotion/react';
import styled from '@emotion/styled';
+import { theme } from '@/style/theme';
+
const slideIn = keyframes`
from {
transform: translateY(20px) translateX(-50%);
@@ -37,7 +39,7 @@ export const BaseToast = styled.div<{ visible: boolean; type: 'success' | 'fail'
font-size: 16px;
color: white;
- background-color: ${({ theme, type }) => {
+ background-color: ${({ type }) => {
switch (type) {
case 'success':
return theme.color.light.complementary_300;
diff --git a/frontend/src/hooks/template/index.ts b/frontend/src/hooks/template/index.ts
index 56cdbcf6e..d071d71ba 100644
--- a/frontend/src/hooks/template/index.ts
+++ b/frontend/src/hooks/template/index.ts
@@ -1,3 +1,2 @@
export { useSourceCode } from './useSourceCode';
export { useTag } from './useTag';
-export { useSearchKeyword } from './useSearchKeyword';
diff --git a/frontend/src/hooks/template/useSearchKeyword.ts b/frontend/src/hooks/template/useSearchKeyword.ts
deleted file mode 100644
index ff82815d2..000000000
--- a/frontend/src/hooks/template/useSearchKeyword.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import { useInput, useDebounce } from '..';
-
-export const useSearchKeyword = (initKeyword: string = '') => {
- const [keyword, handleKeywordChange] = useInput(initKeyword);
- const debouncedKeyword = useDebounce(keyword, 300);
-
- return { keyword, debouncedKeyword, handleKeywordChange };
-};
diff --git a/frontend/src/mocks/fileTransformer.js b/frontend/src/mocks/fileTransformer.js
new file mode 100644
index 000000000..3ea1ef262
--- /dev/null
+++ b/frontend/src/mocks/fileTransformer.js
@@ -0,0 +1,9 @@
+const path = require('path');
+
+module.exports = {
+ process(sourceText, sourcePath, options) {
+ return {
+ code: `module.exports = ${JSON.stringify(path.basename(sourcePath))};`,
+ };
+ },
+};
diff --git a/frontend/src/mocks/handlers.ts b/frontend/src/mocks/handlers.ts
index 32bfe2bf8..57e62978e 100644
--- a/frontend/src/mocks/handlers.ts
+++ b/frontend/src/mocks/handlers.ts
@@ -61,8 +61,7 @@ export const templateHandlers = [
break;
}
- const totalElements = filteredTemplates.length;
- const totalPages = Math.ceil(totalElements / size);
+ const paginationSizes = Math.min(Math.ceil(filteredTemplates.length / size - page + 1), 5);
const startIndex = (page - 1) * size;
const endIndex = startIndex + size;
const paginatedTemplates = filteredTemplates.slice(startIndex, endIndex);
@@ -71,8 +70,7 @@ export const templateHandlers = [
return HttpResponse.json({
status: 200,
templates: paginatedTemplates,
- totalPages,
- totalElements,
+ paginationSizes,
numberOfElements,
});
}),
diff --git a/frontend/src/pages/LoginPage/LoginPage.tsx b/frontend/src/pages/LoginPage/LoginPage.tsx
index 123faedb3..11c8321b4 100644
--- a/frontend/src/pages/LoginPage/LoginPage.tsx
+++ b/frontend/src/pages/LoginPage/LoginPage.tsx
@@ -8,6 +8,7 @@ import { useTrackPageViewed } from '@/service/amplitude';
import { useLoginForm } from './hooks';
import * as S from './LoginPage.style';
+import { theme } from '@/style/theme';
const LoginPage = () => {
useTrackPageViewed({ eventName: '[Viewed] 로그인 페이지' });
@@ -21,7 +22,7 @@ const LoginPage = () => {
- 환영하잽
+ 환영하잽
{
로그인
- 계정이 없으신가요?
+ 계정이 없으신가요?
- 이미 계정이 있으신가요?
+ 이미 계정이 있으신가요?