Merge pull request #547 from shikorism/feature/realtime-checkin
日時指定を省略してチェックインする機能
This commit is contained in:
		@@ -23,6 +23,7 @@ class EjaculationController extends Controller
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        $errors = $request->session()->get('errors');
 | 
					        $errors = $request->session()->get('errors');
 | 
				
			||||||
        $initialState = [
 | 
					        $initialState = [
 | 
				
			||||||
 | 
					            'mode' => 'create',
 | 
				
			||||||
            'fields' => [
 | 
					            'fields' => [
 | 
				
			||||||
                'date' => old('date') ?? $request->input('date', date('Y/m/d')),
 | 
					                'date' => old('date') ?? $request->input('date', date('Y/m/d')),
 | 
				
			||||||
                'time' => old('time') ?? $request->input('time', date('H:i')),
 | 
					                'time' => old('time') ?? $request->input('time', date('H:i')),
 | 
				
			||||||
@@ -30,7 +31,8 @@ class EjaculationController extends Controller
 | 
				
			|||||||
                'tags' => $tags,
 | 
					                'tags' => $tags,
 | 
				
			||||||
                'note' => old('note') ?? $request->input('note', ''),
 | 
					                'note' => old('note') ?? $request->input('note', ''),
 | 
				
			||||||
                'is_private' => old('is_private') ?? $request->input('is_private', 0) == 1,
 | 
					                '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
 | 
					            'errors' => isset($errors) ? $errors->getMessages() : null
 | 
				
			||||||
        ];
 | 
					        ];
 | 
				
			||||||
@@ -43,15 +45,20 @@ class EjaculationController extends Controller
 | 
				
			|||||||
        $inputs = $request->all();
 | 
					        $inputs = $request->all();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $validator = Validator::make($inputs, [
 | 
					        $validator = Validator::make($inputs, [
 | 
				
			||||||
            'date' => 'required|date_format:Y/m/d',
 | 
					            'date' => 'required_without:is_realtime|date_format:Y/m/d',
 | 
				
			||||||
            'time' => 'required|date_format:H:i',
 | 
					            'time' => 'required_without:is_realtime|date_format:H:i',
 | 
				
			||||||
            'note' => 'nullable|string|max:500',
 | 
					            'note' => 'nullable|string|max:500',
 | 
				
			||||||
            'link' => 'nullable|url|max:2000',
 | 
					            'link' => 'nullable|url|max:2000',
 | 
				
			||||||
            'tags' => 'nullable|string',
 | 
					            'tags' => 'nullable|string',
 | 
				
			||||||
        ])->after(function ($validator) use ($request, $inputs) {
 | 
					        ])->after(function ($validator) use ($request, $inputs) {
 | 
				
			||||||
            // 日時の重複チェック
 | 
					            // 日時の重複チェック
 | 
				
			||||||
            if (!$validator->errors()->hasAny(['date', 'time'])) {
 | 
					            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()) {
 | 
					                if (Ejaculation::where(['user_id' => Auth::id(), 'ejaculated_date' => $dt])->count()) {
 | 
				
			||||||
                    $validator->errors()->add('datetime', '既にこの日時にチェックインしているため、登録できません。');
 | 
					                    $validator->errors()->add('datetime', '既にこの日時にチェックインしているため、登録できません。');
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
@@ -59,13 +66,21 @@ class EjaculationController extends Controller
 | 
				
			|||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ($validator->fails()) {
 | 
					        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) {
 | 
					        $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([
 | 
					            $ejaculation = Ejaculation::create([
 | 
				
			||||||
                'user_id' => Auth::id(),
 | 
					                'user_id' => Auth::id(),
 | 
				
			||||||
                'ejaculated_date' => Carbon::createFromFormat('Y/m/d H:i', $inputs['date'] . ' ' . $inputs['time']),
 | 
					                'ejaculated_date' => $ejaculatedDate,
 | 
				
			||||||
                'note' => $inputs['note'] ?? '',
 | 
					                'note' => $inputs['note'] ?? '',
 | 
				
			||||||
                'link' => $inputs['link'] ?? '',
 | 
					                'link' => $inputs['link'] ?? '',
 | 
				
			||||||
                'source' => Ejaculation::SOURCE_WEB,
 | 
					                'source' => Ejaculation::SOURCE_WEB,
 | 
				
			||||||
@@ -138,6 +153,7 @@ class EjaculationController extends Controller
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        $errors = $request->session()->get('errors');
 | 
					        $errors = $request->session()->get('errors');
 | 
				
			||||||
        $initialState = [
 | 
					        $initialState = [
 | 
				
			||||||
 | 
					            'mode' => 'update',
 | 
				
			||||||
            'fields' => [
 | 
					            'fields' => [
 | 
				
			||||||
                'date' => old('date') ?? $ejaculation->ejaculated_date->format('Y/m/d'),
 | 
					                'date' => old('date') ?? $ejaculation->ejaculated_date->format('Y/m/d'),
 | 
				
			||||||
                'time' => old('time') ?? $ejaculation->ejaculated_date->format('H:i'),
 | 
					                'time' => old('time') ?? $ejaculation->ejaculated_date->format('H:i'),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,6 @@
 | 
				
			|||||||
import React, { useState } from 'react';
 | 
					import React, { useState, useEffect } from 'react';
 | 
				
			||||||
import classNames from 'classnames';
 | 
					import classNames from 'classnames';
 | 
				
			||||||
 | 
					import { format } from 'date-fns';
 | 
				
			||||||
import { CheckBox } from './CheckBox';
 | 
					import { CheckBox } from './CheckBox';
 | 
				
			||||||
import { FieldError, StandaloneFieldError } from './FieldError';
 | 
					import { FieldError, StandaloneFieldError } from './FieldError';
 | 
				
			||||||
import { TagInput } from './TagInput';
 | 
					import { TagInput } from './TagInput';
 | 
				
			||||||
@@ -10,18 +11,42 @@ type CheckinFormProps = {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const CheckinForm: React.FC<CheckinFormProps> = ({ initialState }) => {
 | 
					export const CheckinForm: React.FC<CheckinFormProps> = ({ initialState }) => {
 | 
				
			||||||
 | 
					    const mode = initialState.mode;
 | 
				
			||||||
    const [date, setDate] = useState<string>(initialState.fields.date || '');
 | 
					    const [date, setDate] = useState<string>(initialState.fields.date || '');
 | 
				
			||||||
    const [time, setTime] = useState<string>(initialState.fields.time || '');
 | 
					    const [time, setTime] = useState<string>(initialState.fields.time || '');
 | 
				
			||||||
    const [tags, setTags] = useState<string[]>(initialState.fields.tags || []);
 | 
					    const [tags, setTags] = useState<string[]>(initialState.fields.tags || []);
 | 
				
			||||||
    const [link, setLink] = useState<string>(initialState.fields.link || '');
 | 
					    const [link, setLink] = useState<string>(initialState.fields.link || '');
 | 
				
			||||||
    const [linkForPreview, setLinkForPreview] = useState(link);
 | 
					    const [linkForPreview, setLinkForPreview] = useState(link);
 | 
				
			||||||
    const [note, setNote] = useState<string>(initialState.fields.note || '');
 | 
					    const [note, setNote] = useState<string>(initialState.fields.note || '');
 | 
				
			||||||
 | 
					    const [isRealtime, setRealtime] = useState<boolean>(mode === 'create' && initialState.fields.is_realtime);
 | 
				
			||||||
    const [isPrivate, setPrivate] = useState<boolean>(!!initialState.fields.is_private);
 | 
					    const [isPrivate, setPrivate] = useState<boolean>(!!initialState.fields.is_private);
 | 
				
			||||||
    const [isTooSensitive, setTooSensitive] = useState<boolean>(!!initialState.fields.is_too_sensitive);
 | 
					    const [isTooSensitive, setTooSensitive] = useState<boolean>(!!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 (
 | 
					    return (
 | 
				
			||||||
        <>
 | 
					        <>
 | 
				
			||||||
            <div className="form-row">
 | 
					            <div className="form-row">
 | 
				
			||||||
 | 
					                {mode === 'create' && (
 | 
				
			||||||
 | 
					                    <div className="col-sm-12 mb-2">
 | 
				
			||||||
 | 
					                        <CheckBox
 | 
				
			||||||
 | 
					                            id="isRealtime"
 | 
				
			||||||
 | 
					                            name="is_realtime"
 | 
				
			||||||
 | 
					                            checked={isRealtime}
 | 
				
			||||||
 | 
					                            onChange={(v) => setRealtime(v)}
 | 
				
			||||||
 | 
					                        >
 | 
				
			||||||
 | 
					                            現在時刻でチェックイン
 | 
				
			||||||
 | 
					                        </CheckBox>
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
 | 
					                )}
 | 
				
			||||||
                <div className="form-group col-sm-6">
 | 
					                <div className="form-group col-sm-6">
 | 
				
			||||||
                    <label htmlFor="date">
 | 
					                    <label htmlFor="date">
 | 
				
			||||||
                        <span className="oi oi-calendar" /> 日付
 | 
					                        <span className="oi oi-calendar" /> 日付
 | 
				
			||||||
@@ -38,6 +63,7 @@ export const CheckinForm: React.FC<CheckinFormProps> = ({ initialState }) => {
 | 
				
			|||||||
                        required
 | 
					                        required
 | 
				
			||||||
                        value={date}
 | 
					                        value={date}
 | 
				
			||||||
                        onChange={(e) => setDate(e.target.value)}
 | 
					                        onChange={(e) => setDate(e.target.value)}
 | 
				
			||||||
 | 
					                        disabled={isRealtime}
 | 
				
			||||||
                    />
 | 
					                    />
 | 
				
			||||||
                    <FieldError errors={initialState.errors?.date} />
 | 
					                    <FieldError errors={initialState.errors?.date} />
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
@@ -57,6 +83,7 @@ export const CheckinForm: React.FC<CheckinFormProps> = ({ initialState }) => {
 | 
				
			|||||||
                        required
 | 
					                        required
 | 
				
			||||||
                        value={time}
 | 
					                        value={time}
 | 
				
			||||||
                        onChange={(e) => setTime(e.target.value)}
 | 
					                        onChange={(e) => setTime(e.target.value)}
 | 
				
			||||||
 | 
					                        disabled={isRealtime}
 | 
				
			||||||
                    />
 | 
					                    />
 | 
				
			||||||
                    <FieldError errors={initialState.errors?.time} />
 | 
					                    <FieldError errors={initialState.errors?.time} />
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user