diff --git a/app/Http/Controllers/EjaculationController.php b/app/Http/Controllers/EjaculationController.php index 8446c96..e59aece 100644 --- a/app/Http/Controllers/EjaculationController.php +++ b/app/Http/Controllers/EjaculationController.php @@ -16,17 +16,26 @@ class EjaculationController extends Controller { public function create(Request $request) { - $defaults = [ - 'date' => $request->input('date', date('Y/m/d')), - 'time' => $request->input('time', date('H:i')), - 'link' => $request->input('link', ''), - 'tags' => $request->input('tags', ''), - 'note' => $request->input('note', ''), - 'is_private' => $request->input('is_private', 0) == 1, - 'is_too_sensitive' => $request->input('is_too_sensitive', 0) == 1 + $tags = old('tags') ?? $request->input('tags', ''); + if (!empty($tags)) { + $tags = explode(' ', $tags); + } + + $errors = $request->session()->get('errors'); + $initialState = [ + 'fields' => [ + 'date' => old('date') ?? $request->input('date', date('Y/m/d')), + 'time' => old('time') ?? $request->input('time', date('H:i')), + 'link' => old('link') ?? $request->input('link', ''), + '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 + ], + 'errors' => isset($errors) ? $errors->getMessages() : null ]; - return view('ejaculation.checkin')->with('defaults', $defaults); + return view('ejaculation.checkin')->with('initialState', $initialState); } public function store(Request $request) @@ -112,13 +121,36 @@ class EjaculationController extends Controller return view('ejaculation.show')->with(compact('user', 'ejaculation', 'ejaculatedSpan')); } - public function edit($id) + public function edit(Request $request, $id) { $ejaculation = Ejaculation::findOrFail($id); $this->authorize('edit', $ejaculation); - return view('ejaculation.edit')->with(compact('ejaculation')); + if (old('tags') === null) { + $tags = $ejaculation->tags->pluck('name'); + } else { + $tags = old('tags'); + if (!empty($tags)) { + $tags = explode(' ', $tags); + } + } + + $errors = $request->session()->get('errors'); + $initialState = [ + 'fields' => [ + 'date' => old('date') ?? $ejaculation->ejaculated_date->format('Y/m/d'), + 'time' => old('time') ?? $ejaculation->ejaculated_date->format('H:i'), + 'link' => old('link') ?? $ejaculation->link, + 'tags' => $tags, + 'note' => old('note') ?? $ejaculation->note, + 'is_private' => is_bool(old('is_private')) ? old('is_private') : $ejaculation->note, + 'is_too_sensitive' => is_bool(old('is_too_sensitive')) ? old('is_too_sensitive') : $ejaculation->is_too_sensitive + ], + 'errors' => isset($errors) ? $errors->getMessages() : null + ]; + + return view('ejaculation.edit')->with(compact('ejaculation', 'initialState')); } public function update(Request $request, $id) diff --git a/resources/assets/js/checkin.tsx b/resources/assets/js/checkin.tsx index 29d8b7e..23ce902 100644 --- a/resources/assets/js/checkin.tsx +++ b/resources/assets/js/checkin.tsx @@ -1,87 +1,6 @@ -import Vue from 'vue'; -import TagInput from './components/TagInput.vue'; -import MetadataPreview from './components/MetadataPreview.vue'; -import { fetchGet, ResponseError } from './fetch'; import * as React from 'react'; import * as ReactDOM from 'react-dom'; -import { TagInput as TagInput2 } from './components/TagInput2'; +import { CheckinForm } from './components/CheckinForm'; -export const bus = new Vue({ name: 'EventBus' }); - -export enum MetadataLoadState { - Inactive, - Loading, - Success, - Failed, -} - -export type Metadata = { - url: string; - title: string; - description: string; - image: string; - expires_at: string | null; - tags: { - name: string; - }[]; -}; - -new Vue({ - el: '#app', - data: { - metadata: null, - metadataLoadState: MetadataLoadState.Inactive, - }, - components: { - TagInput, - MetadataPreview, - }, - mounted() { - // オカズリンクにURLがセットされている場合は、すぐにメタデータを取得する - const linkInput = this.$el.querySelector('#link'); - if (linkInput && /^https?:\/\//.test(linkInput.value)) { - this.fetchMetadata(linkInput.value); - } - }, - methods: { - // オカズリンクの変更時 - onChangeLink(event: Event) { - if (event.target instanceof HTMLInputElement) { - const url = event.target.value; - - if (url.trim() === '' || !/^https?:\/\//.test(url)) { - this.metadata = null; - this.metadataLoadState = MetadataLoadState.Inactive; - return; - } - - this.fetchMetadata(url); - } - }, - // メタデータの取得 - fetchMetadata(url: string) { - this.metadataLoadState = MetadataLoadState.Loading; - - fetchGet('/api/checkin/card', { url }) - .then((response) => { - if (!response.ok) { - throw new ResponseError(response); - } - return response.json(); - }) - .then((data) => { - this.metadata = data; - this.metadataLoadState = MetadataLoadState.Success; - }) - .catch(() => { - this.metadata = null; - this.metadataLoadState = MetadataLoadState.Failed; - }); - }, - }, -}); - -ReactDOM.render( - , - document.querySelector('#tagInput2') -); +const initialState = JSON.parse(document.getElementById('initialState')?.textContent as string); +ReactDOM.render(, document.getElementById('checkinForm')); diff --git a/resources/assets/js/components/CheckinForm.tsx b/resources/assets/js/components/CheckinForm.tsx new file mode 100644 index 0000000..5931869 --- /dev/null +++ b/resources/assets/js/components/CheckinForm.tsx @@ -0,0 +1,187 @@ +import * as React from 'react'; +import { useState } from 'react'; +import * as classNames from 'classnames'; +import { TagInput } from './TagInput'; +import { MetadataPreview } from './MetadataPreview'; + +type CheckboxProps = { + id: string; + name: string; + className?: string; + checked?: boolean; + onChange?: (newValue: boolean) => void; +}; + +const Checkbox: React.FC = ({ id, name, className, checked, onChange, children }) => ( +
+ onChange && onChange(e.target.checked)} + /> + +
+); + +type FieldErrorProps = { + errors?: string[]; +}; + +const FieldError: React.FC = ({ errors }) => + (errors && errors.length > 0 &&
{errors[0]}
) || null; + +const StandaloneFieldError: React.FC = ({ errors }) => + (errors && errors.length > 0 && ( +
+ {errors[0]} +
+ )) || + null; + +export type CheckinFormProps = { + initialState: any; +}; + +export const CheckinForm: React.FC = ({ initialState }) => { + 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 [isPrivate, setPrivate] = useState(!!initialState.fields.is_private); + const [isTooSensitive, setTooSensitive] = useState(!!initialState.fields.is_too_sensitive); + + return ( + <> +
+
+ + setDate(e.target.value)} + /> + +
+
+ + setTime(e.target.value)} + /> + +
+ +
+
+
+ + setTags(v)} + /> + Tab, Enter, 半角スペースのいずれかで入力確定します。 + +
+
+
+
+ + setLink(e.target.value)} + onBlur={() => setLinkForPreview(link)} + /> + オカズのURLを貼り付けて登録することができます。 + +
+
+ setTags(tags.concat(v))} /> +
+
+ + - - 最大 500 文字 - - @if ($errors->has('note')) -
{{ $errors->first('note') }}
- @endif -
-
-
-

オプション

-
-
- - -
-
- - -
-
-
- -
- +
+
しばらくお待ちください…

Tips: ブックマークレットや共有機能で、簡単にチェックインできます! 使い方はこちら

@@ -107,5 +21,6 @@ @endsection @push('script') + @endpush diff --git a/resources/views/ejaculation/edit.blade.php b/resources/views/ejaculation/edit.blade.php index ffdbd45..33353ad 100644 --- a/resources/views/ejaculation/edit.blade.php +++ b/resources/views/ejaculation/edit.blade.php @@ -3,7 +3,7 @@ @section('title', 'チェックインの修正') @section('content') -
+

チェックインの修正


@@ -11,92 +11,8 @@
{{ method_field('PUT') }} {{ csrf_field() }} - -
-
- - - - @if ($errors->has('date')) -
{{ $errors->first('date') }}
- @endif -
-
- - - - @if ($errors->has('time')) -
{{ $errors->first('time') }}
- @endif -
- @if ($errors->has('datetime')) -
- {{ $errors->first('datetime') }} -
- @endif -
-
-
- - - - Tab, Enter, 半角スペースのいずれかで入力確定します。 - - - @if ($errors->has('tags')) -
{{ $errors->first('tags') }}
- @endif -
-
-
-
- - - - オカズのURLを貼り付けて登録することができます。 - - @if ($errors->has('link')) -
{{ $errors->first('link') }}
- @endif -
-
- -
-
- - - - 最大 500 文字 - - @if ($errors->has('note')) -
{{ $errors->first('note') }}
- @endif -
-
-
-

オプション

-
-
- is_private) ? 'checked' : '' }}> - -
-
- is_too_sensitive) ? 'checked' : '' }}> - -
-
-
- -
- +
+
しばらくお待ちください…
@@ -105,5 +21,6 @@ @endsection @push('script') + @endpush