Skip to content

Commit

Permalink
Feat: Tutorial 및 Block Tab Menu 생성
Browse files Browse the repository at this point in the history
Feat: Tutorial 및 Block Tab Menu 생성
  • Loading branch information
whoisrey authored Aug 25, 2024
2 parents 1587ad5 + 1fcfd04 commit 50967f6
Show file tree
Hide file tree
Showing 10 changed files with 295 additions and 9 deletions.
14 changes: 14 additions & 0 deletions src/assets/tutorial/01.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions src/assets/tutorial/02.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 15 additions & 0 deletions src/assets/tutorial/03.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 15 additions & 0 deletions src/assets/tutorial/04.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 15 additions & 0 deletions src/assets/tutorial/05.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
59 changes: 52 additions & 7 deletions src/components/BlockContainer.jsx
Original file line number Diff line number Diff line change
@@ -1,47 +1,92 @@
import { useState, useEffect } from "react";

import useStore from "../store";

import InputBlock from "./common/InputBlock";
import MethodBlock from "./common/MethodBlock";

import { fetchBlocks } from "../services/blocks";

import {
Content,
Tab,
TabList,
BlockList,
InputBlockList,
MethodBlockList,
} from "../style/BlockContainerStyle";
import { Header, Section, Content } from "../style/CommonStyle";
import { Header, Section } from "../style/CommonStyle";

const BlockContainer = () => {
const { handleBlockDragStart, handleBlockDragOver, handleDeleteBlock } =
useStore();
const [inputBlocks, setInputBlocks] = useState([]);
const [methodBlocks, setMethodBlocks] = useState([]);
const [activeTab, setActiveTab] = useState("All");
const [actions, setActions] = useState(["All"]);

useEffect(() => {
const renderBlocks = async () => {
try {
const blocks = await fetchBlocks();

setInputBlocks(blocks.inputBlocks);
setMethodBlocks(blocks.methodBlocks);

const allActions = new Set(["All"]);

const updateAction = (allBlocks) => {
allBlocks.forEach((block) =>
block.actions.forEach((action) => allActions.add(action)),
);
};

[blocks.inputBlocks, blocks.methodBlocks].forEach(updateAction);

setActions([...allActions]);
} catch (error) {
console.error("Fetch Error");
}
};
renderBlocks();
}, []);

const filterBlocksByAction = (blocks, action) => {
return blocks.filter((block) => block.actions.includes(action));
};

const filterBlocks = (action) => {
if (action === "All") {
return { inputBlocks, methodBlocks };
}

return {
inputBlocks: filterBlocksByAction(inputBlocks, action),
methodBlocks: filterBlocksByAction(methodBlocks, action),
};
};

const {
inputBlocks: filteredInputBlocks,
methodBlocks: filteredMethodBlocks,
} = filterBlocks(activeTab);

return (
<Section onDragOver={handleBlockDragOver} onDrop={handleDeleteBlock}>
<Header>
<h2>Block Container</h2>
</Header>
<Content>
<TabList>
{actions.map((action) => (
<Tab
key={action}
data-active={activeTab === action}
onClick={() => setActiveTab(action)}
>
{action}
</Tab>
))}
</TabList>
<BlockList>
<InputBlockList>
{inputBlocks.map((inputBlock) => (
{filteredInputBlocks.map((inputBlock) => (
<InputBlock
key={inputBlock._id}
parameter={inputBlock.parameter}
Expand All @@ -50,7 +95,7 @@ const BlockContainer = () => {
))}
</InputBlockList>
<MethodBlockList>
{methodBlocks.map((methodBlock) => (
{filteredMethodBlocks.map((methodBlock) => (
<MethodBlock
key={methodBlock._id}
method={methodBlock.method}
Expand Down
67 changes: 67 additions & 0 deletions src/components/common/Tutorial.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { useState } from "react";

import Button from "./Button";

import {
ModalBackground,
ModalContainer,
ModalContent,
} from "../../style/ModalStyle";
import { Header, ButtonContainer } from "../../style/CommonStyle";
import { ImageContainer, ContentContainer } from "../../style/TutorialStyle";

const TutorialModal = ({ title, tutorials, onClose }) => {
const [currentIndex, setCurrentIndex] = useState(0);

const handleNextButton = () => {
if (currentIndex < tutorials.length - 1) {
setCurrentIndex(currentIndex + 1);
} else {
onClose();
}
};

const handlePreviousButton = () => {
if (currentIndex > 0) {
setCurrentIndex(currentIndex - 1);
}
};

const currentTutorial = tutorials[currentIndex];

return (
<ModalBackground>
<ModalContainer>
<Header>
<h2>{title}</h2>
</Header>
<ModalContent>
<ImageContainer>
<img
src={currentTutorial.image}
alt={`Tutorial step ${currentIndex + 1}`}
/>
</ImageContainer>
<ContentContainer>
{currentTutorial.content.split(".").join(".\n")}
</ContentContainer>
<ButtonContainer>
<Button
type="text"
text="prev"
handleClick={handlePreviousButton}
disabled={currentIndex === 0}
/>
<Button
type="text"
text={currentIndex === tutorials.length - 1 ? "start" : "next"}
handleClick={handleNextButton}
/>
</ButtonContainer>
</ModalContent>
</ModalContainer>
</ModalBackground>
);
};

export default TutorialModal;
39 changes: 39 additions & 0 deletions src/pages/Main.jsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,56 @@
import { useState } from "react";

import useStore from "../store";

import BlockContainer from "../components/BlockContainer";
import BlockDashboard from "../components/BlockDashboard";
import TestCodeDashboard from "../components/TestCodeDashboard";
import Tutorial from "../components/common/Tutorial";

import firstStep from "../assets/tutorial/01.svg";
import secondStep from "../assets/tutorial/02.svg";
import thirdStep from "../assets/tutorial/03.svg";
import fourthStep from "../assets/tutorial/04.svg";
import fifthStep from "../assets/tutorial/05.svg";

const Main = () => {
const { handleKeyDown } = useStore();
const [showTutorial, setShowTutorial] = useState(true);

const tutorials = [
{
image: firstStep,
content:
"왼쪽의 회색 블록에는 사용자가 원하는 값을 입력할 수 있습니다.오른쪽의 남색 블록으로 사용자가 원하는 동작을 선택할 수 있습니다.",
},
{
image: secondStep,
content: "Block Dashboard로 블록을 드래그할 수 있습니다.",
},
{
image: thirdStep,
content:
"하나의 라인 블록에는 최소 하나의 남색 블록이 포함되어야 합니다.",
},
{ image: fourthStep, content: "reset 버튼을 누르면 블록이 초기화됩니다." },
{
image: fifthStep,
content: "create 버튼을 누르면 테스트 코드가 생성됩니다.",
},
];

return (
<main onKeyDown={handleKeyDown} tabIndex="0">
<BlockContainer />
<BlockDashboard />
<TestCodeDashboard />
{showTutorial && (
<Tutorial
title="Tutorial"
tutorials={tutorials}
onClose={() => setShowTutorial(false)}
/>
)}
</main>
);
};
Expand Down
51 changes: 49 additions & 2 deletions src/style/BlockContainerStyle.jsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,56 @@
import styled from "styled-components";

const Content = styled.div`
display: flex;
flex-direction: column;
align-items: center;
position: relative;
height: 100vh;
overflow: scroll;
overflow-x: auto;
`;

const TabList = styled.nav`
display: flex;
flex-direction: column;
position: absolute;
top: 0;
left: 0;
height: 100%;
padding: 2rem 0.5rem;
background-color: transparent;
gap: 2rem;
@media (max-width: 1120px) {
position: static;
top: unset;
left: unset;
}
`;

const Tab = styled.button`
border: none;
background: ${({ theme }) => theme.color.lightGrayColor};
color: ${({ theme, "data-active": active }) =>
active ? theme.color.whiteColor : theme.color.blackColor};
font-size: ${({ theme }) => theme.fontSize.xsmall};
text-align: left;
cursor: pointer;
&:hover {
background-color: ${({ theme }) => theme.color.grayColor};
}
&:focus {
outline: none;
}
`;

const BlockList = styled.ul`
display: flex;
flex-direction: column;
gap: 2rem;
margin: 4rem;
padding: 2rem;
`;

const InputBlockList = styled.ul`
Expand All @@ -18,4 +65,4 @@ const MethodBlockList = styled.ul`
gap: 1rem;
`;

export { BlockList, InputBlockList, MethodBlockList };
export { Content, Tab, TabList, BlockList, InputBlockList, MethodBlockList };
20 changes: 20 additions & 0 deletions src/style/TutorialStyle.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import styled from "styled-components";

const ImageContainer = styled.div`
display: flex;
gap: 4rem;
width: 50rem;
height: 20rem;
img {
width: 50rem;
}
`;

const ContentContainer = styled.pre`
display: flex;
line-height: 2rem;
font-weight: bold;
`;

export { ImageContainer, ContentContainer };

0 comments on commit 50967f6

Please sign in to comment.