Skip to content

Commit

Permalink
Merge pull request #141 from boostcampwm-2024/Feature/FE/#137_workspaโ€ฆ
Browse files Browse the repository at this point in the history
โ€ฆce์—_๋กœํ‹ฐ์• ๋‹ˆ๋ฉ”์ด์…˜_์ ์šฉ

Feature/#137 workspace์— ๋กœํ‹ฐ์• ๋‹ˆ๋ฉ”์ด์…˜ ์ ์šฉ
  • Loading branch information
hyonun321 authored Nov 18, 2024
2 parents 141598c + 2217f0a commit 3f58bed
Show file tree
Hide file tree
Showing 10 changed files with 192 additions and 22 deletions.
10 changes: 10 additions & 0 deletions client/src/components/lotties/ErrorAlert.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Player } from "@lottiefiles/react-lottie-player";
import errorAlert from "@assets/lotties/errorAlert.json";

export const ErrorAlert = ({ size = 200 }) => {
return (
<div style={{ width: size, height: size }}>
<Player autoplay loop src={errorAlert} style={{ width: "100%", height: "100%" }} />
</div>
);
};
14 changes: 14 additions & 0 deletions client/src/components/modal/ErrorModal.style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { css } from "@styled-system/css";

export const errorModalWrapper = css({
display: "flex",
flexDirection: "column",
justifyContent: "center",
alignItems: "center",
padding: "40px",
});

export const errorMessageItem = css({
color: "red",
fontSize: "sm",
});
42 changes: 42 additions & 0 deletions client/src/components/modal/ErrorModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { ErrorAlert } from "@components/lotties/ErrorAlert";
import { errorMessageItem, errorModalWrapper } from "./ErrorModal.style";
import { Modal } from "./modal";

interface ErrorScreenProps {
errorMessage: string;
}

export const ErrorModal = ({ errorMessage }: ErrorScreenProps) => {
return (
<Modal
isOpen
primaryButtonLabel="์ƒˆ๋กœ๊ณ ์นจ"
primaryButtonOnClick={() => {
window.location.reload();
}}
>
<div className={errorModalWrapper}>
<ErrorAlert size={200} />
์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.
<br />
<p className={errorMessageItem}>{errorMessage}</p>
</div>
</Modal>
);
};

// <div className={overlay}>
// <div className={`${glassContainer({ border: "lg" })} ${modalWrapper}`}>
// <div className={animationContainer}>
// <Player autoplay loop src={errorAlert} style={{ width: "100%", height: "100%" }} />
// </div>

// <div className={content}>
// <h2 className={title}>์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.</h2>
// <p className={message}>{errorMessage}</p>
// <TextButton onClick={() => window.location.reload()} variant="primary">
// ์ƒˆ๋กœ๊ณ ์นจ
// </TextButton>
// </div>
// </div>
// </div>
2 changes: 1 addition & 1 deletion client/src/components/modal/modal.style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const modalContainer = cx(
flexDirection: "column",
justifyContent: "space-between",
width: "400px",
minHeight: "200px",
height: "auto",
padding: "md",
background: "white/20",
boxShadow: "md",
Expand Down
31 changes: 26 additions & 5 deletions client/src/features/workSpace/WorkSpace.style.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,31 @@
import { css } from "@styled-system/css";

export const container = css({
display: "flex",
});
import { css, cva } from "@styled-system/css";

export const content = css({
position: "relative",
padding: "md",
});

export const workSpaceContainer = cva({
base: {
display: "flex",
transition: "opacity 0.3s ease-in-out",
},
variants: {
visibility: {
visible: {
visibility: "visible",
},
hidden: {
visibility: "hidden",
},
},
opacity: {
1: {
opacity: 1,
},
0: {
opacity: 0,
},
},
},
});
49 changes: 33 additions & 16 deletions client/src/features/workSpace/WorkSpace.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,45 @@
import { BottomNavigator } from "@components/bottomNavigator/BottomNavigator";
import { ErrorModal } from "@components/modal/ErrorModal";
import { Sidebar } from "@components/sidebar/Sidebar";
import { Page } from "@features/page/Page";
import { container, content } from "./WorkSpace.style";
import { workSpaceContainer, content } from "./WorkSpace.style";
import { IntroScreen } from "./components/IntroScreen";
import { usePagesManage } from "./hooks/usePagesManage";
import { useWorkspaceInit } from "./hooks/useWorkspaceInit";

export const WorkSpace = () => {
const { isLoading, isInitialized, error } = useWorkspaceInit();

const { pages, addPage, selectPage, closePage, updatePageTitle } = usePagesManage();
const visiblePages = pages.filter((a) => a.isVisible);
const visiblePages = pages.filter((page) => page.isVisible);

if (error) {
return <ErrorModal errorMessage="test" />;
}

return (
<div className={container}>
<Sidebar pages={pages} handlePageAdd={addPage} handlePageSelect={selectPage} />
<div className={content}>
{visiblePages.map((page) => (
<Page
key={page.id}
{...page}
handlePageSelect={selectPage}
handlePageClose={closePage}
handleTitleChange={updatePageTitle}
/>
))}
<>
{isLoading && <IntroScreen />}
<div
className={workSpaceContainer({
visibility: isInitialized && !isLoading ? "visible" : "hidden",
opacity: isInitialized && !isLoading ? 1 : 0,
})}
>
<Sidebar pages={pages} handlePageAdd={addPage} handlePageSelect={selectPage} />
<div className={content}>
{visiblePages.map((page) => (
<Page
key={page.id}
{...page}
handlePageSelect={selectPage}
handlePageClose={closePage}
handleTitleChange={updatePageTitle}
/>
))}
</div>
<BottomNavigator pages={visiblePages} handlePageSelect={selectPage} />
</div>
<BottomNavigator pages={visiblePages} handlePageSelect={selectPage} />
</div>
</>
);
};
13 changes: 13 additions & 0 deletions client/src/features/workSpace/components/IntroScreen.style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { css } from "@styled-system/css";

export const IntroScreenContainer = css({
display: "flex",
zIndex: 50,
position: "fixed",
inset: 0,
justifyContent: "center",
alignItems: "center",
backgroundImage: "linear-gradient(135deg, gray, green)",
backgroundSize: "cover",
transition: "opacity 0.5s ease-in-out",
});
10 changes: 10 additions & 0 deletions client/src/features/workSpace/components/IntroScreen.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { LoadingSpinner } from "@components/lotties/LoadingSpinner";
import { IntroScreenContainer } from "./IntroScreen.style";

export const IntroScreen = () => {
return (
<div className={IntroScreenContainer}>
<LoadingSpinner size={200} />
</div>
);
};
43 changes: 43 additions & 0 deletions client/src/features/workSpace/hooks/useWorkspaceInit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { useState, useEffect } from "react";

interface UseWorkspaceInitReturn {
isLoading: boolean;
isInitialized: boolean;
error: Error | null;
}

export const useWorkspaceInit = (): UseWorkspaceInitReturn => {
const [isLoading, setIsLoading] = useState(true);
const [isInitialized, setIsInitialized] = useState(false);
const [error, setError] = useState<Error | null>(null);

useEffect(() => {
const initializeWorkspace = async () => {
try {
// TODO: ํ•„์š”ํ•œ ์ดˆ๊ธฐ ๋ฐ์ดํ„ฐ ๋กœ๋“œ
// ์˜ˆ์‹œ:
// await Promise.all([
// fetchUserSettings(),
// fetchInitialPages(),
// fetchWorkspaceData(),
// ]);

// ๊ฐœ๋ฐœ ์ค‘์—๋Š” ์ž„์‹œ๋กœ ๋”œ๋ ˆ์ด๋ฅผ ์ค˜์„œ ์Šคํ”Œ๋ž˜์‹œ ํ™”๋ฉด ํ™•์ธ
await new Promise((resolve) => setTimeout(resolve, 2000));

setIsInitialized(true);
} catch (err) {
setError(err instanceof Error ? err : new Error("Failed to initialize workspace"));
} finally {
// ํŽ˜์ด๋“œ ์•„์›ƒ ํšจ๊ณผ๋ฅผ ์œ„ํ•œ ์•ฝ๊ฐ„์˜ ๋”œ๋ ˆ์ด
setTimeout(() => {
setIsLoading(false);
}, 500);
}
};

initializeWorkspace();
}, []);

return { isLoading, isInitialized, error };
};

0 comments on commit 3f58bed

Please sign in to comment.