diff --git a/resources/assets/js/checkin.ts b/resources/assets/js/checkin.tsx similarity index 89% rename from resources/assets/js/checkin.ts rename to resources/assets/js/checkin.tsx index 45bbd2a..5cbe176 100644 --- a/resources/assets/js/checkin.ts +++ b/resources/assets/js/checkin.tsx @@ -15,6 +15,17 @@ export enum MetadataLoadState { Failed, } +export type Metadata = { + url: string; + title: string; + description: string; + image: string; + expires_at: string | null; + tags: { + name: string; + }[]; +}; + new Vue({ el: '#app', data: { @@ -71,6 +82,6 @@ new Vue({ }); ReactDOM.render( - React.createElement(TagInput2, { id: 'tagInput2', name: 'tags2', value: '', isInvalid: false }), + , document.querySelector('#tagInput2') ); diff --git a/resources/assets/js/components/MetadataPreview2.tsx b/resources/assets/js/components/MetadataPreview2.tsx new file mode 100644 index 0000000..e2dcdac --- /dev/null +++ b/resources/assets/js/components/MetadataPreview2.tsx @@ -0,0 +1,110 @@ +import * as React from 'react'; +import { Metadata, MetadataLoadState } from '../checkin'; +import * as classNames from 'classnames'; + +type Suggestion = { + name: string; + used: boolean; +}; + +type MetadataPreviewProps = { + state: MetadataLoadState; + metadata: Metadata | null; + tags: string[]; + handleAddTag: (tag: string) => void; +}; + +const MetadataLoading = () => ( +
+
+
+
+ オカズの情報を読み込んでいます… +
+
+
+
+); + +const MetadataLoadFailed = () => ( +
+
+
+
+ オカズの情報を読み込めませんでした +
+
+
+
+); + +export const MetadataPreview: React.FC = ({ state, metadata, tags, handleAddTag }) => { + if (state === MetadataLoadState.Inactive) { + return null; + } + const hasImage = metadata !== null && metadata.image !== ''; + const descClasses = classNames({ + 'col-8': hasImage, + 'col-12': !hasImage, + }); + const tagClasses = (s: Suggestion) => + classNames({ + 'list-inline-item': true, + badge: true, + 'badge-primary': !s.used, + 'badge-secondary': s.used, + 'metadata-tag-item': true, + }); + const suggestions = + metadata?.tags.map((t) => ({ + name: t.name, + used: tags.indexOf(t.name) !== -1, + })) ?? []; + + return ( +
+
+
+ {state === MetadataLoadState.Loading ? ( + + ) : state === MetadataLoadState.Success ? ( +
+
+ Thumbnail +
+
+
+
{metadata?.title}
+ {suggestions.length > 0 && ( + <> +

+ タグ候補 +
+ + (クリックするとタグ入力欄にコピーできます) + +

+
    + {suggestions.map((tag) => ( +
  • handleAddTag(tag.name)} + > + {tag.name} +
  • + ))} +
+ + )} +
+
+
+ ) : ( + + )} +
+
+
+ ); +}; diff --git a/resources/assets/sass/components/_metadata-preview.scss b/resources/assets/sass/components/_metadata-preview.scss new file mode 100644 index 0000000..4ce8e79 --- /dev/null +++ b/resources/assets/sass/components/_metadata-preview.scss @@ -0,0 +1,28 @@ +.tis-metadata-preview { + &-link-card { + $height: 150px; + overflow: hidden; + font-size: small; + + .row > div:first-child { + display: flex; + + &:not([display='none']) { + min-height: $height; + + img { + position: absolute; + } + } + } + + .card-text { + white-space: pre-line; + } + } + + &-tag-item { + cursor: pointer; + user-select: none; + } +} diff --git a/resources/views/ejaculation/checkin.blade.php b/resources/views/ejaculation/checkin.blade.php index 1ae063f..9ffb8ca 100644 --- a/resources/views/ejaculation/checkin.blade.php +++ b/resources/views/ejaculation/checkin.blade.php @@ -65,6 +65,7 @@ +
diff --git a/webpack.mix.js b/webpack.mix.js index 16ed4e0..dd4c5e1 100644 --- a/webpack.mix.js +++ b/webpack.mix.js @@ -20,7 +20,7 @@ mix.ts('resources/assets/js/app.ts', 'public/js') .ts('resources/assets/js/setting/privacy.ts', 'public/js/setting') .ts('resources/assets/js/setting/import.ts', 'public/js/setting') .ts('resources/assets/js/setting/deactivate.ts', 'public/js/setting') - .ts('resources/assets/js/checkin.ts', 'public/js') + .ts('resources/assets/js/checkin.tsx', 'public/js') .sass('resources/assets/sass/app.scss', 'public/css') .autoload({ jquery: ['$', 'jQuery', 'window.jQuery'],