Skip to content
Open
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
12 changes: 11 additions & 1 deletion __tests__/unit/validateTask.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ describe('タスク追加バリデーション', () => {
taskId: '01G6NM6EJ7C35J6ZHF6Z3CHGVK',
parentTaskId: null,
taskName: 'タスク名',
startDate: '2022-09-20',
dueDate: '2222-06-29',
assignLabelIdList: [],
status: false,
}

Expand All @@ -20,7 +22,9 @@ describe('タスク追加バリデーション', () => {
taskId: '1',
parentTaskId: null,
taskName: 'タスク名',
startDate: '2022-09-20',
dueDate: '2222-06-29',
assignLabelIdList: [],
status: false,
}

Expand All @@ -33,7 +37,9 @@ describe('タスク追加バリデーション', () => {
taskId: '01G6NM6EJ7C35J6ZHF6Z3CHGVK',
parentTaskId: null,
taskName: '',
startDate: '2022-09-20',
dueDate: '2222-06-29',
assignLabelIdList: [],
status: false,
}
const err_msg = validateTask(task)
Expand All @@ -45,7 +51,9 @@ describe('タスク追加バリデーション', () => {
taskId: '01G6NM6EJ7C35J6ZHF6Z3CHGVK',
parentTaskId: null,
taskName: 'タスク名',
dueDate: '2222-06-29--------',
startDate: '2022-09-20',
dueDate: '2222-06-29-----------------',
assignLabelIdList: [],
status: false,
}
const err_msg = validateTask(task)
Expand All @@ -57,7 +65,9 @@ describe('タスク追加バリデーション', () => {
taskId: '01G6NM6EJ7C35J6ZHF6Z3CHGVK',
parentTaskId: null,
taskName: 'タスク名',
startDate: '2022-09-20',
dueDate: '2000-06-29',
assignLabelIdList: [],
status: false,
}
const err_msg = validateTask(task)
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"next": "12.1.5",
"react": "18.1.0",
"react-dom": "18.1.0",
"react-draggable": "^4.4.5",
"react-error-boundary": "3.1.4",
"react-redux": "^8.0.2",
"ulid": "^2.3.0"
Expand Down
49 changes: 38 additions & 11 deletions pages/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { useEffect, FC, ChangeEvent, useState } from 'react'
import { useEffect, FC, useState } from 'react'
import { useDispatch } from 'react-redux'
import { Button } from '@mantine/core'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faCalendar } from '@fortawesome/free-solid-svg-icons'
import { setTaskList } from '../src/stores/TaskListSlice'
import { setLabelList } from '../src/stores/LabelListSlice'
import {
Expand All @@ -11,10 +14,12 @@ import TaskAdd from '../src/components/TaskAdd'
import TaskClear from '../src/components/TaskClear'
import TaskList from '../src/components/TaskList'
import LabelAdd from '../src/components/LabelAdd'
import { TaskCalenderList } from '../src/components/TaskCalenderList'

const Index: FC<void> = () => {
const [searchString, setSearchString] = useState('')
const dispatch = useDispatch()
const [isCalenderView, setIsCalenderView] = useState<boolean>(false)

useEffect(() => {
const loadedTaskList = getAllTaskListFromLocalStorage()
Expand All @@ -37,18 +42,40 @@ const Index: FC<void> = () => {
</div>
</div>

<form className="sm:ml-5">
<input
type="text"
className=" w-80 my-8 rounded-lg border-2 border-black"
placeholder="search"
onChange={(e) => setSearchString(e.target.value)}
/>
</form>
<div className="flex mt-8">
{/** switch calender */}
<Button
variant="outline"
color="dark"
radius="md"
size="md"
className="w-60 border-2 p-2 mr-4 text-center"
onClick={() => {
setIsCalenderView(!isCalenderView)
}}
>
<FontAwesomeIcon icon={faCalendar} className="m-1" />
{isCalenderView ? 'リスト' : 'カレンダー'}表示に切り替え
</Button>

{/** Search */}
<form className="sm:ml-5">
<input
type="text"
className="w-80 rounded-lg border-2 border-black"
placeholder="search"
onChange={(e) => setSearchString(e.target.value)}
/>
</form>
</div>
</div>

<div className=" mx-8 mt-8">
<TaskList parentTaskId={null} depth={0} searchString={searchString} />
<div className="mx-8 mt-8">
{isCalenderView ? (
<TaskCalenderList />
) : (
<TaskList parentTaskId={null} depth={0} searchString={searchString} />
)}
</div>

<LabelAdd />
Expand Down
20 changes: 16 additions & 4 deletions src/components/ChildrenTaskAdd.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ const ChildrenTaskAdd: FC<TaskAddParameters> = (props) => {
// local
const [opened, setOpened] = useState(false)
const [inputTaskName, setInputTaskName] = useState('')
const [inputDate, setInputDate] = useState(new Date())
const [inputStartDate, setInputStartDate] = useState(new Date())
const [inputDueDate, setInputDueDate] = useState(new Date())
const dispatch = useDispatch()

const addTaskLocal = (e: FormEvent<HTMLFormElement>) => {
Expand All @@ -29,7 +30,8 @@ const ChildrenTaskAdd: FC<TaskAddParameters> = (props) => {
taskId: ulid(),
parentTaskId: props.parentTaskId,
taskName: inputTaskName,
dueDate: dayjs(inputDate).format(DateFormat),
startDate: dayjs(inputStartDate).format(DateFormat),
dueDate: dayjs(inputDueDate).format(DateFormat),
status: false,
assignLabelIdList: [],
}
Expand Down Expand Up @@ -92,13 +94,23 @@ const ChildrenTaskAdd: FC<TaskAddParameters> = (props) => {
onChange={(e) => setInputTaskName(e.target.value)}
/>

<DatePicker
placeholder="締切日を選択してください"
label="開始日"
required
value={inputStartDate}
onChange={(e) =>
e == null ? setInputStartDate(new Date()) : setInputStartDate(e)
}
/>

<DatePicker
placeholder="締切日を選択してください"
label="締切日"
required
value={inputDate}
value={inputDueDate}
onChange={(e) =>
e == null ? setInputDate(new Date()) : setInputDate(e)
e == null ? setInputDueDate(new Date()) : setInputDueDate(e)
}
/>

Expand Down
21 changes: 17 additions & 4 deletions src/components/TaskAdd.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ const TaskAdd: FC<TaskAddParameters> = (props) => {
// local
const [opened, setOpened] = useState(false)
const [inputTaskName, setInputTaskName] = useState('')
const [inputDate, setInputDate] = useState(new Date())
const [inputStartDate, setInputStartDate] = useState(new Date())
const [inputDueDate, setInputDueDate] = useState(new Date())
const dispatch = useDispatch()

const addTaskLocal = (e: FormEvent<HTMLFormElement>) => {
Expand All @@ -28,10 +29,12 @@ const TaskAdd: FC<TaskAddParameters> = (props) => {
taskId: ulid(),
parentTaskId: props.parentTaskId,
taskName: inputTaskName,
dueDate: dayjs(inputDate).format(DateFormat),
startDate: dayjs(inputStartDate).format(DateFormat),
dueDate: dayjs(inputDueDate).format(DateFormat),
status: false,
assignLabelIdList: [],
}
console.warn(newTask)
const err_msg = validateTask(newTask)
if (err_msg) {
showNotification({
Expand Down Expand Up @@ -93,13 +96,23 @@ const TaskAdd: FC<TaskAddParameters> = (props) => {
onChange={(e) => setInputTaskName(e.target.value)}
/>

<DatePicker
placeholder="開始日を選択してください"
label="開始日"
required
value={inputStartDate}
onChange={(e) =>
e == null ? setInputStartDate(new Date()) : setInputStartDate(e)
}
/>

<DatePicker
placeholder="締切日を選択してください"
label="締切日"
required
value={inputDate}
value={inputDueDate}
onChange={(e) =>
e == null ? setInputDate(new Date()) : setInputDate(e)
e == null ? setInputDueDate(new Date()) : setInputDueDate(e)
}
/>

Expand Down
148 changes: 148 additions & 0 deletions src/components/TaskCalenderList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import { FC, useState, useRef, useEffect } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { RootState } from '../stores/store'
import dayjs from 'dayjs'
import Draggable from 'react-draggable'
import { showNotification } from '@mantine/notifications'
import { updateTask } from '../stores/TaskListSlice'
import type { Task } from '../types/Task'
import { DateFormat, validateTask } from '../functions/Task'

export const TaskCalenderList: FC = () => {
const taskListSelector = useSelector((state: RootState) => state.taskList)

const dateLength = 100
const dateArray = new Array(dateLength)
.fill('')
.map((_, i) => dayjs().add(i, 'day'))

return (
<div className="overflow-x-scroll">
<div className="flex">
{dateArray.map((date, index) => (
<div
key={index}
className="flex-shrink-0 w-4 m-2 text-xl text-center"
>
{date.get('date') === 1 ? <b>{date.get('month') + 1}</b> : ''}
</div>
))}
</div>
<div className="flex">
{dateArray.map((date, index) => (
<div
key={index}
className={`flex-shrink-0 w-4 m-2 text-xl text-center ${
[0, 6].includes(date.get('day')) ? 'text-red-500' : ''
}`}
>
<span>{date.get('date')}</span>
</div>
))}
</div>
{taskListSelector.taskList.map((task) => (
<CalenderListTask key={task.taskId} task={task} />
))}
</div>
)
}

type Props = {
task: Task
}

const CalenderListTask: FC<Props> = ({ task }) => {
const CALEMDER_DATE_WIDTH = 32
const [startX, setStartX] = useState(0)
const [marginLeft, setMarginLeft] = useState(0)
const nodeRef = useRef(null)

useEffect(() => {
const newMarginLeft =
Math.max(dayjs(task.startDate).diff(dayjs(new Date()), 'day') + 1, 0) *
CALEMDER_DATE_WIDTH
setMarginLeft(newMarginLeft)
}, [task.startDate])

const handleStart = (e: any) => {
setStartX(e.screenX)
}
const handleStop = (e: any) => {
const diffDays = (e.screenX - startX) / CALEMDER_DATE_WIDTH
updateTaskLocal(diffDays)
}

const dispatch = useDispatch()

const updateTaskLocal = (diffDays: number) => {
const newStartDate = dayjs(task.startDate)
.add(diffDays, 'day')
.format(DateFormat)
const newDueDate = dayjs(task.dueDate)
.add(diffDays, 'day')
.format(DateFormat)
const newTask: Task = {
...task,
startDate: newStartDate,
dueDate: newDueDate,
}

const msg = validateTask(newTask)
if (msg) {
showNotification({
title: 'タスクの編集に失敗しました',
message: msg,
autoClose: 5000,
color: 'red',
})
return
}

dispatch(updateTask(newTask))
showNotification({
message: 'タスクの編集に成功しました',
autoClose: 5000,
color: 'green',
})
}

return (
<Draggable
axis={'x'}
grid={[CALEMDER_DATE_WIDTH, 0]}
onStart={(e: any) => {
handleStart(e)
}}
defaultPosition={{ x: 0, y: 0 }}
position={{ x: 0, y: 0 }}
onStop={(e: any) => {
handleStop(e)
}}
nodeRef={nodeRef}
>
<div
ref={nodeRef}
className="bg-task border mt-2 p-2 rounded-xl cursor-pointer shadow-md hover:shadow-inner hover:opacity-90"
style={{
marginLeft: `${marginLeft}px`,
width: `${
(dayjs(task.dueDate).diff(dayjs(task.startDate), 'day') + 1) *
CALEMDER_DATE_WIDTH
}px`,
}}
>
<div>
{dayjs(task.dueDate).diff(dayjs(task.startDate), 'day') + 1 <= 3
? `${task.startDate.substring(5, 10)} ~ ${task.dueDate.substring(
5,
10
)}`
: `${task.startDate} ~ ${task.dueDate}`}
</div>
<div>
<b>{task.taskName}</b>
</div>
</div>
</Draggable>
)
}
2 changes: 1 addition & 1 deletion src/components/TaskListTask.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ const TaskListTask: FC<TaskListTaskProps> = (props) => {
</div>
<div>
<span className="font-light text-s pr-5">
締め切り: {props.task.dueDate}
開始:{props.task.startDate} ~ 締め切り:{props.task.dueDate}
</span>
</div>
</div>
Expand Down
Loading