import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' import { useState } from 'react' import { Helmet } from 'react-helmet-async' import FormField from '@/components/common/FormField' import PageTitle from '@/components/common/PageTitle' import MainArea from '@/components/layout/MainArea' import { Button } from '@/components/ui/button' import { toast } from '@/components/ui/use-toast' import { SITE_TITLE } from '@/config' import { createMaterialSyncSuppression, fetchMaterialSyncSuppressions } from '@/lib/materials' import { materialsKeys } from '@/lib/queryKeys' import { dateString, inputClass } from '@/lib/utils' import type { FC, FormEvent } from 'react' import type { MaterialSyncSuppressionSourceKind } from '@/types' const SOURCE_KIND_LABELS: Record = { uri: 'URI', google_drive_path: 'Google Drive ファイル', google_drive_path_prefix: 'Google Drive フォルダ', google_drive_file: 'Google Drive ファイル Id.', legacy_drive_path: '汎用ファイル', legacy_drive_path_prefix: '汎用フォルダ' } const REASONS = [ 'copyright_high_risk', 'copyright_takedown', 'adult_or_sensitive', 'personal_information', 'malware_or_dangerous_file', 'duplicate_or_low_quality', 'source_owner_request', 'other'] as const type MaterialSyncSuppressionReason = typeof REASONS[number] const REASON_NAMES: Record = { ['copyright_high_risk']: '著作権への懸念', ['copyright_takedown']: '著作者からの申出', ['adult_or_sensitive']: '成人向け', ['personal_information']: '個人情報', ['malware_or_dangerous_file']: '危険なソフトウェア', ['duplicate_or_low_quality']: '重複', ['source_owner_request']: '同期元管理者からの申出', ['other']: 'その他' } as const const reasonName = (reason: string): string => REASON_NAMES[reason as MaterialSyncSuppressionReason] ?? reason const MaterialSyncSuppressionsPage: FC = () => { const qc = useQueryClient () const [sourceKind, setSourceKind] = useState ('uri') const [sourceUri, setSourceUri] = useState ('') const [drivePath, setDrivePath] = useState ('') const [driveFileId, setDriveFileId] = useState ('') const [reason, setReason] = useState (REASONS[0]) const { data, isError, isLoading } = useQuery ({ queryKey: materialsKeys.suppressions (), queryFn: fetchMaterialSyncSuppressions}) const createMutation = useMutation ({ mutationFn: async () => await createMaterialSyncSuppression ({ sourceKind, sourceUri, drivePath, driveFileId, reason}), onSuccess: async () => { await qc.invalidateQueries ({ queryKey: materialsKeys.suppressions () }) await qc.invalidateQueries ({ queryKey: materialsKeys.root }) setSourceUri ('') setDrivePath ('') setDriveFileId ('') toast ({ title: '同期元抑止を登録しました' }) }, onError: () => { toast ({ title: '同期元抑止の登録に失敗しました' }) }}) const handleSubmit = (event: FormEvent) => { event.preventDefault () createMutation.mutate () } const suppressions = data?.suppressions ?? [] return ( {`素材同期抑止 | ${ SITE_TITLE }`}
同期抑止
{({ invalid }) => ( )} {({ invalid }) => ( setSourceUri (e.target.value)} className={inputClass (invalid)}/>)} {({ invalid }) => ( setDrivePath (e.target.value)} className={inputClass (invalid)}/>)} {({ invalid }) => ( setDriveFileId (e.target.value)} className={inputClass (invalid)}/>)} {({ invalid }) => ( )}
{isLoading &&

Loading...

} {isError && (

同期元抑止一覧の取得に失敗しました.

)}
{suppressions.map (suppression => (
{SOURCE_KIND_LABELS[suppression.sourceKind]}
{suppression.normalizedSourceKey}
事由: {reasonName (suppression.reason)} / 登録: {dateString (suppression.createdAt)}
))}
) } export default MaterialSyncSuppressionsPage