Skip to content
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

同じ目標を複製する機能を作成 #127

Merged
merged 2 commits into from
Dec 20, 2024
Merged
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
3 changes: 1 addition & 2 deletions src/Components/DeleteGoalModal/DeleteGoalModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,8 @@ export default function DeleteGoalModal({ goalId }: { goalId: string }) {
return (
<>
<DeleteOutlineIcon
style={{ fontSize: "23px" }}
onClick={() => setOpen(true)}
sx={{ cursor: "pointer" }}
sx={{ cursor: "pointer", fontSize: "23px" }}
/>

<Modal
Expand Down
34 changes: 34 additions & 0 deletions src/Components/GoalModal/CopyGoalAfterPostButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { Add } from "@mui/icons-material";
import { Button } from "@mui/joy";
import { useState } from "react";
import CreateGoalModal from "./CreateGoalModal";

export default function CopyGoalAfterPostButton({
goalText,
deadline,
}: {
goalText: string;
deadline: string;
}) {
const [open, setOpen] = useState(false);

return (
<>
<Button
variant="solid"
color="success"
startDecorator={<Add />}
onClick={() => setOpen(true)}
>
この目標を次の日も達成する
</Button>

<CreateGoalModal
open={open}
setOpen={setOpen}
defaultText={goalText}
defaultDeadline={deadline}
/>
</>
);
}
29 changes: 29 additions & 0 deletions src/Components/GoalModal/CopyGoalButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import LibraryAddOutlinedIcon from "@mui/icons-material/LibraryAddOutlined";
import { useState } from "react";
import CreateGoalModal from "./CreateGoalModal";

export default function CopyModalButton({
deadline,
goalText,
}: {
deadline: string;
goalText: string;
}) {
const [open, setOpen] = useState(false);

return (
<>
<LibraryAddOutlinedIcon
onClick={() => setOpen(true)}
sx={{ cursor: "pointer", fontSize: "23px" }}
/>

<CreateGoalModal
open={open}
setOpen={setOpen}
defaultText={goalText}
defaultDeadline={deadline}
/>
</>
);
}
159 changes: 159 additions & 0 deletions src/Components/GoalModal/CreateGoalModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
"use client";
import { showSnackBar } from "@/Components/SnackBar/SnackBar";
import { Goal } from "@/types/types";
import { createGoal, handleCreateGoalError } from "@/utils/API/Goal/createGoal";
import { useUser } from "@/utils/UserContext";
import SendIcon from "@mui/icons-material/Send";
import {
Button,
DialogContent,
DialogTitle,
Input,
Modal,
ModalDialog,
Stack,
Typography,
} from "@mui/joy";
import React, { useEffect, useState } from "react";

export default function CreateGoalModal({
open,
setOpen,
defaultText,
defaultDeadline,
}: {
open: boolean;
setOpen: React.Dispatch<React.SetStateAction<boolean>>;
defaultText?: string;
defaultDeadline?: string;
}) {
const [text, setText] = useState("");
const [dueDate, setDueDate] = useState("");

const { user } = useUser();

useEffect(() => {
if (defaultText) {
setText(defaultText);
}
if (defaultDeadline) {
const convertedDate = new Date(defaultDeadline);
const localDate = new Date(
convertedDate.getTime() - convertedDate.getTimezoneOffset() * 60000
);
localDate.setDate(localDate.getDate() + 1); // 1日後にする
setDueDate(localDate.toISOString().slice(0, 16));
}
}, [defaultText, defaultDeadline]);

const handleSubmit = async (event: React.FormEvent) => {
event.preventDefault();

// 過去の時間が入力されている場合
if (new Date(dueDate).getTime() < Date.now()) {
showSnackBar({
message: "過去の時間を指定することはできません",
type: "warning",
});
return;
}

const postData: Goal = {
userId: user?.userId as string,
text: text,
deadline: new Date(dueDate),
};

try {
const data = await createGoal(postData);
console.log("Success:", data);

showSnackBar({
message: "目標を作成しました",
type: "success",
});

setText("");
setDueDate("");
setOpen(false);
} catch (error: unknown) {
console.error("Error creating goal:", error);
const message = handleCreateGoalError(error);
showSnackBar({
message,
type: "warning",
});
}
};

// 以下のJoy UIによるエラーを無効化
// Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release. Error Component Stack
try {
const consoleError = console.error;
console.error = (...args) => {
if (args[0]?.includes("Accessing element.ref was removed")) {
return;
}
consoleError(...args);
};
} catch {
console.error("Failed to disable Joy UI error");
}

return (
<Modal
open={open}
onClose={() => setOpen(false)}
keepMounted
disablePortal={false}
>
<ModalDialog
aria-labelledby="create-goal-title"
aria-describedby="create-goal-description"
sx={{ width: "90%", maxWidth: 400 }}
>
<DialogTitle>目標を作成</DialogTitle>
<DialogContent>達成したい内容と期限を入力してください</DialogContent>
<form onSubmit={handleSubmit}>
<Stack spacing={2}>
<Input
placeholder="Goal Title"
value={text}
onChange={(e) => setText(e.target.value)}
required
/>
<Input
type="datetime-local"
value={dueDate}
onChange={(e) => setDueDate(e.target.value)}
required
/>
<Typography color="danger">
期限が1時間以内の目標は削除できなくなります
</Typography>
<Stack direction="row" spacing={1} justifyContent="flex-end">
<Button
variant="plain"
color="neutral"
onClick={() => setOpen(false)}
>
キャンセル
</Button>
<Button
type="submit"
variant="solid"
color="primary"
disabled={
!user || user?.loginType === "Guest" || !user?.isMailVerified
}
endDecorator={<SendIcon />}
>
作成
</Button>
</Stack>
</Stack>
</form>
</ModalDialog>
</Modal>
);
}
Loading
Loading