diff --git a/.eslintrc.json b/.eslintrc.json
index bdd27ad..646a272 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -23,6 +23,7 @@
"import/order": "off",
"no-console": "off",
"react/function-component-definition": "off",
- "arrow-body-style": "off"
+ "arrow-body-style": "off",
+ "jsx-a11y/no-autofocus": "off"
}
}
diff --git a/next.config.js b/next.config.js
index 3f3be5d..5e98ec0 100644
--- a/next.config.js
+++ b/next.config.js
@@ -1,8 +1,12 @@
-const { createVanillaExtractPlugin } = require("@vanilla-extract/next-plugin");
+const { createVanillaExtractPlugin } = require('@vanilla-extract/next-plugin');
const withVanillaExtract = createVanillaExtractPlugin();
/** @type {import('next').NextConfig} */
-const nextConfig = {};
+const nextConfig = {
+ compiler: {
+ removeConsole: process.env.NODE_ENV === 'production',
+ },
+};
module.exports = withVanillaExtract(nextConfig);
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index ca878f8..f3108d5 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -1,5 +1,5 @@
-import ThemeProvider from '@/providers/ThemeProvider/ThemeProvider';
-import '../styles/globalStyles.css.ts';
+import ThemeProvider from '@/commons/providers/ThemeProvider/ThemeProvider.tsx';
+import '../commons/styles/globalStyles.css.ts';
import { Metadata } from 'next';
export const metadata: Metadata = {
diff --git a/src/app/page.tsx b/src/app/page.tsx
index cb0592a..98618df 100755
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -1,8 +1,8 @@
-import RemoteControl from '@/components/features/Common/RemoteControl/RemoteControl';
-import Card from '@/components/features/Items/Card/Card';
-import Header from '@/components/widgets/Header/Header';
-import SearchToolbar from '@/components/widgets/SearchToolbar/SearchToolbar';
-import * as styles from '@/styles/rootStyles.css';
+import RemoteControl from '@/commons/components/features/Common/RemoteControl/RemoteControl';
+import Card from '@/commons/components/features/Items/Card/Card';
+import Header from '@/commons/components/widgets/Header/Header';
+import SearchToolbar from '@/commons/components/widgets/SearchToolbar/SearchToolbar';
+import * as styles from '@/commons/styles/rootStyles.css';
export default function RootPage() {
return (
diff --git a/src/components/atoms/Icons/ArrowUp/ArrowUp.tsx b/src/commons/components/atoms/Icons/ArrowUp/ArrowUp.tsx
similarity index 100%
rename from src/components/atoms/Icons/ArrowUp/ArrowUp.tsx
rename to src/commons/components/atoms/Icons/ArrowUp/ArrowUp.tsx
diff --git a/src/components/atoms/Icons/MagnifyingGlass/MagnifyingGlass.tsx b/src/commons/components/atoms/Icons/MagnifyingGlass/MagnifyingGlass.tsx
similarity index 100%
rename from src/components/atoms/Icons/MagnifyingGlass/MagnifyingGlass.tsx
rename to src/commons/components/atoms/Icons/MagnifyingGlass/MagnifyingGlass.tsx
diff --git a/src/components/atoms/Icons/Moon/Moon.tsx b/src/commons/components/atoms/Icons/Moon/Moon.tsx
similarity index 100%
rename from src/components/atoms/Icons/Moon/Moon.tsx
rename to src/commons/components/atoms/Icons/Moon/Moon.tsx
diff --git a/src/components/atoms/Icons/Sun/Sun.tsx b/src/commons/components/atoms/Icons/Sun/Sun.tsx
similarity index 100%
rename from src/components/atoms/Icons/Sun/Sun.tsx
rename to src/commons/components/atoms/Icons/Sun/Sun.tsx
diff --git a/src/components/atoms/Icons/Tag/Tag.tsx b/src/commons/components/atoms/Icons/Tag/Tag.tsx
similarity index 100%
rename from src/components/atoms/Icons/Tag/Tag.tsx
rename to src/commons/components/atoms/Icons/Tag/Tag.tsx
diff --git a/src/commons/components/atoms/boxes/tagBox/tagBox.css.ts b/src/commons/components/atoms/boxes/tagBox/tagBox.css.ts
new file mode 100644
index 0000000..9f5ded6
--- /dev/null
+++ b/src/commons/components/atoms/boxes/tagBox/tagBox.css.ts
@@ -0,0 +1,9 @@
+import { style } from '@vanilla-extract/css';
+
+export const tagBox = style({
+ padding: '8px 10px',
+ borderRadius: '50px',
+ backgroundColor: '#6A6868',
+
+ fontSize: '12px',
+});
diff --git a/src/commons/components/atoms/boxes/tagBox/tagBox.tsx b/src/commons/components/atoms/boxes/tagBox/tagBox.tsx
new file mode 100644
index 0000000..a0b2369
--- /dev/null
+++ b/src/commons/components/atoms/boxes/tagBox/tagBox.tsx
@@ -0,0 +1,5 @@
+import * as styles from './tagBox.css';
+
+export function TagBox({ tagName }: { tagName: string }) {
+ return
{tagName}
;
+}
diff --git a/src/components/features/Common/RemoteControl/RemoteControl.css.ts b/src/commons/components/features/Common/RemoteControl/RemoteControl.css.ts
similarity index 100%
rename from src/components/features/Common/RemoteControl/RemoteControl.css.ts
rename to src/commons/components/features/Common/RemoteControl/RemoteControl.css.ts
diff --git a/src/components/features/Common/RemoteControl/RemoteControl.tsx b/src/commons/components/features/Common/RemoteControl/RemoteControl.tsx
similarity index 72%
rename from src/components/features/Common/RemoteControl/RemoteControl.tsx
rename to src/commons/components/features/Common/RemoteControl/RemoteControl.tsx
index c7473fb..603384c 100644
--- a/src/components/features/Common/RemoteControl/RemoteControl.tsx
+++ b/src/commons/components/features/Common/RemoteControl/RemoteControl.tsx
@@ -1,7 +1,7 @@
'use client';
-import ArrowUp from '@/components/atoms/Icons/ArrowUp/ArrowUp';
-import { scrollToTop } from '@/utils/ui/scrollToTop/scrollToTop';
+import ArrowUp from '@/commons/components/atoms/Icons/ArrowUp/ArrowUp';
+import { scrollToTop } from '@/commons/utils/ui/scrollToTop/scrollToTop';
import * as styles from './RemoteControl.css';
export default function RemoteControl() {
diff --git a/src/components/features/Common/Slider/Slider.css.ts b/src/commons/components/features/Common/Slider/Slider.css.ts
similarity index 94%
rename from src/components/features/Common/Slider/Slider.css.ts
rename to src/commons/components/features/Common/Slider/Slider.css.ts
index f00ce2a..128ed88 100644
--- a/src/components/features/Common/Slider/Slider.css.ts
+++ b/src/commons/components/features/Common/Slider/Slider.css.ts
@@ -1,4 +1,4 @@
-import { vars } from '@/styles/globalStyles.css';
+import { vars } from '@/commons/styles/globalStyles.css';
import { keyframes, style } from '@vanilla-extract/css';
export const wrapper = style({
diff --git a/src/components/features/Common/Slider/Slider.tsx b/src/commons/components/features/Common/Slider/Slider.tsx
similarity index 100%
rename from src/components/features/Common/Slider/Slider.tsx
rename to src/commons/components/features/Common/Slider/Slider.tsx
diff --git a/src/components/features/Common/ThemeIcon/ThemeIcon.tsx b/src/commons/components/features/Common/ThemeIcon/ThemeIcon.tsx
similarity index 67%
rename from src/components/features/Common/ThemeIcon/ThemeIcon.tsx
rename to src/commons/components/features/Common/ThemeIcon/ThemeIcon.tsx
index 43b682c..a52f30e 100644
--- a/src/components/features/Common/ThemeIcon/ThemeIcon.tsx
+++ b/src/commons/components/features/Common/ThemeIcon/ThemeIcon.tsx
@@ -1,6 +1,6 @@
-import Moon from '@/components/atoms/Icons/Moon/Moon';
-import Sun from '@/components/atoms/Icons/Sun/Sun';
-import { Theme } from '@/types/theme';
+import Moon from '@/commons/components/atoms/Icons/Moon/Moon';
+import Sun from '@/commons/components/atoms/Icons/Sun/Sun';
+import { Theme } from '@/commons/types/theme';
import { ThemeIconProps } from './ThemeIcon.types';
export default function ThemeIcon({ setTheme, resolvedTheme }: ThemeIconProps) {
diff --git a/src/components/features/Common/ThemeIcon/ThemeIcon.types.ts b/src/commons/components/features/Common/ThemeIcon/ThemeIcon.types.ts
similarity index 100%
rename from src/components/features/Common/ThemeIcon/ThemeIcon.types.ts
rename to src/commons/components/features/Common/ThemeIcon/ThemeIcon.types.ts
diff --git a/src/commons/components/features/Inputs/CollapsedSearch/CollapsedSearch.css.ts b/src/commons/components/features/Inputs/CollapsedSearch/CollapsedSearch.css.ts
new file mode 100644
index 0000000..c6a4ebd
--- /dev/null
+++ b/src/commons/components/features/Inputs/CollapsedSearch/CollapsedSearch.css.ts
@@ -0,0 +1,8 @@
+import { style } from '@vanilla-extract/css';
+
+export const collapsedSearchWrapper = style({
+ display: 'flex',
+ flexDirection: 'row',
+
+ marginRight: 'auto',
+});
diff --git a/src/commons/components/features/Inputs/CollapsedSearch/CollapsedSearch.tsx b/src/commons/components/features/Inputs/CollapsedSearch/CollapsedSearch.tsx
new file mode 100644
index 0000000..74958df
--- /dev/null
+++ b/src/commons/components/features/Inputs/CollapsedSearch/CollapsedSearch.tsx
@@ -0,0 +1,27 @@
+import { collapsedSearchWrapper } from './CollapsedSearch.css';
+import { KeyboardEvent } from 'react';
+import Image from 'next/image';
+import { TagList } from '../../Lists/TagList/TagList';
+
+export const CollapsedSearch = ({
+ tagList,
+ handleKeyDown,
+}: {
+ tagList: string[];
+ handleKeyDown: (event: KeyboardEvent) => void;
+}) => {
+ return (
+ <>
+
+
+
+
+ >
+ );
+};
diff --git a/src/commons/components/features/Inputs/ExpandedSearch/ExpandedSearch.css.ts b/src/commons/components/features/Inputs/ExpandedSearch/ExpandedSearch.css.ts
new file mode 100644
index 0000000..c479ad4
--- /dev/null
+++ b/src/commons/components/features/Inputs/ExpandedSearch/ExpandedSearch.css.ts
@@ -0,0 +1,140 @@
+import { style } from '@vanilla-extract/css';
+
+export const wrapper = style({
+ position: 'relative',
+
+ display: 'flex',
+ flexDirection: 'row',
+ backgroundColor: '#fff',
+
+ width: '27rem',
+ height: '3rem',
+ padding: '10px 20px',
+ borderRadius: '50px',
+
+ cursor: 'pointer',
+});
+
+export const glassesWrapper = style({
+ display: 'flex',
+ flexDirection: 'row',
+});
+
+export const tagWrapper = style({
+ display: 'flex',
+ flexDirection: 'row',
+
+ marginRight: 'auto',
+});
+
+export const tagBox = style({
+ padding: '6px',
+ borderRadius: '50px',
+ backgroundColor: '#6A6868',
+
+ fontSize: '12px',
+
+ marginRight: '10px',
+});
+
+export const OutExpandedWrapper = style({
+ position: 'fixed',
+ top: '0',
+ left: '0',
+ right: '0',
+ bottom: '0',
+
+ display: 'flex',
+ justifyContent: 'center',
+
+ width: '100vw', // 100%에서 100vw로 변경
+ height: '100vh', // 100%에서 100vh로 변경
+
+ padding: '80px 54px',
+
+ zIndex: '1000',
+ backgroundColor: 'rgba(0, 0, 0, 0.65)', // 반투명 검은색으로 변경
+});
+
+export const expandedWrapper = style({
+ position: 'absolute',
+ top: '0',
+ left: '0',
+ right: '0',
+ bottom: '0',
+
+ display: 'flex',
+ flexDirection: 'column',
+
+ width: '37rem',
+ height: '22rem',
+
+ backgroundColor: '#fff',
+
+ borderRadius: '25px',
+ padding: '20px',
+
+ zIndex: '2000',
+});
+
+export const searchInput = style({
+ width: '100%',
+ height: '16px',
+
+ marginBottom: '14px',
+
+ backgroundColor: 'transparent',
+ color: '#000',
+
+ fontSize: '14px',
+
+ border: 'none',
+ outline: 'none',
+});
+
+export const expandedTagWrapper = style({
+ display: 'flex',
+ flexDirection: 'row',
+ flexWrap: 'wrap',
+
+ fontSize: '12px',
+});
+
+export const relatedTagWrapper = style({
+ display: 'flex',
+ flexDirection: 'column',
+
+ margin: '0',
+ padding: '0',
+});
+
+export const relatedTagBox = style({
+ display: 'flex',
+ flexDirection: 'row',
+ alignItems: 'center',
+
+ width: '100%',
+
+ gap: '10px',
+
+ cursor: 'pointer',
+
+ ':focus': {
+ outline: 'none',
+ backgroundColor: 'rgba(106, 104, 104, 0.1)',
+ },
+
+ ':hover': {
+ backgroundColor: 'rgba(106, 104, 104, 0.1)',
+ },
+});
+
+export const relatedTagText = style({
+ fontSize: '12px',
+
+ color: '#000',
+});
+
+export const focusedTag = style({
+ backgroundColor: 'rgba(106, 104, 104, 0.1)',
+});
diff --git a/src/commons/components/features/Inputs/ExpandedSearch/ExpandedSearch.tsx b/src/commons/components/features/Inputs/ExpandedSearch/ExpandedSearch.tsx
new file mode 100644
index 0000000..9cf5e42
--- /dev/null
+++ b/src/commons/components/features/Inputs/ExpandedSearch/ExpandedSearch.tsx
@@ -0,0 +1,54 @@
+import { TagType } from '@/domains/tag/tpyes/tag.type';
+import { RelatedTags } from '../../Lists/RelatedTags/RelatedTags';
+import { TagList } from '../../Lists/TagList/TagList';
+import * as styles from './ExpandedSearch.css';
+import { KeyboardEvent } from 'react';
+
+export const ExpandedSearch = ({
+ inputValue,
+ setInputValue,
+ handleKeyDown,
+ tagList,
+ relatedTags,
+ focusedIndex,
+ onClickRelatedTag,
+ onClickExpanded,
+}: {
+ inputValue: string;
+ setInputValue: (value: string) => void;
+ handleKeyDown: (event: KeyboardEvent) => void;
+ tagList: string[];
+ relatedTags: TagType[];
+ focusedIndex: number;
+ onClickRelatedTag: (tag: TagType) => void;
+ onClickExpanded: () => void;
+}) => {
+ return (
+ <>
+
+ setInputValue(e.target.value)}
+ onKeyDown={handleKeyDown}
+ autoFocus
+ />
+
+
+
+
+
+
+
+ >
+ );
+};
diff --git a/src/components/features/Inputs/Search/Search.css.ts b/src/commons/components/features/Inputs/Search/Search.css.ts
similarity index 88%
rename from src/components/features/Inputs/Search/Search.css.ts
rename to src/commons/components/features/Inputs/Search/Search.css.ts
index d49c8a1..c479ad4 100644
--- a/src/components/features/Inputs/Search/Search.css.ts
+++ b/src/commons/components/features/Inputs/Search/Search.css.ts
@@ -116,6 +116,17 @@ export const relatedTagBox = style({
width: '100%',
gap: '10px',
+
+ cursor: 'pointer',
+
+ ':focus': {
+ outline: 'none',
+ backgroundColor: 'rgba(106, 104, 104, 0.1)',
+ },
+
+ ':hover': {
+ backgroundColor: 'rgba(106, 104, 104, 0.1)',
+ },
});
export const relatedTagText = style({
@@ -123,3 +134,7 @@ export const relatedTagText = style({
color: '#000',
});
+
+export const focusedTag = style({
+ backgroundColor: 'rgba(106, 104, 104, 0.1)',
+});
diff --git a/src/commons/components/features/Inputs/Search/Search.tsx b/src/commons/components/features/Inputs/Search/Search.tsx
new file mode 100644
index 0000000..c5ed84d
--- /dev/null
+++ b/src/commons/components/features/Inputs/Search/Search.tsx
@@ -0,0 +1,124 @@
+'use client';
+
+import { KeyboardEvent, useEffect, useState } from 'react';
+import * as styles from './Search.css';
+import { getTags } from '@/domains/tag/api/tags.api';
+import type { TagType } from '@/domains/tag/tpyes/tag.type';
+import { CollapsedSearch } from '../CollapsedSearch/CollapsedSearch';
+import { ExpandedSearch } from '../ExpandedSearch/ExpandedSearch';
+
+export default function Search() {
+ const [isExpanded, setIsExpanded] = useState(false);
+ const [tagList, setTagList] = useState([]);
+ const [inputValue, setInputValue] = useState('');
+ const [relatedTags, setRelatedTags] = useState([]);
+ const [focusedIndex, setFocusedIndex] = useState(-1);
+
+ useEffect(() => {
+ const searchTags = async () => {
+ if (inputValue.trim().length > 0) {
+ try {
+ const response = await getTags(inputValue);
+ setRelatedTags(response.tags);
+ } catch (error) {
+ console.error('태그 검색 실패:', error);
+ setRelatedTags([]);
+ }
+ } else {
+ setRelatedTags([]);
+ }
+ };
+
+ const timer = setTimeout(searchTags, 300);
+ return () => clearTimeout(timer);
+ }, [inputValue]);
+
+ const handleKeyDown = (event: KeyboardEvent) => {
+ if (event.nativeEvent.isComposing || event.keyCode === 229) return;
+
+ if (event.key === 'ArrowDown') {
+ event.preventDefault();
+ setFocusedIndex((prev) => {
+ if (prev === -1) return 0;
+ return Math.min(prev + 1, relatedTags.length - 1);
+ });
+ return;
+ }
+
+ if (event.key === 'ArrowUp') {
+ event.preventDefault();
+ setFocusedIndex((prev) => {
+ const next = prev > 0 ? prev - 1 : -1;
+ return next;
+ });
+ return;
+ }
+
+ if (event.key === 'Enter') {
+ event.preventDefault();
+
+ if (focusedIndex >= 0 && relatedTags[focusedIndex]) {
+ const selectedTag = relatedTags[focusedIndex].name;
+
+ setTagList((prev) => {
+ if (prev.includes(selectedTag)) {
+ return prev;
+ }
+ return [...prev, selectedTag];
+ });
+
+ setInputValue('');
+ setRelatedTags([]);
+ setFocusedIndex(-1);
+ } else if (inputValue.trim()) {
+ const newTag = inputValue.trim();
+
+ setTagList((prev) => {
+ if (prev.includes(newTag)) {
+ return prev;
+ }
+ return [...prev, newTag];
+ });
+
+ setInputValue('');
+ setRelatedTags([]);
+ }
+ return;
+ }
+
+ if (event.key === 'Escape') {
+ setIsExpanded(false);
+ setFocusedIndex(-1);
+ }
+ };
+
+ const onClickExpanded = () => {
+ setIsExpanded((prev) => !prev);
+ };
+
+ const onClickRelatedTag = (tag: TagType) => {
+ setTagList((prev) => [...prev, tag.name]);
+ setInputValue('');
+ setRelatedTags([]);
+ setFocusedIndex(-1);
+ };
+
+ return (
+
+ {isExpanded ? (
+
+ ) : (
+
+ )}
+
+ );
+}
diff --git a/src/components/features/Items/Card/Card.css.ts b/src/commons/components/features/Items/Card/Card.css.ts
similarity index 100%
rename from src/components/features/Items/Card/Card.css.ts
rename to src/commons/components/features/Items/Card/Card.css.ts
diff --git a/src/components/features/Items/Card/Card.tsx b/src/commons/components/features/Items/Card/Card.tsx
similarity index 100%
rename from src/components/features/Items/Card/Card.tsx
rename to src/commons/components/features/Items/Card/Card.tsx
diff --git a/src/commons/components/features/Lists/RelatedTags/RelatedTags.css.ts b/src/commons/components/features/Lists/RelatedTags/RelatedTags.css.ts
new file mode 100644
index 0000000..ba1d464
--- /dev/null
+++ b/src/commons/components/features/Lists/RelatedTags/RelatedTags.css.ts
@@ -0,0 +1,40 @@
+import { style } from '@vanilla-extract/css';
+
+export const relatedTagWrapper = style({
+ display: 'flex',
+ flexDirection: 'column',
+
+ margin: '0',
+ padding: '0',
+});
+
+export const relatedTagBox = style({
+ display: 'flex',
+ flexDirection: 'row',
+ alignItems: 'center',
+
+ width: '100%',
+
+ gap: '10px',
+
+ cursor: 'pointer',
+
+ ':focus': {
+ outline: 'none',
+ backgroundColor: 'rgba(106, 104, 104, 0.1)',
+ },
+
+ ':hover': {
+ backgroundColor: 'rgba(106, 104, 104, 0.1)',
+ },
+});
+
+export const relatedTagText = style({
+ fontSize: '12px',
+
+ color: '#000',
+});
+
+export const focusedTag = style({
+ backgroundColor: 'rgba(106, 104, 104, 0.1)',
+});
diff --git a/src/commons/components/features/Lists/RelatedTags/RelatedTags.tsx b/src/commons/components/features/Lists/RelatedTags/RelatedTags.tsx
new file mode 100644
index 0000000..12c9c6b
--- /dev/null
+++ b/src/commons/components/features/Lists/RelatedTags/RelatedTags.tsx
@@ -0,0 +1,31 @@
+import type { TagType } from '@/domains/tag/tpyes/tag.type';
+import * as styles from './RelatedTags.css';
+import Tag from '@/commons/components/atoms/Icons/Tag/Tag';
+
+export const RelatedTags = ({
+ relatedTags,
+ focusedIndex,
+ onClickRelatedTag,
+}: {
+ relatedTags: TagType[];
+ focusedIndex: number;
+ onClickRelatedTag: (tag: TagType) => void;
+}) => {
+ return (
+
+ {relatedTags.map((tag, index) => (
+ - onClickRelatedTag(tag)}
+ tabIndex={0}
+ role="option"
+ aria-selected={index === focusedIndex}
+ >
+
+
{tag.name}
+
+ ))}
+
+ );
+};
diff --git a/src/commons/components/features/Lists/TagList/TagList.css.ts b/src/commons/components/features/Lists/TagList/TagList.css.ts
new file mode 100644
index 0000000..ba3d37b
--- /dev/null
+++ b/src/commons/components/features/Lists/TagList/TagList.css.ts
@@ -0,0 +1,11 @@
+import { style } from '@vanilla-extract/css';
+
+export const tagListWrapper = style({
+ display: 'flex',
+ flexDirection: 'row',
+ flexWrap: 'wrap',
+
+ gap: '10px',
+
+ fontSize: '12px',
+});
diff --git a/src/commons/components/features/Lists/TagList/TagList.tsx b/src/commons/components/features/Lists/TagList/TagList.tsx
new file mode 100644
index 0000000..9d402a2
--- /dev/null
+++ b/src/commons/components/features/Lists/TagList/TagList.tsx
@@ -0,0 +1,12 @@
+import { TagBox } from '@/commons/components/atoms/boxes/tagBox/tagBox';
+import * as styles from './TagList.css';
+
+export const TagList = ({ tags }: { tags: string[] }) => {
+ return (
+
+ {tags.map((tag) => (
+
+ ))}
+
+ );
+};
diff --git a/src/components/widgets/Header/Header.tsx b/src/commons/components/widgets/Header/Header.tsx
similarity index 88%
rename from src/components/widgets/Header/Header.tsx
rename to src/commons/components/widgets/Header/Header.tsx
index 6de42ca..e3fdc39 100755
--- a/src/components/widgets/Header/Header.tsx
+++ b/src/commons/components/widgets/Header/Header.tsx
@@ -1,7 +1,7 @@
'use client';
import Image from 'next/image';
-import ThemeIcon from '@/components/features/Common/ThemeIcon/ThemeIcon';
+import ThemeIcon from '@/commons/components/features/Common/ThemeIcon/ThemeIcon';
import { useTheme } from 'next-themes';
import * as styles from './header.css';
diff --git a/src/components/widgets/Header/header.css.ts b/src/commons/components/widgets/Header/header.css.ts
similarity index 100%
rename from src/components/widgets/Header/header.css.ts
rename to src/commons/components/widgets/Header/header.css.ts
diff --git a/src/components/widgets/SearchToolbar/SearchToolbar.css.ts b/src/commons/components/widgets/SearchToolbar/SearchToolbar.css.ts
similarity index 100%
rename from src/components/widgets/SearchToolbar/SearchToolbar.css.ts
rename to src/commons/components/widgets/SearchToolbar/SearchToolbar.css.ts
diff --git a/src/components/widgets/SearchToolbar/SearchToolbar.tsx b/src/commons/components/widgets/SearchToolbar/SearchToolbar.tsx
similarity index 56%
rename from src/components/widgets/SearchToolbar/SearchToolbar.tsx
rename to src/commons/components/widgets/SearchToolbar/SearchToolbar.tsx
index 04d088e..d3fb690 100644
--- a/src/components/widgets/SearchToolbar/SearchToolbar.tsx
+++ b/src/commons/components/widgets/SearchToolbar/SearchToolbar.tsx
@@ -1,5 +1,5 @@
-import Slider from '@/components/features/Common/Slider/Slider';
-import Search from '@/components/features/Inputs/Search/Search';
+import Slider from '@/commons/components/features/Common/Slider/Slider';
+import Search from '@/commons/components/features/Inputs/Search/Search';
import * as styles from './SearchToolbar.css';
export default function SearchToolbar() {
diff --git a/src/configs/fetch/http.api.ts b/src/commons/configs/fetch/http.api.ts
similarity index 90%
rename from src/configs/fetch/http.api.ts
rename to src/commons/configs/fetch/http.api.ts
index 6bf1b7f..d599fb0 100644
--- a/src/configs/fetch/http.api.ts
+++ b/src/commons/configs/fetch/http.api.ts
@@ -1,9 +1,3 @@
-interface ResponseData {
- code: string;
- isSuccess: boolean;
- result: T;
-}
-
type FetchOptions = RequestInit & {
params?: Record;
revalidate?: number | false;
@@ -58,7 +52,7 @@ const createFetchInstance = (baseUrl: string) => {
export const fetchApi = createFetchInstance(baseURL);
const createApiMethods = (instance: (url: string, options?: FetchOptions) => Promise) => ({
- Get: async (url: string, params = {}, options: { revalidate?: number | false } = {}): Promise> => {
+ Get: async (url: string, params = {}, options: { revalidate?: number | false } = {}): Promise => {
try {
return await instance(url, {
method: 'GET',
@@ -70,7 +64,7 @@ const createApiMethods = (instance: (url: string, options?: FetchOptions) => Pro
}
},
- Post: async (url: string, data?: D, options = {}): Promise> => {
+ Post: async (url: string, data?: D, options = {}): Promise => {
try {
return await instance(url, {
method: 'POST',
@@ -83,7 +77,7 @@ const createApiMethods = (instance: (url: string, options?: FetchOptions) => Pro
}
},
- Put: async (url: string, data?: D, options = {}): Promise> => {
+ Put: async (url: string, data?: D, options = {}): Promise => {
try {
return await instance(url, {
method: 'PUT',
@@ -96,7 +90,7 @@ const createApiMethods = (instance: (url: string, options?: FetchOptions) => Pro
}
},
- Delete: async (url: string, options = {}): Promise> => {
+ Delete: async (url: string, options = {}): Promise => {
try {
return await instance(url, {
method: 'DELETE',
@@ -108,7 +102,7 @@ const createApiMethods = (instance: (url: string, options?: FetchOptions) => Pro
}
},
- Patch: async (url: string, data?: D, options = {}): Promise> => {
+ Patch: async (url: string, data?: D, options = {}): Promise => {
try {
return await instance(url, {
method: 'PATCH',
diff --git a/src/providers/ThemeProvider/ThemeProvider.tsx b/src/commons/providers/ThemeProvider/ThemeProvider.tsx
similarity index 83%
rename from src/providers/ThemeProvider/ThemeProvider.tsx
rename to src/commons/providers/ThemeProvider/ThemeProvider.tsx
index bb78d8e..561b366 100644
--- a/src/providers/ThemeProvider/ThemeProvider.tsx
+++ b/src/commons/providers/ThemeProvider/ThemeProvider.tsx
@@ -1,6 +1,6 @@
'use client';
-import { darkTheme, lightTheme } from '@/styles/globalStyles.css';
+import { darkTheme, lightTheme } from '@/commons/styles/globalStyles.css';
import { ThemeProvider } from 'next-themes';
const Provider = ({ children }: { children: React.ReactNode }) => {
diff --git a/src/styles/globalStyles.css.ts b/src/commons/styles/globalStyles.css.ts
similarity index 100%
rename from src/styles/globalStyles.css.ts
rename to src/commons/styles/globalStyles.css.ts
diff --git a/src/styles/rootStyles.css.ts b/src/commons/styles/rootStyles.css.ts
similarity index 100%
rename from src/styles/rootStyles.css.ts
rename to src/commons/styles/rootStyles.css.ts
diff --git a/src/types/theme/index.ts b/src/commons/types/theme/index.ts
similarity index 100%
rename from src/types/theme/index.ts
rename to src/commons/types/theme/index.ts
diff --git a/src/utils/ui/scrollToTop/scrollToTop.ts b/src/commons/utils/ui/scrollToTop/scrollToTop.ts
similarity index 100%
rename from src/utils/ui/scrollToTop/scrollToTop.ts
rename to src/commons/utils/ui/scrollToTop/scrollToTop.ts
diff --git a/src/utils/ui/scrollToTop/scrollToTop.types.ts b/src/commons/utils/ui/scrollToTop/scrollToTop.types.ts
similarity index 100%
rename from src/utils/ui/scrollToTop/scrollToTop.types.ts
rename to src/commons/utils/ui/scrollToTop/scrollToTop.types.ts
diff --git a/src/components/features/Inputs/Search/Search.tsx b/src/components/features/Inputs/Search/Search.tsx
deleted file mode 100644
index df44070..0000000
--- a/src/components/features/Inputs/Search/Search.tsx
+++ /dev/null
@@ -1,92 +0,0 @@
-'use client';
-
-import { KeyboardEvent, useState } from 'react';
-import Image from 'next/image';
-import Tag from '@/components/atoms/Icons/Tag/Tag';
-import * as styles from './Search.css';
-
-export default function Search() {
- const [isExpanded, setIsExpanded] = useState(false);
- const [tagList, setTagList] = useState([]);
- const [inputValue, setInputValue] = useState(''); // 입력값을 저장할 state 추가
-
- const handleKeyDown = (event: KeyboardEvent) => {
- if (event.nativeEvent.isComposing || event.keyCode === 229) return;
-
- if (event.key === 'Enter' && inputValue.trim()) {
- setTagList((prev) => [...prev, inputValue.trim()]);
- setInputValue('');
- }
- };
-
- const onClickExpanded = () => {
- setIsExpanded((prev) => !prev);
- };
-
- return (
-
- {isExpanded ? (
- <>
-
-
setInputValue(e.target.value)}
- onKeyDown={handleKeyDown}
- />
-
-
- {tagList.map((el) => (
-
- {el}
-
- ))}
-
-
-
- -
-
-
관련 태그
-
- -
-
-
관련 태그
-
-
-
-
-
- >
- ) : (
- <>
-
- {new Array(3).fill('React').map((el, index) => (
-
- {el}
-
- ))}
-
-
-
-
- >
- )}
-
- );
-}
diff --git a/src/domains/tag/api/tags.api.ts b/src/domains/tag/api/tags.api.ts
new file mode 100644
index 0000000..23adf1e
--- /dev/null
+++ b/src/domains/tag/api/tags.api.ts
@@ -0,0 +1,4 @@
+import { Get } from '@/commons/configs/fetch/http.api';
+import type { TagResponse } from '@/domains/tag/tpyes/tag.type';
+
+export const getTags = async (search?: string) => Get(`/tags`, { search });
diff --git a/src/domains/tag/tpyes/tag.type.ts b/src/domains/tag/tpyes/tag.type.ts
new file mode 100644
index 0000000..d0cd9e9
--- /dev/null
+++ b/src/domains/tag/tpyes/tag.type.ts
@@ -0,0 +1,11 @@
+interface TagType {
+ id: number;
+ name: string;
+}
+
+interface TagResponse {
+ count: number;
+ tags: TagType[];
+}
+
+export type { TagType, TagResponse };