@@ -2,7 +2,13 @@ import { zodResolver } from "@hookform/resolvers/zod";
22import dayjs from "dayjs" ;
33import { useEffect , useState } from "react" ;
44import { useFieldArray , useForm } from "react-hook-form" ;
5- import { HiClipboardCheck , HiClipboardCopy , HiOutlineCheckCircle , HiOutlineExclamationCircle } from "react-icons/hi" ;
5+ import {
6+ HiClipboardCheck ,
7+ HiClipboardCopy ,
8+ HiInformationCircle ,
9+ HiOutlineCheckCircle ,
10+ HiOutlineExclamationCircle ,
11+ } from "react-icons/hi" ;
612import { NavLink , useNavigate , useParams } from "react-router" ;
713import type { z } from "zod" ;
814import { editReqSchema , projectReqSchema , projectResSchema } from "../../../common/schema" ;
@@ -36,24 +42,30 @@ export default function ProjectPage() {
3642 } | null > ( null ) ;
3743
3844 const [ copied , setCopied ] = useState ( false ) ;
45+ const [ isInfoExpanded , setIsInfoExpanded ] = useState ( ! eventId ) ; // 新規作成時は展開、編集時は折りたたみ
3946
4047 const {
4148 register,
4249 handleSubmit,
4350 control,
4451 reset,
52+ trigger,
4553 formState : { errors, isValid, isDirty } ,
4654 } = useForm < FormSchemaType > ( {
4755 resolver : zodResolver ( formSchema ) ,
4856 mode : "onChange" ,
4957 defaultValues : {
5058 name : "" ,
51- startDate : "" ,
52- endDate : "" ,
59+ startDate : eventId ? "" : dayjs ( ) . format ( "YYYY-MM-DD" ) ,
60+ endDate : eventId ? "" : dayjs ( ) . add ( 6 , "day" ) . format ( "YYYY-MM-DD" ) ,
5361 allowedRanges : [ { startTime : "00:00" , endTime : "23:45" } ] ,
5462 } ,
5563 } ) ;
5664
65+ const handleFieldFocus = ( ) => {
66+ trigger ( "name" ) ;
67+ } ;
68+
5769 const { fields, replace } = useFieldArray ( {
5870 control,
5971 name : "allowedRanges" ,
@@ -80,8 +92,8 @@ export default function ProjectPage() {
8092 setSubmitLoading ( true ) ;
8193
8294 // 日付をISO形式に変換
83- const startDateTime = new Date ( `${ data . startDate } T00:00:00.000Z ` ) . toISOString ( ) ;
84- const endDateTime = new Date ( `${ data . endDate } T23:59:59.999Z ` ) . toISOString ( ) ;
95+ const startDateTime = new Date ( `${ data . startDate } T00:00:00.000 ` ) . toISOString ( ) ;
96+ const endDateTime = new Date ( `${ data . endDate } T23:59:59.999 ` ) . toISOString ( ) ;
8597
8698 // range もISO形式に変換
8799 const rangeWithDateTime = data . allowedRanges ?. map ( ( range ) => ( {
@@ -184,13 +196,43 @@ export default function ProjectPage() {
184196 < input
185197 { ...register ( "name" ) }
186198 id = "input-name"
187- className = " input w-full text-base"
199+ className = { ` input w-full text-base ${ errors . name ? "input-error border-red-500" : "" } ` }
188200 placeholder = "イベント名"
201+ onBlur = { ( ) => trigger ( "name" ) }
189202 />
190- { errors . name && < p className = "text-red-500" > { errors . name . message } </ p > }
203+ { errors . name && < p className = "text-red-500 text-sm mt-1 " > { errors . name . message } </ p > }
191204 </ div >
192205 { ! project || ( project && project . guests . length === 0 ) ? (
193206 < >
207+ < div className = "collapse collapse-arrow bg-blue-50 border border-blue-200 mb-4" >
208+ < input
209+ type = "checkbox"
210+ checked = { isInfoExpanded }
211+ onChange = { ( e ) => setIsInfoExpanded ( e . target . checked ) }
212+ />
213+ < div className = "collapse-title text-sm font-medium text-primary flex items-center gap-2" >
214+ < HiInformationCircle className = "w-5 h-5" />
215+ 開始日・終了日/時間帯について
216+ </ div >
217+ < div className = "collapse-content text-sm text-primary" >
218+ < p >
219+ イツヒマでは、< strong > 主催者側で候補日程を設定せずに</ strong > 日程調整します。
220+ < br />
221+ ここでは、参加者の日程を知りたい日付の範囲と時間帯の範囲を設定してください。
222+ < br />
223+ 詳しくは、
224+ < a
225+ href = "https://utcode.notion.site/1e4ca5f557bc80f2b697ca7b9342dc89?pvs=4"
226+ target = "_blank"
227+ rel = "noreferrer noopener"
228+ className = "link"
229+ >
230+ 使い方ページ
231+ </ a >
232+ をご覧ください。
233+ </ p >
234+ </ div >
235+ </ div >
194236 < div className = "flex gap-2" >
195237 < div className = "flex-1" >
196238 < label htmlFor = "input-start" className = "text-sm text-gray-400" >
@@ -200,24 +242,31 @@ export default function ProjectPage() {
200242 type = "date"
201243 { ...register ( "startDate" ) }
202244 id = "input-start"
203- className = "input w-full text-base"
245+ className = { `input w-full text-base ${ errors . startDate ? "input-error border-red-500" : "" } ` }
246+ onFocus = { handleFieldFocus }
204247 />
205- { errors . startDate && < p className = "text-red-500" > { errors . startDate . message } </ p > }
248+ { errors . startDate && < p className = "text-red-500 text-sm mt-1 " > { errors . startDate . message } </ p > }
206249 </ div >
207250 < div className = "flex-1" >
208251 < label htmlFor = "input-end" className = "text-sm text-gray-400" >
209252 終了日
210253 </ label >
211- < input type = "date" { ...register ( "endDate" ) } id = "input-end" className = "input w-full text-base" />
212- { errors . endDate && < p className = "text-red-500" > { errors . endDate . message } </ p > }
254+ < input
255+ type = "date"
256+ { ...register ( "endDate" ) }
257+ id = "input-end"
258+ className = { `input w-full text-base ${ errors . endDate ? "input-error border-red-500" : "" } ` }
259+ onFocus = { handleFieldFocus }
260+ />
261+ { errors . endDate && < p className = "text-red-500 text-sm mt-1" > { errors . endDate . message } </ p > }
213262 </ div >
214263 </ div >
215264 < fieldset >
216265 < legend className = "text-sm text-gray-400" > 時間帯</ legend >
217266 < div className = "flex gap-2 items-center" >
218267 < div className = "flex-1 flex gap-1" >
219268 < select
220- className = " input flex-1 text-base"
269+ className = { ` input flex-1 text-base ${ errors . allowedRanges ? "input-error border-red-500" : "" } ` }
221270 value = { fields [ 0 ] . startTime . split ( ":" ) [ 0 ] }
222271 onChange = { ( e ) => {
223272 replace ( [
@@ -227,6 +276,7 @@ export default function ProjectPage() {
227276 } ,
228277 ] ) ;
229278 } }
279+ onFocus = { handleFieldFocus }
230280 >
231281 < option value = "" disabled >
232282 時
@@ -238,7 +288,7 @@ export default function ProjectPage() {
238288 ) ) }
239289 </ select >
240290 < select
241- className = " input flex-1 text-base"
291+ className = { ` input flex-1 text-base ${ errors . allowedRanges ? "input-error border-red-500" : "" } ` }
242292 value = { fields [ 0 ] . startTime . split ( ":" ) [ 1 ] }
243293 onChange = { ( e ) => {
244294 replace ( [
@@ -248,6 +298,7 @@ export default function ProjectPage() {
248298 } ,
249299 ] ) ;
250300 } }
301+ onFocus = { handleFieldFocus }
251302 >
252303 < option value = "" disabled >
253304 分
@@ -262,7 +313,7 @@ export default function ProjectPage() {
262313 < span > 〜</ span >
263314 < div className = "flex-1 flex gap-1" >
264315 < select
265- className = " input flex-1 text-base"
316+ className = { ` input flex-1 text-base ${ errors . allowedRanges ? "input-error border-red-500" : "" } ` }
266317 value = { fields [ 0 ] . endTime . split ( ":" ) [ 0 ] }
267318 onChange = { ( e ) => {
268319 replace ( [
@@ -272,6 +323,7 @@ export default function ProjectPage() {
272323 } ,
273324 ] ) ;
274325 } }
326+ onFocus = { handleFieldFocus }
275327 >
276328 < option value = "" disabled >
277329 時
@@ -283,7 +335,7 @@ export default function ProjectPage() {
283335 ) ) }
284336 </ select >
285337 < select
286- className = " input flex-1 text-base"
338+ className = { ` input flex-1 text-base ${ errors . allowedRanges ? "input-error border-red-500" : "" } ` }
287339 value = { fields [ 0 ] . endTime . split ( ":" ) [ 1 ] }
288340 onChange = { ( e ) => {
289341 replace ( [
@@ -293,6 +345,7 @@ export default function ProjectPage() {
293345 } ,
294346 ] ) ;
295347 } }
348+ onFocus = { handleFieldFocus }
296349 >
297350 < option value = "" disabled >
298351 分
@@ -306,7 +359,7 @@ export default function ProjectPage() {
306359 </ div >
307360 </ div >
308361 { errors . allowedRanges && typeof errors . allowedRanges ?. message === "string" && (
309- < p className = "text-red-500" > { errors . allowedRanges . message } </ p >
362+ < p className = "text-red-500 text-sm mt-1 " > { errors . allowedRanges . message } </ p >
310363 ) }
311364 </ fieldset >
312365 </ >
@@ -329,7 +382,7 @@ export default function ProjectPage() {
329382 if ( ! response . ok ) {
330383 throw new Error ( "削除に失敗しました。" ) ;
331384 }
332- navigate ( "/" ) ;
385+ navigate ( "/home " ) ;
333386 setToast ( {
334387 message : "イベントを削除しました。" ,
335388 variant : "success" ,
0 commit comments