-
Notifications
You must be signed in to change notification settings - Fork 3
feat: 자료실 기능 및 워크스페이스 목업 확장 (#21) #22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| // 워크스페이스 자료실 페이지의 라우트 진입점입니다. | ||
| import { ResourcesView } from '@/views/store-operation/resources'; | ||
|
|
||
| interface FilesPageProps { | ||
| params: Promise<{ | ||
| workspaceId: string; | ||
| }>; | ||
| } | ||
|
|
||
| export default async function FilesPage({ params }: FilesPageProps) { | ||
| const { workspaceId } = await params; | ||
|
|
||
| return <ResourcesView workspaceId={workspaceId} />; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| // 자료실 도메인의 타입과 목업 데이터 공개 API입니다. | ||
| export type { | ||
| ResourceFormValues, | ||
| ResourceItem, | ||
| ResourceLinkProvider, | ||
| ResourceType, | ||
| } from './model/resource.types'; | ||
| export { mockResources } from './model/mock-resources'; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,140 @@ | ||
| // Supabase Storage와 resources 테이블 연결 전 자료실 화면에서 사용하는 목업 데이터입니다. | ||
| import type { ResourceItem } from './resource.types'; | ||
|
|
||
| export const mockResources: ResourceItem[] = [ | ||
| { | ||
| id: 'resource-1', | ||
| workspaceId: 'store-workspace', | ||
| title: '7월 신메뉴 레시피.pdf', | ||
| description: '망고라떼, 피치에이드 레시피', | ||
| resourceType: 'file', | ||
| fileName: '7월 신메뉴 레시피.pdf', | ||
| uploadedBy: '김민서', | ||
| createdAt: '2025-06-28', | ||
| }, | ||
| { | ||
| id: 'resource-2', | ||
| workspaceId: 'store-workspace', | ||
| title: '6월 매출 정산.xls', | ||
| description: '일별 매출 집계표', | ||
| resourceType: 'file', | ||
| fileName: '6월 매출 정산.xlsx', | ||
| uploadedBy: '이준혁', | ||
| createdAt: '2025-06-30', | ||
| }, | ||
| { | ||
| id: 'resource-3', | ||
| workspaceId: 'store-workspace', | ||
| title: '재고 관리 시트', | ||
| description: 'Google 스프레드시트', | ||
| resourceType: 'link', | ||
| linkProvider: 'link', | ||
| url: 'https://docs.google.com/spreadsheets', | ||
| uploadedBy: '김민서', | ||
| createdAt: '2025-06-01', | ||
| }, | ||
| { | ||
| id: 'resource-4', | ||
| workspaceId: 'store-workspace', | ||
| title: '카드단말기 사용설명서.pdf', | ||
| description: '신형 단말기 매뉴얼', | ||
| resourceType: 'file', | ||
| fileName: '카드단말기 사용설명서.pdf', | ||
| uploadedBy: '이준혁', | ||
| createdAt: '2025-06-22', | ||
| }, | ||
| { | ||
| id: 'resource-5', | ||
| workspaceId: 'team-workspace', | ||
| title: '캡스톤 기획서 v2.pdf', | ||
| description: '최종 기획 문서', | ||
| resourceType: 'file', | ||
| fileName: '캡스톤 기획서 v2.pdf', | ||
| uploadedBy: '김지은', | ||
| createdAt: '2025-06-28', | ||
| }, | ||
| { | ||
| id: 'resource-6', | ||
| workspaceId: 'team-workspace', | ||
| title: 'Figma 디자인 파일', | ||
| description: 'UI 컴포넌트 모음', | ||
| resourceType: 'link', | ||
| linkProvider: 'figma', | ||
| url: 'https://figma.com', | ||
| uploadedBy: '박서준', | ||
| createdAt: '2025-06-26', | ||
| }, | ||
| { | ||
| id: 'resource-7', | ||
| workspaceId: 'team-workspace', | ||
| title: '사용자 인터뷰 결과.xlsx', | ||
| description: '인터뷰 응답 원본 데이터', | ||
| resourceType: 'file', | ||
| fileName: '사용자 인터뷰 결과.xlsx', | ||
| uploadedBy: '이하은', | ||
| createdAt: '2025-06-24', | ||
| }, | ||
| { | ||
| id: 'resource-8', | ||
| workspaceId: 'team-workspace', | ||
| title: 'API 명세서 (Notion)', | ||
| description: 'REST API 문서', | ||
| resourceType: 'link', | ||
| linkProvider: 'notion', | ||
| url: 'https://notion.so', | ||
| uploadedBy: '최민준', | ||
| createdAt: '2025-06-22', | ||
| }, | ||
| { | ||
| id: 'resource-9', | ||
| workspaceId: 'team-workspace', | ||
| title: '로고 최종본.zip', | ||
| description: 'PNG, SVG, AI 파일 포함', | ||
| resourceType: 'file', | ||
| fileName: '로고 최종본.zip', | ||
| uploadedBy: '박서준', | ||
| createdAt: '2025-06-20', | ||
| }, | ||
| { | ||
| id: 'resource-10', | ||
| workspaceId: 'side-workspace', | ||
| title: 'Fitto 피그마 파일', | ||
| description: '전체 UI/X 디자인', | ||
| resourceType: 'link', | ||
| linkProvider: 'figma', | ||
| url: 'http://figma.com', | ||
| uploadedBy: '박서준', | ||
| createdAt: '2025-06-30', | ||
| }, | ||
| { | ||
| id: 'resource-11', | ||
| workspaceId: 'side-workspace', | ||
| title: 'Github Repository', | ||
| description: '메인 코드 저장소', | ||
| resourceType: 'link', | ||
| linkProvider: 'github', | ||
| url: 'https://github.com', | ||
| uploadedBy: '이하은', | ||
| createdAt: '2025-06-31', | ||
| }, | ||
| { | ||
| id: 'resource-12', | ||
| workspaceId: 'side-workspace', | ||
| title: 'API 명세서 v3.pdf', | ||
| description: 'REST API 전체 문서', | ||
| resourceType: 'file', | ||
| fileName: 'API 명세서 v3.pdf', | ||
| uploadedBy: '이하은', | ||
| createdAt: '2025-06-29', | ||
| }, | ||
| { | ||
| id: 'resource-13', | ||
| workspaceId: 'side-workspace', | ||
| title: '기획서_Fitto_v2.pdf', | ||
| description: '서비스 기획 문서', | ||
| resourceType: 'file', | ||
| fileName: '기획서_Fitto_v2.pdf', | ||
| uploadedBy: '김지은', | ||
| createdAt: '2025-06-15', | ||
| }, | ||
| ]; | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| // 자료실에서 파일과 외부 링크를 같은 목록으로 다루기 위한 타입입니다. | ||
| export type ResourceType = 'file' | 'link'; | ||
|
|
||
| export type ResourceLinkProvider = 'link' | 'notion' | 'figma' | 'github'; | ||
|
|
||
| export interface ResourceItem { | ||
| id: string; | ||
| workspaceId: string; | ||
| title: string; | ||
| description: string; | ||
| resourceType: ResourceType; | ||
| linkProvider?: ResourceLinkProvider; | ||
| url?: string; | ||
| fileName?: string; | ||
| uploadedBy: string; | ||
| createdAt: string; | ||
| } | ||
|
|
||
| export interface ResourceFormValues { | ||
| resourceType: ResourceType; | ||
| title: string; | ||
| description: string; | ||
| url: string; | ||
| fileName: string; | ||
| linkProvider: ResourceLinkProvider; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| // 자료실 관리 기능의 상태 훅과 UI 컴포넌트 공개 API입니다. | ||
| export { useResourceLibraryState } from './model/use-resource-library-state'; | ||
| export { ResourceAddDialog } from './ui/ResourceAddDialog'; | ||
| export { ResourceList } from './ui/ResourceList'; |
91 changes: 91 additions & 0 deletions
91
src/features/manage-resources/model/use-resource-library-state.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,91 @@ | ||
| 'use client'; | ||
|
|
||
| // 자료실 목록과 파일/링크 추가 모달의 클라이언트 목업 상태를 관리합니다. | ||
| import { useMemo, useState } from 'react'; | ||
| import type { ResourceFormValues, ResourceItem, ResourceType } from '@/entities/resource'; | ||
|
|
||
| interface UseResourceLibraryStateParams { | ||
| initialResources: ResourceItem[]; | ||
| workspaceId: string; | ||
| uploaderName: string; | ||
| } | ||
|
|
||
| function sortResources(resources: ResourceItem[]) { | ||
| return [...resources].sort((first, second) => second.createdAt.localeCompare(first.createdAt)); | ||
| } | ||
|
|
||
| function createResourceId() { | ||
| if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') { | ||
| return `resource-${crypto.randomUUID()}`; | ||
| } | ||
|
|
||
| return `resource-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`; | ||
| } | ||
|
|
||
| function createTodayLabel() { | ||
| return new Date().toISOString().slice(0, 10); | ||
| } | ||
|
|
||
| export function useResourceLibraryState({ | ||
| initialResources, | ||
| workspaceId, | ||
| uploaderName, | ||
| }: UseResourceLibraryStateParams) { | ||
| const workspaceResources = useMemo( | ||
| () => sortResources(initialResources.filter((resource) => resource.workspaceId === workspaceId)), | ||
| [initialResources, workspaceId], | ||
| ); | ||
| const [resourcesByWorkspaceId, setResourcesByWorkspaceId] = useState< | ||
| Record<string, ResourceItem[]> | ||
| >({}); | ||
| const [isDialogOpen, setIsDialogOpen] = useState(false); | ||
| const [dialogResourceType, setDialogResourceType] = useState<ResourceType>('file'); | ||
| const resources = resourcesByWorkspaceId[workspaceId] ?? workspaceResources; | ||
|
|
||
| const addResource = (values: ResourceFormValues) => { | ||
| const title = values.title.trim() || values.fileName.trim() || values.url.trim(); | ||
| const description = values.description.trim(); | ||
|
|
||
| if (!title) { | ||
| return; | ||
| } | ||
|
|
||
| if (values.resourceType === 'link' && !values.url.trim()) { | ||
| return; | ||
| } | ||
|
|
||
| const nextResource: ResourceItem = { | ||
| id: createResourceId(), | ||
| workspaceId, | ||
| title, | ||
| description, | ||
| resourceType: values.resourceType, | ||
| linkProvider: values.resourceType === 'link' ? values.linkProvider : undefined, | ||
| url: values.resourceType === 'link' ? values.url.trim() : undefined, | ||
| fileName: values.resourceType === 'file' ? values.fileName.trim() : undefined, | ||
| uploadedBy: uploaderName, | ||
| createdAt: createTodayLabel(), | ||
| }; | ||
|
|
||
| setResourcesByWorkspaceId((currentResourcesByWorkspaceId) => ({ | ||
| ...currentResourcesByWorkspaceId, | ||
| [workspaceId]: sortResources([ | ||
| nextResource, | ||
| ...(currentResourcesByWorkspaceId[workspaceId] ?? workspaceResources), | ||
| ]), | ||
| })); | ||
| setIsDialogOpen(false); | ||
| }; | ||
|
|
||
| return { | ||
| resources, | ||
| isDialogOpen, | ||
| dialogResourceType, | ||
| openDialog: (nextResourceType: ResourceType) => { | ||
| setDialogResourceType(nextResourceType); | ||
| setIsDialogOpen(true); | ||
| }, | ||
| closeDialog: () => setIsDialogOpen(false), | ||
| addResource, | ||
| }; | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win
존재하지 않는 날짜 값 (
2025-06-31).resource-11의createdAt이'2025-06-31'인데, 6월은 30일까지만 존재합니다.sortResources가localeCompare로 문자열 비교만 하므로 크래시는 나지 않지만, 실제로는 유효하지 않은 날짜라 향후Date파싱이나 표시 로직에서 문제가 될 수 있습니다.🛠️ 제안 수정
resourceType: 'link', linkProvider: 'github', url: 'https://github.com', uploadedBy: '이하은', - createdAt: '2025-06-31', + createdAt: '2025-06-30', },📝 Committable suggestion
🤖 Prompt for AI Agents