Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
Expand Up @@ -15,7 +15,7 @@ type Props = {
totalNumber: number;
currentNumber: number;
isFoldFrontSide: boolean;
handleRegisterOrigami: () => void;
handleFinishFolding: () => void;
origamiDescription: string;
handleOrigamiDescriptionChange: (description: string) => void;
};
Expand All @@ -30,7 +30,7 @@ export const FoldMethodSelectPanel: React.FC<Props> = ({
totalNumber,
currentNumber,
isFoldFrontSide,
handleRegisterOrigami,
handleFinishFolding,
origamiDescription,
handleOrigamiDescriptionChange,
}) => {
Expand Down Expand Up @@ -85,11 +85,11 @@ export const FoldMethodSelectPanel: React.FC<Props> = ({
</div>
</div>
<Button
onClick={handleRegisterOrigami}
onClick={handleFinishFolding}
className={styles.registerButton}
size="3"
>
折り紙を登録
公開設定へ→
</Button>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
@use "@/styles/variables" as *;

.container {
display: flex;
flex-direction: column;
gap: 2.5rem;
align-items: start;
width: 100%;

.title {
font-size: 1.5rem;
font-weight: bold;
}
.h3Section {
width: 100%;
display: flex;
flex-direction: column;
align-items: start;
gap: 1rem;

.h3 {
font-size: 1.25rem;
font-weight: bold;
}

.requiredMessage {
color: red;
font-size: 0.875rem;
}
}

.pickerContainer {
display: flex;
gap: 0.5rem;
align-items: center;
border: solid 1px #c7c7c7;
padding: 0.25rem;
border-radius: 0.25rem;
width: 100%;

.picker {
width: 1.5rem;
height: 1.5rem;
cursor: pointer;
}
}

.descriptions {
display: flex;
flex-direction: column;
gap: 1rem;
width: 100%;

.gif {
border: solid 1px #c7c7c7;
}
}

.buttons {
display: flex;
flex-direction: column;
width: 100%;
justify-content: center;
align-items: center;
gap: 1rem;

.button {
position: relative;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 0.75rem 1rem 1rem 1rem;
border-radius: 0.5rem;
border: solid 2px #000;
font-weight: bold;
width: 100%;
background-color: #fff;
color: #000;

&:hover {
background-color: $hover-color;
}
}

.active {
border: solid 2px $primary-color;
color: $primary-color;
}

.registerButton {
position: relative;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 0.75rem 1rem 1rem 1rem;
border-radius: 0.5rem;
font-weight: bold;
width: 100%;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import styles from "./index.module.scss";
import { Button, TextField } from "@radix-ui/themes";

type Props = {
handlePrevStep: () => void;
handleNextStep: () => void;
handleRegisterOrigami: () => void;
name: string;
handleNameChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
color: string;
handleColorChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
};

export const PreviewPanel: React.FC<Props> = ({
name,
color,
handleColorChange,
handleNameChange,
//handleRegisterOrigami,
}) => {
return (
<div className={styles.container}>
<h2 className={styles.title}>折り紙を公開する</h2>
<section className={styles.h3Section}>
<h3 className={styles.h3}>
折り紙の名前をつけましょう
<span className={styles.requiredMessage}>※必須</span>
</h3>
<div className={styles.descriptions}>
<TextField.Root
placeholder="つる"
value={name}
onChange={handleNameChange}
/>
</div>
</section>
<section className={styles.h3Section}>
<h3 className={styles.h3}>折り紙の色を変更できます</h3>
<div className={styles.pickerContainer}>
<input
type="color"
className={styles.picker}
value={color}
onChange={handleColorChange}
/>
<div>{color}</div>
</div>
</section>
<section className={styles.h3Section}>
<h3 className={styles.h3}>折り方に間違いがないか確認してください</h3>
</section>
{/* <div className={styles.descriptions}>
<p></p>
<Image
src="/assets/step2.gif"
alt="動画:カーソルが動いて、折り紙の折る側の面を選択している。"
width={255}
height={255}
className={styles.gif}
/>
</div> */}
<div className={styles.buttons}>
<Button
className={styles.button}
onClick={() => console.log("未実装:戻る")}
>
修正する
</Button>
<Button
className={styles.registerButton}
onClick={() => console.log("未実装:手順確定")}
>
手順を確定する
</Button>
</div>
</div>
);
};
85 changes: 56 additions & 29 deletions src/components/OrigamiPost/FoldMethodControlPanel/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { FoldTargetSelectPanel } from "./FoldTargetSelectPanel";
import { FoldMethodSelectPanel } from "./FoldMethodSelectPanel";
import { FoldStepSegmentedControl } from "./ui/FoldStepSegmentedControl";
import React from "react";
import { PreviewPanel } from "./PreviewPanel";

export type Step = "axis" | "target" | "fold";

Expand All @@ -29,6 +30,12 @@ type Props = {
inputStepLength: number;
procedureIndex: number;
handleChangeStep: (step: number) => void;
handleFinishFolding: () => void;
isFinishFolding: boolean;
name: string;
handleNameChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
color: string;
handleColorChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
};

export const FoldMethodControlPanel: React.FC<Props> = ({
Expand All @@ -51,41 +58,61 @@ export const FoldMethodControlPanel: React.FC<Props> = ({
inputStepLength,
procedureIndex,
handleChangeStep,
handleFinishFolding,
isFinishFolding,
name,
handleNameChange,
color,
handleColorChange,
}) => {
return (
<section className={styles.container}>
{currentStep === "axis" && (
<AxisSelectPanel handleNextStep={handleDecideRotateAxis} />
)}
{currentStep === "target" && (
<FoldTargetSelectPanel
handlePrevStep={handleCancelRotateAxis}
handleNextStep={handleDecideFoldTarget}
/>
)}
{currentStep === "fold" && (
<FoldMethodSelectPanel
handlePrevStep={handleCancelFoldTarget}
handleFoldFrontSide={handleFoldFrontSide}
handleFoldBackSide={handleFoldBackSide}
foldAngle={foldAngle}
handleFoldAngleChange={handleFoldingAngleChange}
handleNextStep={handleDecideFoldMethod}
totalNumber={totalNumber}
currentNumber={currentNumber}
isFoldFrontSide={isFoldFrontSide}
{!isFinishFolding ? (
<>
{currentStep === "axis" && (
<AxisSelectPanel handleNextStep={handleDecideRotateAxis} />
)}
{currentStep === "target" && (
<FoldTargetSelectPanel
handlePrevStep={handleCancelRotateAxis}
handleNextStep={handleDecideFoldTarget}
/>
)}
{currentStep === "fold" && (
<FoldMethodSelectPanel
handlePrevStep={handleCancelFoldTarget}
handleFoldFrontSide={handleFoldFrontSide}
handleFoldBackSide={handleFoldBackSide}
foldAngle={foldAngle}
handleFoldAngleChange={handleFoldingAngleChange}
handleNextStep={handleDecideFoldMethod}
totalNumber={totalNumber}
currentNumber={currentNumber}
isFoldFrontSide={isFoldFrontSide}
handleFinishFolding={handleFinishFolding}
origamiDescription={origamiDescription}
handleOrigamiDescriptionChange={handleOrigamiDescriptionChange}
/>
)}
<div className={styles.segmentedControl}>
<FoldStepSegmentedControl
procedureLength={inputStepLength}
currentStep={procedureIndex}
handleChangeStep={handleChangeStep}
/>
</div>
</>
) : (
<PreviewPanel
handlePrevStep={() => console.log("未実装")}
handleNextStep={() => console.log("未実装")}
handleRegisterOrigami={handleRegisterOrigami}
origamiDescription={origamiDescription}
handleOrigamiDescriptionChange={handleOrigamiDescriptionChange}
name={name}
handleNameChange={handleNameChange}
color={color}
handleColorChange={handleColorChange}
/>
)}
<div className={styles.segmentedControl}>
<FoldStepSegmentedControl
procedureLength={inputStepLength}
currentStep={procedureIndex}
handleChangeStep={handleChangeStep}
/>
</div>
</section>
);
};
29 changes: 23 additions & 6 deletions src/components/OrigamiPost/hooks/useRegisterOrigami/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ type UseRegisterOrigami = (props: {
cameraRef: React.MutableRefObject<THREE.PerspectiveCamera | null>;
rendererRef: React.MutableRefObject<THREE.WebGLRenderer | null>;
}) => {
handleDecideProcedure: () => Model | undefined;
handleRegisterOrigami: () => void;
};

Expand All @@ -39,14 +40,10 @@ export const useRegisterOrigami: UseRegisterOrigami = ({
const isMoveBoardsRight = step.isMoveBoardsRight;
const description = step.description;

const handleRegisterOrigami = () => {
//折り面、折り線、タイトルがない場合は登録できない
const handleDecideProcedure = () => {
//折り面、折り線がない場合は登録できない
if (!moveBoards.length) return;
if (!rotateAxis.length) return;
if (!origamiName.length) {
console.error("Origami name is required.");
return;
}

// xy平面上の板のうち、z座標が大きい順に、numberOfMoveBoards枚を折る
// それ以外の板は無条件で折る
Expand All @@ -64,6 +61,10 @@ export const useRegisterOrigami: UseRegisterOrigami = ({
// TODO: ProcedureとinputStepObjectの整合性を取る
// 現在はnewProcedureだけが入っているが、それまでの手順は入っていない
const procedures = { [procedureIndex]: newProcedure };
if (!procedures) {
console.error("Procedure is null.");
return;
}

// idとimageUrlはDBから取得するため、空文字を設定
const model: Model = {
Expand All @@ -74,6 +75,21 @@ export const useRegisterOrigami: UseRegisterOrigami = ({
procedure: procedures,
};

return model;
};

const handleRegisterOrigami = () => {
// タイトル、折り紙モデルがない場合は登録できない。
if (!origamiName.length) {
console.error("Origami name is required.");
return;
}
const model = handleDecideProcedure();
if (!model) {
console.error("Failed to decide procedure.");
return;
}

const scene = sceneRef.current;
const camera = cameraRef.current;
const renderer = rendererRef.current;
Expand All @@ -100,5 +116,6 @@ export const useRegisterOrigami: UseRegisterOrigami = ({

return {
handleRegisterOrigami,
handleDecideProcedure,
};
};
Loading