diff --git a/app/Http/Controllers/EjaculationController.php b/app/Http/Controllers/EjaculationController.php index ef9bcd4..e062c21 100644 --- a/app/Http/Controllers/EjaculationController.php +++ b/app/Http/Controllers/EjaculationController.php @@ -23,6 +23,7 @@ class EjaculationController extends Controller $errors = $request->session()->get('errors'); $initialState = [ + 'mode' => 'create', 'fields' => [ 'date' => old('date') ?? $request->input('date', date('Y/m/d')), 'time' => old('time') ?? $request->input('time', date('H:i')), @@ -30,7 +31,8 @@ class EjaculationController extends Controller 'tags' => $tags, 'note' => old('note') ?? $request->input('note', ''), 'is_private' => old('is_private') ?? $request->input('is_private', 0) == 1, - 'is_too_sensitive' => old('is_too_sensitive') ?? $request->input('is_too_sensitive', 0) == 1 + 'is_too_sensitive' => old('is_too_sensitive') ?? $request->input('is_too_sensitive', 0) == 1, + 'is_realtime' => old('is_realtime', true) ], 'errors' => isset($errors) ? $errors->getMessages() : null ]; @@ -43,15 +45,20 @@ class EjaculationController extends Controller $inputs = $request->all(); $validator = Validator::make($inputs, [ - 'date' => 'required|date_format:Y/m/d', - 'time' => 'required|date_format:H:i', + 'date' => 'required_without:is_realtime|date_format:Y/m/d', + 'time' => 'required_without:is_realtime|date_format:H:i', 'note' => 'nullable|string|max:500', 'link' => 'nullable|url|max:2000', 'tags' => 'nullable|string', ])->after(function ($validator) use ($request, $inputs) { // 日時の重複チェック if (!$validator->errors()->hasAny(['date', 'time'])) { - $dt = $inputs['date'] . ' ' . $inputs['time']; + if (isset($inputs['date']) && isset($inputs['time'])) { + $dt = Carbon::createFromFormat('Y/m/d H:i', $inputs['date'] . ' ' . $inputs['time']); + } else { + $dt = now(); + } + $dt = $dt->startOfMinute(); if (Ejaculation::where(['user_id' => Auth::id(), 'ejaculated_date' => $dt])->count()) { $validator->errors()->add('datetime', '既にこの日時にチェックインしているため、登録できません。'); } @@ -59,13 +66,21 @@ class EjaculationController extends Controller }); if ($validator->fails()) { - return redirect()->route('checkin')->withErrors($validator)->withInput(); + return redirect()->route('checkin') + ->withErrors($validator) + ->withInput(array_merge(['is_realtime' => false], $request->input())); } $ejaculation = DB::transaction(function () use ($request, $inputs) { + if (isset($inputs['date']) && isset($inputs['time'])) { + $ejaculatedDate = Carbon::createFromFormat('Y/m/d H:i', $inputs['date'] . ' ' . $inputs['time']); + } else { + $ejaculatedDate = now(); + } + $ejaculatedDate = $ejaculatedDate->startOfMinute(); $ejaculation = Ejaculation::create([ 'user_id' => Auth::id(), - 'ejaculated_date' => Carbon::createFromFormat('Y/m/d H:i', $inputs['date'] . ' ' . $inputs['time']), + 'ejaculated_date' => $ejaculatedDate, 'note' => $inputs['note'] ?? '', 'link' => $inputs['link'] ?? '', 'source' => Ejaculation::SOURCE_WEB, @@ -138,6 +153,7 @@ class EjaculationController extends Controller $errors = $request->session()->get('errors'); $initialState = [ + 'mode' => 'update', 'fields' => [ 'date' => old('date') ?? $ejaculation->ejaculated_date->format('Y/m/d'), 'time' => old('time') ?? $ejaculation->ejaculated_date->format('H:i'), diff --git a/resources/assets/js/components/CheckinForm.tsx b/resources/assets/js/components/CheckinForm.tsx index fec11be..c03f1bd 100644 --- a/resources/assets/js/components/CheckinForm.tsx +++ b/resources/assets/js/components/CheckinForm.tsx @@ -1,5 +1,6 @@ -import React, { useState } from 'react'; +import React, { useState, useEffect } from 'react'; import classNames from 'classnames'; +import { format } from 'date-fns'; import { CheckBox } from './CheckBox'; import { FieldError, StandaloneFieldError } from './FieldError'; import { TagInput } from './TagInput'; @@ -10,18 +11,42 @@ type CheckinFormProps = { }; export const CheckinForm: React.FC = ({ initialState }) => { + const mode = initialState.mode; const [date, setDate] = useState(initialState.fields.date || ''); const [time, setTime] = useState(initialState.fields.time || ''); const [tags, setTags] = useState(initialState.fields.tags || []); const [link, setLink] = useState(initialState.fields.link || ''); const [linkForPreview, setLinkForPreview] = useState(link); const [note, setNote] = useState(initialState.fields.note || ''); + const [isRealtime, setRealtime] = useState(mode === 'create' && initialState.fields.is_realtime); const [isPrivate, setPrivate] = useState(!!initialState.fields.is_private); const [isTooSensitive, setTooSensitive] = useState(!!initialState.fields.is_too_sensitive); + useEffect(() => { + if (mode === 'create' && isRealtime) { + const id = setInterval(() => { + const now = new Date(); + setDate(format(now, 'yyyy/MM/dd')); + setTime(format(now, 'HH:mm')); + }, 500); + return () => clearInterval(id); + } + }, [mode, isRealtime]); return ( <>
+ {mode === 'create' && ( +
+ setRealtime(v)} + > + 現在時刻でチェックイン + +
+ )}
@@ -57,6 +83,7 @@ export const CheckinForm: React.FC = ({ initialState }) => { required value={time} onChange={(e) => setTime(e.target.value)} + disabled={isRealtime} />