diff --git a/src/app/(sidebar)/(my-info)/apis/useGetCardTags.ts b/src/app/(sidebar)/(my-info)/apis/useGetCardTags.ts
index 75edf9ca..047e1427 100644
--- a/src/app/(sidebar)/(my-info)/apis/useGetCardTags.ts
+++ b/src/app/(sidebar)/(my-info)/apis/useGetCardTags.ts
@@ -2,7 +2,7 @@ import { http } from '@/apis/http';
import { TagType } from '@/types';
import { useQuery } from '@tanstack/react-query';
-export const GET_TAGS = 'tags';
+export const GET_TAGS = 'tagList';
type GetCardTagsRseponse = TagType[];
diff --git a/src/app/(sidebar)/(my-info)/components/InfoCardSkeleton.tsx b/src/app/(sidebar)/(my-info)/components/InfoCardSkeleton.tsx
index 1b77c7aa..715b1834 100644
--- a/src/app/(sidebar)/(my-info)/components/InfoCardSkeleton.tsx
+++ b/src/app/(sidebar)/(my-info)/components/InfoCardSkeleton.tsx
@@ -1,5 +1,4 @@
import { motion } from 'framer-motion';
-import { match } from 'ts-pattern';
interface InfoCardSkeletonProps {
count: number;
diff --git a/src/app/(sidebar)/layout.tsx b/src/app/(sidebar)/layout.tsx
index d9b05b11..e891e9c1 100644
--- a/src/app/(sidebar)/layout.tsx
+++ b/src/app/(sidebar)/layout.tsx
@@ -1,11 +1,14 @@
import { Sidebar } from '@/container/Sidebar/Sidebar';
import { PropsWithChildren } from 'react';
+import { CardWindowLayout } from '@/components/CardWindow/context';
export default function SidebarLayout({ children }: PropsWithChildren) {
return (
-
{children}
+
+ {children}
+
);
}
diff --git a/src/app/(sidebar)/my-recruit/[id]/mocks.ts b/src/app/(sidebar)/my-recruit/[id]/mocks.ts
index e8fba7f4..bebd8f60 100644
--- a/src/app/(sidebar)/my-recruit/[id]/mocks.ts
+++ b/src/app/(sidebar)/my-recruit/[id]/mocks.ts
@@ -582,6 +582,7 @@ export const colorStyle = {
default: 'bg-[#F1F2F3] text-[#37383C]',
blue: 'bg-[#E8F1FF] text-[#418CC3]',
purple: 'bg-[#F1E8FF] text-[#9C6BB3]',
+ yellow: 'bg-[#FFF3C2] text-[#D77B0F]',
};
export const DEFAULT_TAG_MOCKS: TagType[] = [
diff --git a/src/app/(sidebar)/write/[id]/page.tsx b/src/app/(sidebar)/write/[id]/page.tsx
index d70a7cb5..92da36ab 100644
--- a/src/app/(sidebar)/write/[id]/page.tsx
+++ b/src/app/(sidebar)/write/[id]/page.tsx
@@ -99,7 +99,8 @@ export default function Page({ params: { id } }: { params: { id: string } }) {
- {categoryTags.map((tag) => (
+ {/* FIXME */}
+ {/* {categoryTags.map((tag) => (
{tag.name}
- ))}
+ ))} */}
diff --git a/src/components/CardWindow/CardWindow.tsx b/src/components/CardWindow/CardWindow.tsx
new file mode 100644
index 00000000..546ebe09
--- /dev/null
+++ b/src/components/CardWindow/CardWindow.tsx
@@ -0,0 +1,159 @@
+import { TouchButton } from '@/components/TouchButton';
+import { Icon, Tag } from '@/system/components';
+import { color } from '@/system/token/color';
+import { ReactNode, useState } from 'react';
+import { useGetInfoCardDetail } from '../../hooks/apis/useGetInfoCardDetail';
+import { Spacing } from '@/system/utils/Spacing';
+import { formatToYYMMDD } from '@/utils/date';
+import { motion } from 'framer-motion';
+import { If } from '@/system/utils/If';
+import { useRouter } from 'next/navigation';
+
+interface CardWindowProps {
+ cardId: number;
+ onClose: () => void;
+}
+
+export function CardWindow({ cardId, onClose }: CardWindowProps) {
+ const router = useRouter();
+ const [isRight, setIsRight] = useState(true);
+
+ const { data: card, isLoading } = useGetInfoCardDetail(cardId);
+
+ return (
+
+
+
+
+ {
+ router.push(`/write/${cardId}`);
+ onClose();
+ }}
+ description="해당 글로 이동하기">
+
+
+ setIsRight((prev) => !prev)}
+ description={`${isRight ? '왼쪽' : '오른쪽'}으로 옮기기`}>
+ svg]:rotate-180' : undefined}>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {card?.title || '제목을 입력해주세요'}
+
+
+ {formatToYYMMDD(card?.updatedDate || '', { separator: '.' })}
+
+
+
+
+ {card?.cardTypeValueList.map((type) => (
+
+ {type.replaceAll('_', ' ')}
+
+ ))}
+ {card?.tagList.map(({ id, name, type }) => (
+
+ {name}
+
+ ))}
+
+
+
{card?.content || '내용을 입력해주세요'}
+
+
+
+ );
+}
+
+interface WindowButtonProps {
+ onClick?: () => void;
+ description?: string;
+ children: ReactNode;
+}
+
+function WindowButton({ onClick, children, description }: WindowButtonProps) {
+ return (
+
+ {children}
+
+ {description}
+
+
+ );
+}
+
+function Skeleton() {
+ return (
+
+
+
+
+ );
+}
diff --git a/src/components/CardWindow/context.tsx b/src/components/CardWindow/context.tsx
new file mode 100644
index 00000000..d0add7d0
--- /dev/null
+++ b/src/components/CardWindow/context.tsx
@@ -0,0 +1,39 @@
+'use client';
+
+import { generateContext } from '@/lib';
+import { useState } from 'react';
+import { CardWindow } from './CardWindow';
+import { AnimatePresence } from 'framer-motion';
+
+interface CardWindowContext {
+ isOpen: boolean;
+ open: (cardId: number) => void;
+ close: () => void;
+}
+
+const [CardWindowProvider, useCardWindowContext] = generateContext({
+ name: 'CardWindow',
+});
+
+function CardWindowLayout({ children }: { children: React.ReactNode }) {
+ const [cardId, setCardId] = useState(null);
+
+ const isOpen = cardId !== null;
+
+ const open = (cardId: number) => {
+ setCardId(cardId);
+ };
+
+ const close = () => {
+ setCardId(null);
+ };
+
+ return (
+
+ {children}
+ {isOpen && }
+
+ );
+}
+
+export { CardWindowLayout, useCardWindowContext };
diff --git a/src/components/InfoCard.tsx b/src/components/InfoCard.tsx
index 32ac9156..1324015c 100644
--- a/src/components/InfoCard.tsx
+++ b/src/components/InfoCard.tsx
@@ -12,12 +12,14 @@ import { color } from '@/system/token/color';
import { useDeleteCard } from '@/app/(sidebar)/(my-info)/apis/useDeleteCard';
import Link from 'next/link';
import { MouseEventHandler } from 'react';
+import { useCardWindowContext } from './CardWindow/context';
type InfoCardProps = InfoCardType;
export function InfoCard({ id, title, updatedDate, tagList }: InfoCardProps) {
const formattedDate = formatToYYMMDD(updatedDate, { separator: '.' });
+ const { open } = useCardWindowContext();
const { mutate: deleteCard } = useDeleteCard();
const handleDeleteCard: MouseEventHandler = (event) => {
@@ -26,6 +28,12 @@ export function InfoCard({ id, title, updatedDate, tagList }: InfoCardProps) {
deleteCard(id);
};
+ const handleOpenCardWindow: MouseEventHandler = (event) => {
+ event.stopPropagation();
+
+ open(id);
+ };
+
return (
@@ -46,7 +54,7 @@ export function InfoCard({ id, title, updatedDate, tagList }: InfoCardProps) {
삭제하기
-
+
개별창으로 띄우기
@@ -64,4 +72,4 @@ export function InfoCard({ id, title, updatedDate, tagList }: InfoCardProps) {
);
-}
\ No newline at end of file
+}
diff --git a/src/hooks/apis/useGetInfoCardDetail.ts b/src/hooks/apis/useGetInfoCardDetail.ts
new file mode 100644
index 00000000..a3a52430
--- /dev/null
+++ b/src/hooks/apis/useGetInfoCardDetail.ts
@@ -0,0 +1,26 @@
+import { http } from '@/apis/http';
+import { InfoType, TagType } from '@/types';
+import { useQuery } from '@tanstack/react-query';
+
+export interface GetInfoCardDetailResponse {
+ title: string;
+ content: string;
+ updatedDate: string;
+ cardTypeValueList: InfoType[];
+ tagList: TagType[];
+}
+
+const getInfoCardDetail = (cardId: number) =>
+ http.get({
+ url: `/cards/${cardId}`,
+ });
+
+export const useGetInfoCardDetail = (cardId: number) =>
+ useQuery({
+ queryKey: ['get-info-card-detail', cardId],
+ queryFn: async () => {
+ const res = await getInfoCardDetail(cardId);
+
+ return res.data;
+ },
+ });
diff --git a/src/system/components/Icon/Icon.tsx b/src/system/components/Icon/Icon.tsx
index 0648eb6e..5e5ca901 100644
--- a/src/system/components/Icon/Icon.tsx
+++ b/src/system/components/Icon/Icon.tsx
@@ -1,24 +1,15 @@
-import { RemoveMemo } from '@/system/components/Icon/SVG/RemoveMemo';
-import { SubmitArrow } from '@/system/components/Icon/SVG/SubmitArrow';
import type { IconBaseType } from '@/system/components/Icon/SVG/type';
import { Add } from './SVG/Add';
import { Bell } from './SVG/Bell';
-import { Calendar } from './SVG/Calendar';
-import { CalendarFill } from './SVG/CalendarFill';
import { Check } from './SVG/Check';
-import { Close } from './SVG/Close';
-import { Clover } from './SVG/Clover';
import { CodingSignUp } from './SVG/CodingSignUp';
import { Copy } from './SVG/Copy';
import { Delete } from './SVG/Delete';
import { DesignSignup } from './SVG/DesignSignup';
import { Division } from './SVG/Division';
import { Down } from './SVG/Down';
-import { DownChevron } from './SVG/DownChevron';
import { Empty } from './SVG/Empty';
-import { FilledMemo } from './SVG/FilledMemo';
import { Folder } from './SVG/Folder';
-import { FolderFill } from './SVG/FolderFill';
import { Link } from './SVG/Link';
import { LogoOnly } from './SVG/LogoOnly';
import { Logout } from './SVG/Logout';
@@ -37,6 +28,17 @@ import { Shoes } from './SVG/Shoes';
import { Tag } from './SVG/Tag';
import { Trash } from './SVG/Trash';
import { Unlink } from './SVG/Unlink';
+import { Calendar } from './SVG/Calendar';
+import { CalendarFill } from './SVG/CalendarFill';
+import { SubmitArrow } from '@/system/components/Icon/SVG/SubmitArrow';
+import { FilledMemo } from './SVG/FilledMemo';
+import { RemoveMemo } from '@/system/components/Icon/SVG/RemoveMemo';
+import { Clover } from './SVG/Clover';
+import { DownChevron } from './SVG/DownChevron';
+import { FolderFill } from './SVG/FolderFill';
+import { Close } from './SVG/Close';
+import { FullScreenCorner } from './SVG/FullScreenCorner';
+import { ToLeft } from './SVG/ToLeft';
import { Up } from './SVG/Up';
import { X } from './SVG/X';
import { WorkFill } from './SVG/WorkFill';
@@ -74,6 +76,8 @@ const iconMap = {
filledMemo: FilledMemo,
removeMemo: RemoveMemo,
clover: Clover,
+ fullScreenCorner: FullScreenCorner,
+ toLeft: ToLeft,
refresh: Refresh,
empty: Empty,
tag: Tag,
diff --git a/src/system/components/Icon/SVG/FullScreenCorner.tsx b/src/system/components/Icon/SVG/FullScreenCorner.tsx
new file mode 100644
index 00000000..22d34f29
--- /dev/null
+++ b/src/system/components/Icon/SVG/FullScreenCorner.tsx
@@ -0,0 +1,11 @@
+import { IconBaseType } from './type';
+
+export function FullScreenCorner({ size, color }: IconBaseType) {
+ return (
+
+ );
+}
diff --git a/src/system/components/Icon/SVG/ToLeft.tsx b/src/system/components/Icon/SVG/ToLeft.tsx
new file mode 100644
index 00000000..4b5f332a
--- /dev/null
+++ b/src/system/components/Icon/SVG/ToLeft.tsx
@@ -0,0 +1,11 @@
+import { IconBaseType } from './type';
+
+export function ToLeft({ size, color }: IconBaseType) {
+ return (
+
+ );
+}
diff --git a/src/system/components/Tag/Tag.tsx b/src/system/components/Tag/Tag.tsx
index d77a671a..5f9b0f31 100644
--- a/src/system/components/Tag/Tag.tsx
+++ b/src/system/components/Tag/Tag.tsx
@@ -1,7 +1,7 @@
import { cn } from '@/utils/tailwind-util';
import { PropsWithChildren } from 'react';
-export type TagColor = 'default' | 'blue' | 'purple';
+export type TagColor = 'default' | 'blue' | 'purple' | 'yellow';
export interface TagProps {
color?: TagColor;
}
@@ -12,6 +12,7 @@ const colorStyle = {
default: 'bg-[#F1F2F3] text-[#37383C]',
blue: 'bg-[#E8F1FF] text-[#418CC3]',
purple: 'bg-[#F1E8FF] text-[#9C6BB3]',
+ yellow: 'bg-[#FFF3C2] text-[#D77B0F]',
};
export function Tag({ color = 'default', children }: PropsWithChildren) {