From 0c3ccb280691476daf6cb53cdae67dfb13ddebcd Mon Sep 17 00:00:00 2001 From: smanylov Date: Wed, 8 Apr 2026 13:41:56 +0700 Subject: [PATCH] matches: add animation, add suspense for table, add no-image image --- public/images/no-image.png | Bin 0 -> 2595 bytes src/app/actions/definitions.ts | 4 +- src/app/styles/pages-styles.scss | 21 ++- .../violation-table/case-complaint.tsx | 9 +- .../violation-table/case-violation.tsx | 25 ++- .../file-page-violation-info.tsx | 13 +- .../file-page-violations-list.tsx | 60 ++++++-- .../file-page-violations-loading-list.tsx | 143 ++++++++++++++++++ src/i18n/messages/en.json | 9 +- src/i18n/messages/ru.json | 9 +- 10 files changed, 267 insertions(+), 26 deletions(-) create mode 100644 public/images/no-image.png create mode 100644 src/app/ui/file-page/violation-table/file-page-violations-loading-list.tsx diff --git a/public/images/no-image.png b/public/images/no-image.png new file mode 100644 index 0000000000000000000000000000000000000000..942404a7accdc02b89a3496bb53c7ef64fff2867 GIT binary patch literal 2595 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 X!TRU`fB!8+(V_MRg!$L+KA8ItVCM-Y literal 0 HcmV?d00001 diff --git a/src/app/actions/definitions.ts b/src/app/actions/definitions.ts index c05d2ff..972eaf3 100644 --- a/src/app/actions/definitions.ts +++ b/src/app/actions/definitions.ts @@ -96,11 +96,11 @@ export const createCaseSchema = z .object({ textArea: z .string() - .min(6, { error: 'text-area-error-fill-complaint-text' }) + .min(6, { error: 'fill-text-of-the-case' }) .trim(), caseTitle: z .string() - .min(6, { error: 'text-area-error-fill-complaint-text' }) + .min(6, { error: 'fill-title-of-the-case' }) .trim(), }) diff --git a/src/app/styles/pages-styles.scss b/src/app/styles/pages-styles.scss index e0ca933..e4199d0 100644 --- a/src/app/styles/pages-styles.scss +++ b/src/app/styles/pages-styles.scss @@ -4457,9 +4457,10 @@ padding: 15px; height: calc(16vh - 12px); cursor: pointer; - display: flex; justify-content: space-between; opacity: 0.75; + display: flex; + gap: 10px; &:hover { transform: translateY(-2px); @@ -4497,10 +4498,12 @@ max-height: 80%; min-height: 50px; height: 100%; + position: relative; img { - height: 100%; + height: 100% !important; border-radius: 8px; + width: auto !important; } } @@ -4662,6 +4665,7 @@ &-image { width: 300px; height: 200px; + position: relative; img { width: 100%; @@ -4727,6 +4731,7 @@ &-case { padding: 10px; + position: relative; &:first-child { border-bottom: 1px solid rgb(226, 232, 240); @@ -4763,6 +4768,12 @@ border-color: #6366f1; box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1); } + + &-wrapper { + display: flex; + flex-direction: column; + margin-bottom: 10px; + } } .note-form-flex { @@ -4789,6 +4800,10 @@ border-color: #6366f1; box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1); } + + &::placeholder { + font-size: 12px; + } } .note-case-label { @@ -5389,6 +5404,7 @@ border-radius: 10px; box-shadow: 0 1px 2px #0000000d; color: v.$p-color; + cursor: pointer; .icon { width: 18px; @@ -5414,6 +5430,7 @@ padding: 0.25rem 0.75rem; border-radius: 10px; color: v.$p-color; + cursor: pointer; &:disabled { opacity: 0.5; diff --git a/src/app/ui/file-page/violation-table/case-complaint.tsx b/src/app/ui/file-page/violation-table/case-complaint.tsx index d787a74..0958b3b 100644 --- a/src/app/ui/file-page/violation-table/case-complaint.tsx +++ b/src/app/ui/file-page/violation-table/case-complaint.tsx @@ -143,7 +143,14 @@ export default function CaseComplaint({ selectedViolation, updateStatusHandler } if (isLoadingComplain) { return (
-
{t('loading')}...
+
+
+
+
); } diff --git a/src/app/ui/file-page/violation-table/case-violation.tsx b/src/app/ui/file-page/violation-table/case-violation.tsx index 3fb8704..fd92d73 100644 --- a/src/app/ui/file-page/violation-table/case-violation.tsx +++ b/src/app/ui/file-page/violation-table/case-violation.tsx @@ -86,7 +86,7 @@ export default function CaseViolation({ selectedViolation, updateStatusHandler } className="btn-action btn-case" onClick={toggleForm} > - Создание дела + {t('create-case')} ) : (
@@ -111,12 +111,13 @@ export default function CaseViolation({ selectedViolation, updateStatusHandler } className="note-case-label" htmlFor="caseTitle" > - Название дела + {t('case-name')} {state?.errorMessage?.caseTitle && (

- Сумма ущерба + {t('amount-of-damage')} {state?.errorMessage?.amount && (

-
+
{state?.errorMessage?.textArea && (

-

{t('loading')}...
+
+
+
+
+ ); } diff --git a/src/app/ui/file-page/violation-table/file-page-violation-info.tsx b/src/app/ui/file-page/violation-table/file-page-violation-info.tsx index e2b34d4..18f084c 100644 --- a/src/app/ui/file-page/violation-table/file-page-violation-info.tsx +++ b/src/app/ui/file-page/violation-table/file-page-violation-info.tsx @@ -12,6 +12,7 @@ import { useCallback, useEffect, useState } from 'react'; import { MatchStatus } from '@/app/actions/violationActions'; import { toast } from 'sonner'; import FilePageViolationEpmtyScreen from '@/app/ui/file-page/violation-table/file-page-violation-epmty-screen'; +import Image from 'next/image'; export default function FilePageViolationInfo({ selectedViolation }: { selectedViolation: ViolationFileDetail | null }) { const t = useTranslations('Global'); @@ -88,7 +89,17 @@ export default function FilePageViolationInfo({ selectedViolation }: { selectedV
- {selectedViolation?.page_title} + {selectedViolation?.page_title} { + const target = e.target as HTMLImageElement; + target.src = '/images/no-image.png'; + }} + />
(null); + const [cachedPagination, setCachedPagination] = useState<{ + total_pages: number; + total_elements: number; + current_page: number; + } | null>(null); + const { data: fileViolations, error, isPending } = useFileViolations(fileId, currentPage, status); - if (!fileViolations?.violations) { - return null; - } + useEffect(() => { + if (fileViolations?.violations) { + setCachedPagination({ + total_pages: fileViolations.total_pages, + total_elements: fileViolations.total_elements, + current_page: fileViolations.current_page + }); + } + }, [fileViolations]); + const paginationData = fileViolations?.violations ? fileViolations : cachedPagination; + + if (!fileViolations?.violations) { + return ; + } const handlePageChange = (page: number) => { const params = new URLSearchParams(searchParams); params.set('page', page.toString()); @@ -105,7 +131,7 @@ export default function FilePageViolationsList({ className="sources-list-wrapper" >
- {fileViolations.violations.map(item => { + {fileViolations?.violations.map(item => { return (
- + {item.page_title} { + const target = e.target as HTMLImageElement; + target.src = '/images/no-image.png'; + }} + />
- {t('total-violations')}: {fileViolations.total_elements} | {t('page')} {fileViolations.current_page} {t('out-of')} {fileViolations.total_pages} + {t('total-violations')}: {fileViolations?.total_elements} | {t('page')} {fileViolations?.current_page} {t('out-of')} {fileViolations?.total_pages} - {fileViolations.total_pages > 1 && ( + {fileViolations?.total_pages > 1 && (
@@ -215,14 +251,14 @@ export default function FilePageViolationsList({ diff --git a/src/app/ui/file-page/violation-table/file-page-violations-loading-list.tsx b/src/app/ui/file-page/violation-table/file-page-violations-loading-list.tsx new file mode 100644 index 0000000..d445f00 --- /dev/null +++ b/src/app/ui/file-page/violation-table/file-page-violations-loading-list.tsx @@ -0,0 +1,143 @@ +'use client' + +import Link from 'next/link'; +import FilePageViolationInfo from '@/app/ui/file-page/violation-table/file-page-violation-info'; +import DropDownList from '@/app/components/DropDownList'; +import { IconArrowLeft, IconArrowRight, IconDoubleArrowLeft, IconDoubleArrowRight } from '@/app/ui/icons/icons'; +import { useTranslations } from 'next-intl'; + +export default function FilePageViolationsLoadingList({ + currentPage, + fileId, + status, + cachedTotalPages, + cachedTotalElements, + cachedCurrentPage, +}: { + currentPage: number, + fileId: string, + status: string | undefined, + cachedTotalPages: number | undefined, + cachedTotalElements: number | undefined, + cachedCurrentPage: number | undefined +}) { + const t = useTranslations('Global'); + const tStatus = useTranslations('Match-status'); + + const getPageNumbers = () => { + const pages = []; + const maxVisible = 5; + const total = cachedTotalPages; + + let start = Math.max(1, currentPage - Math.floor(maxVisible / 2)); + let end = Math.min(total ? total : 0, start + maxVisible - 1); + + if (end - start + 1 < maxVisible) { + start = Math.max(1, end - maxVisible + 1); + } + + for (let i = start; i <= end; i++) { + pages.push(i); + } + + return pages; + }; + + return ( +
+
+

+ {t('all-file-violations')} +

+ +
+
+ { }} + > +
  • {t('all-statuses')}
  • +
  • {tStatus('NEW')}
  • +
  • {tStatus('SHOWED')}
  • +
  • {tStatus('LEGAL_IN_WORK')}
  • +
  • {tStatus('COMPLAINT_IN_WORK')}
  • +
  • {tStatus('COMPLAINT_AND_LEGAL_IN_WORK')}
  • +
  • {tStatus('AUTHORIZED_USE')}
  • +
    +
    +
    + +
    + +
    +
    +
    +
    +
    +
    +
    + + + {t('total-violations')}: {cachedTotalElements} | {t('page')} {cachedCurrentPage} {t('out-of')} {cachedTotalPages} + +
    + + + +
    + {getPageNumbers().map(pageNum => ( + + ))} +
    + + + + +
    +
    +
    + ) +} \ No newline at end of file diff --git a/src/i18n/messages/en.json b/src/i18n/messages/en.json index 3405c52..37a5569 100644 --- a/src/i18n/messages/en.json +++ b/src/i18n/messages/en.json @@ -407,7 +407,14 @@ "priority": "Priority", "type": "Type", "lawyer": "Lawyer", - "not-assigned": "Not assigned" + "not-assigned": "Not assigned", + "create-case": "Create case", + "case-name": "Case name", + "amount-of-damage": "Amount of damage", + "text-of-the-case": "Text of the case", + "fill-text-of-the-case": "Fill the case text", + "fill-title-of-the-case": "Fill the case title", + "enter-the-amount-of-damage": "Enter the amount of damage" }, "Login-register-form": { "and": "and", diff --git a/src/i18n/messages/ru.json b/src/i18n/messages/ru.json index e5c0de6..7ff5e2e 100644 --- a/src/i18n/messages/ru.json +++ b/src/i18n/messages/ru.json @@ -407,7 +407,14 @@ "priority": "Приоритет", "type": "Тип", "lawyer": "Адвокат", - "not-assigned": "Не назначено" + "not-assigned": "Не назначено", + "create-case": "Создать дело", + "case-name": "Название дела", + "amount-of-damage": "Сумма ущерба", + "text-of-the-case": "Текст дела", + "fill-text-of-the-case": "Заполните текст дела", + "fill-title-of-the-case": "Заполните название дела", + "enter-the-amount-of-damage": "Введите сумму ущерба" }, "Login-register-form": { "and": "и",