Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
5613965
refactor: 순환 참조 문제로 인해 스토어 파일에서 type 분리
mamonde456 Jul 13, 2026
c32f1e8
refactor: import 경로 수정
mamonde456 Jul 14, 2026
1a640a4
chore: 관심사 및 파일 분리
mamonde456 Jul 15, 2026
ea6eb12
chore: service 함수들 관심사 및 파일 분리
mamonde456 Jul 16, 2026
13fc81b
chore: import 경로 수정
mamonde456 Jul 17, 2026
3c43392
feat/test: test에 필요한 fixture 생성 헬퍼 함수 추가
mamonde456 Jul 20, 2026
5d66f7a
feat/test: handleCellChange의 셀 수정 테스트 추가
mamonde456 Jul 20, 2026
dad5341
feat/test: handleCellChange 예외 케이스들 검사 추가
mamonde456 Jul 21, 2026
6e9b0c0
chore: 파일 위치 이동으로 인한 import 경로 수정
mamonde456 Jul 22, 2026
e2e513d
chore/test: fixtures 데이터 추가
mamonde456 Jul 23, 2026
8582268
feat/test:toLegacyStructure 함수의 변환 로직 테스트 추가
mamonde456 Jul 23, 2026
b08353d
feat/test: toLegacyStructure 테스트의 예외 케이스 추가
mamonde456 Jul 27, 2026
2ed24f3
feat/test: toFlayStructure 테스트 추가
mamonde456 Jul 28, 2026
c775618
feat/test: toFlatStructure 예외 케이스 추가
mamonde456 Jul 29, 2026
c0628f0
feat/test: applyChangesToServer 테스트 함수 추가
mamonde456 Jul 30, 2026
7a1eaae
feat/test: applyChangesToServer 예외 케이스 추가
mamonde456 Jul 31, 2026
9a239a9
fix: main 포지션이 없을 때 하위 포지션이 생성되지 않는 문제 해결
mamonde456 Aug 3, 2026
b0a465a
chore: import 경로 수정
mamonde456 Aug 3, 2026
19d3f12
chore: import 경로 변경
mamonde456 Aug 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Button from "@/feature/ui/Button";
import { useMandalaStore, type SubGoal } from "@/lib/stores/mandalaStore";
import { useMandalaStore } from "@/lib/stores/mandalaStore";
import { cn } from "@/lib/utils";
import { ChevronRight } from "lucide-react";
import React, { useState } from "react";
Expand All @@ -10,6 +10,7 @@ import {
tutorialArrowCells,
tutorialCellMap,
} from "@/feature/tutorial/service";
import type { SubGoal } from "@/lib/stores/types/mandalart";

type MandalaReadOnlyCellProps = {
goalId: string;
Expand Down
2 changes: 1 addition & 1 deletion src/feature/mandala/components/full/FullMandalaView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import {
type Type,
} from "../../utills/css";
import useGridTabNavigation from "../../hooks/useGridTabNavigation";
import { getNextFullCellId } from "../../service";
import FullCell from "../full/FullCell";
import { getNextFullCellId } from "../../service/navigation";

export default function FullMandalaView() {
const editingFullCellId = useMandalaStore((state) => state.editingFullCellId);
Expand Down
2 changes: 1 addition & 1 deletion src/feature/mandala/components/grid/MandalaGrid.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { useMandalaStore } from "@/lib/stores/mandalaStore";
import useGridTabNavigation from "../../hooks/useGridTabNavigation";
import { getNextMainCellId } from "../../service";
import GridCell from "./GridCell";
import { getGridClasses } from "../../utills/css";
import MandalaModal from "../modal/MandalaModal";
import { getNextMainCellId } from "../../service/navigation";

export default function MandalaGrid() {
const editingCellId = useMandalaStore((state) => state.editingCellId);
Expand Down
5 changes: 3 additions & 2 deletions src/feature/mandala/components/modal/MandalaModal.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useMandalaStore, type SubGoal } from "@/lib/stores/mandalaStore";
import { useMandalaStore } from "@/lib/stores/mandalaStore";

import { useCallback, useEffect, useMemo, useRef, useState } from "react";

Expand All @@ -14,11 +14,12 @@ import { useShallow } from "zustand/react/shallow";
import useGridTabNavigation from "../../hooks/useGridTabNavigation";
import UseSubsGoalNavigation from "../../hooks/ueSubsGoalNavigation";
import useSSERecommendation from "../../hooks/useSSERecommendation";
import { getNextSubCellId } from "../../service";
import type { CellData } from "../../service/type";
import ModalCell from "./ModalCell";
import { getGridClasses } from "../../utills/css";
import QuestionIcon from "../icon/QuestionIcon";
import { getNextSubCellId } from "../../service/navigation";
import type { SubGoal } from "@/lib/stores/types/mandalart";

type Props = {
isModalVisible: boolean;
Expand Down
2 changes: 1 addition & 1 deletion src/feature/mandala/hooks/useMandalaData.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { useQuery } from "@tanstack/react-query";
import { getMandalaAPI } from "../api/mandalart/getMandala";
import { emptyDummyData } from "../service";
import { useAuthStore } from "@/lib/stores/authStore";
import type { ServerMandalaType } from "../service/type";
import { emptyDummyData } from "../service/transform";

export default function useMandalaData() {
const accessToken = useAuthStore((state) => state.accessToken);
Expand Down
3 changes: 2 additions & 1 deletion src/feature/mandala/hooks/useSSERecommendation.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { useCallback, useEffect, useRef, useState } from "react";
import { EventSourcePolyfill } from "event-source-polyfill";
import { useMandalaStore, type SubGoal } from "@/lib/stores/mandalaStore";
import { useMandalaStore } from "@/lib/stores/mandalaStore";
import type { CellData } from "../service/type";
import { ENV } from "@/const";
import type { SubGoal } from "@/lib/stores/types/mandalart";

type UseSSERecommendationOptions = {
goal: string;
Expand Down
2 changes: 1 addition & 1 deletion src/feature/mandala/pages/MandalaBoard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import Button from "@/feature/ui/Button";

import { useEffect } from "react";
import { useAuthStore } from "@/lib/stores/authStore";
import { uiToServer } from "../service";
import { toast } from "sonner";
import MailIcon from "../components/icon/MailIcon";
import ActivationBellIcon from "../components/icon/ActivationBellIcon";
Expand All @@ -19,6 +18,7 @@ import { performLogout } from "@/feature/auth/hooks/useLogout";
import MandalaGrid from "../components/grid/MandalaGrid";
import FullMandalaView from "../components/full/FullMandalaView";
import ReminderSetting from "../components/reminder/ReminderSetting";
import { uiToServer } from "../service/server";

type MandaraChartProps = {
getCurrentBackground: () => Record<string, string>;
Expand Down
5 changes: 3 additions & 2 deletions src/feature/mandala/service/changedCellId.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import type { MainGoal, MandalaType } from "@/lib/stores/mandalaStore";
import { getDataById, isEqual, toFlatStructure } from ".";
import type { MainGoal, MandalaType } from "@/lib/stores/types/mandalart";
import { parseCellId } from "./parseCellId";
import type { MandalaMap, ServerMandalaType } from "./type";
import { getDataById, isEqual } from ".";
import { toFlatStructure } from "./transform";

type GetChangedCellId = {
cellId: string;
Expand Down
80 changes: 80 additions & 0 deletions src/feature/mandala/service/idManager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import type { ServerMandalaType } from "./type";

export const createMandalaIdManager = (
serverData: ServerMandalaType["data"]
) => {
const usedMainIds = new Set<string>();
const usedSubIds = new Set<string>();
const resgisterExistingIds = () => {
if (serverData.core?.goalId) {
usedMainIds.add(`core-${serverData.core.goalId}`);
}

serverData?.core?.mains?.forEach((main) => {
if (main.goalId) {
usedMainIds.add(`main-${main.goalId}`);
}

main.subs.forEach((sub) => {
if (sub.goalId) {
usedSubIds.add(`sub-${main.goalId || main.position}-${sub.goalId}`);
}
});
});
};

resgisterExistingIds();

const generateCoreId = (originalId?: number) => {
if (originalId) {
return `core-${serverData.core.goalId}`;
}
return `core-0`;
};

const generateMainId = (originalId?: number, position?: number) => {
if (originalId) {
return `main-${originalId}`;
}

let candidateId = `main-${position}`;
let counter = 1000;

while (usedMainIds.has(candidateId)) {
candidateId = `main-${counter}`;
counter++;
}

usedMainIds.add(candidateId);
return candidateId;
};

const generateSubId = (
mainId: string,
originalId?: number,
position?: number
) => {
if (originalId) {
return `sub-${mainId.replace("main-", "")}-${originalId}`;
}

let candidateId = `sub-${mainId.replace("main-", "")}-${position}`;
let counter = 1000;

while (usedSubIds.has(candidateId)) {
candidateId = `sub-${mainId.replace("main-", "")}-${counter}`;
counter++;
}

usedSubIds.add(candidateId);
return candidateId;
};

return {
generateCoreId,
generateMainId,
generateSubId,
getUsedMainId: () => Array.from(usedMainIds),
getUsedMSubId: () => Array.from(usedSubIds),
};
};
Loading
Loading