add modal window for save compaint text template
This commit is contained in:
@@ -994,7 +994,7 @@
|
|||||||
right: 0;
|
right: 0;
|
||||||
background: none;
|
background: none;
|
||||||
border: none;
|
border: none;
|
||||||
color: white;
|
color: v.$white;
|
||||||
font-size: 32px;
|
font-size: 32px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
@@ -1003,4 +1003,117 @@
|
|||||||
&:hover {
|
&:hover {
|
||||||
opacity: 0.8;
|
opacity: 0.8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.template-modal-content {
|
||||||
|
min-width: 400px;
|
||||||
|
max-width: 500px;
|
||||||
|
background: v.$white;
|
||||||
|
border-radius: 8px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.template-modal-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 16px 20px;
|
||||||
|
border-bottom: 1px solid v.$border-color-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.template-modal-header h3 {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.template-modal-close {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
font-size: 24px;
|
||||||
|
cursor: pointer;
|
||||||
|
color: #666;
|
||||||
|
padding: 0;
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border-radius: 4px;
|
||||||
|
transition: all 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.template-modal-close:hover {
|
||||||
|
background: v.$border-color-1;
|
||||||
|
color: v.$text-p;
|
||||||
|
}
|
||||||
|
|
||||||
|
.template-modal-body {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.template-form-group {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.template-form-group label {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: v.$text-p;
|
||||||
|
}
|
||||||
|
|
||||||
|
.template-name-input {
|
||||||
|
width: 100%;
|
||||||
|
padding: 8px 12px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-size: 14px;
|
||||||
|
transition: border-color 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.template-name-input:focus {
|
||||||
|
outline: none;
|
||||||
|
box-shadow: 0 0 0 2px rgba(74, 144, 226, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.template-preview {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.template-preview-label {
|
||||||
|
font-weight: 500;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
color: v.$text-p;
|
||||||
|
}
|
||||||
|
|
||||||
|
.template-preview-text {
|
||||||
|
background: v.$bg-hover;
|
||||||
|
padding: 12px;
|
||||||
|
border-radius: 8px;
|
||||||
|
max-height: 200px;
|
||||||
|
overflow-y: auto;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.5;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-wrap: break-word;
|
||||||
|
color: v.$text-s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.template-modal-footer {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
gap: 12px;
|
||||||
|
padding: 16px 20px;
|
||||||
|
border-top: 1px solid v.$border-color-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* .btn-secondary {
|
||||||
|
background: #6c757d;
|
||||||
|
color: v.$white;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-secondary:hover {
|
||||||
|
background: #5a6268;
|
||||||
|
} */
|
||||||
@@ -7,6 +7,7 @@ import { createComplaint, fetchComplainInfo, MatchStatus } from '@/app/actions/v
|
|||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
import { useQuery } from '@tanstack/react-query';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
import { formatDate, formatDateTime } from '@/app/lib/formatDate';
|
import { formatDate, formatDateTime } from '@/app/lib/formatDate';
|
||||||
|
import ModalWindow from '@/app/components/ModalWindow';
|
||||||
|
|
||||||
interface complaintInfo {
|
interface complaintInfo {
|
||||||
id: number,
|
id: number,
|
||||||
@@ -28,6 +29,8 @@ export default function CaseComplaint({ selectedViolation, updateStatusHandler }
|
|||||||
const [localViolation, setLocalViolation] = useState<ViolationFileDetail>(selectedViolation);
|
const [localViolation, setLocalViolation] = useState<ViolationFileDetail>(selectedViolation);
|
||||||
const [noteText, setNoteText] = useState('');
|
const [noteText, setNoteText] = useState('');
|
||||||
const [state, formAction, isPending] = useActionState(createComplaint, undefined);
|
const [state, formAction, isPending] = useActionState(createComplaint, undefined);
|
||||||
|
const [isTemplateModalOpen, setIsTemplateModalOpen] = useState(false);
|
||||||
|
const [templateName, setTemplateName] = useState('');
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setLocalViolation(selectedViolation);
|
setLocalViolation(selectedViolation);
|
||||||
@@ -77,178 +80,256 @@ export default function CaseComplaint({ selectedViolation, updateStatusHandler }
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function openTemplateSaveModal() {
|
||||||
|
if (!noteText.trim()) {
|
||||||
|
toast.warning(t('please-enter-complaint-text-first'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setTemplateName('');
|
||||||
|
setIsTemplateModalOpen(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveTemplateHandler() {
|
||||||
|
if (!templateName.trim()) {
|
||||||
|
toast.warning(t('please-enter-template-name'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// пока нету эндпоинта оставлю заглушку
|
||||||
|
console.log('СОХРАНЕНИЕ ШАБЛОНА');
|
||||||
|
console.log('Название шаблона:', templateName);
|
||||||
|
console.log('Текст жалобы:', noteText);
|
||||||
|
console.log('========================');
|
||||||
|
|
||||||
|
toast.success(t('template-saved-successfully') || 'Шаблон успешно сохранен');
|
||||||
|
setIsTemplateModalOpen(false);
|
||||||
|
setTemplateName('');
|
||||||
|
}
|
||||||
|
|
||||||
if (!ENABLED_STATUSES.includes(localViolation.status)) {
|
if (!ENABLED_STATUSES.includes(localViolation.status)) {
|
||||||
return (
|
return (
|
||||||
<div className="violation-info-case">
|
<>
|
||||||
|
<div className="violation-info-case">
|
||||||
<div className="note-form">
|
<div className="note-form">
|
||||||
<form action={formAction}>
|
<form action={formAction}>
|
||||||
<input type="hidden" name="violationId" value={localViolation.id} />
|
<input type="hidden" name="violationId" value={localViolation.id} />
|
||||||
<section
|
<section
|
||||||
className="note-form-section"
|
className="note-form-section"
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="note-form-group"
|
|
||||||
>
|
>
|
||||||
<label
|
<div
|
||||||
className="note-case-label"
|
className="note-form-group"
|
||||||
htmlFor="note"
|
|
||||||
>
|
>
|
||||||
{t('text-of-the-complaint')}
|
<label
|
||||||
</label>
|
className="note-case-label"
|
||||||
|
htmlFor="note"
|
||||||
|
>
|
||||||
|
{t('text-of-the-complaint')}
|
||||||
|
</label>
|
||||||
|
|
||||||
<textarea
|
<textarea
|
||||||
name="note"
|
name="note"
|
||||||
className="note-textarea"
|
className="note-textarea"
|
||||||
placeholder={`${t('text-area-error-fill-complaint-text')}...`}
|
placeholder={`${t('text-area-error-fill-complaint-text')}...`}
|
||||||
value={noteText}
|
value={noteText}
|
||||||
onChange={(e) => setNoteText(e.target.value)}
|
onChange={(e) => setNoteText(e.target.value)}
|
||||||
|
>
|
||||||
|
</textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{state?.errorMessage?.textArea && (
|
||||||
|
<p
|
||||||
|
className="text-sm text-red-500"
|
||||||
|
>
|
||||||
|
{
|
||||||
|
state?.errorMessage?.textArea.split('&').map((e, index) => {
|
||||||
|
return (
|
||||||
|
<span key={index}>
|
||||||
|
{t(e)}
|
||||||
|
<br />
|
||||||
|
</span>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<div
|
||||||
|
className="button-actions"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn-s btn-primary-small"
|
||||||
|
onClick={openTemplateSaveModal}
|
||||||
>
|
>
|
||||||
</textarea>
|
{t('save-template')}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
className="btn-s btn-primary-small"
|
||||||
|
disabled={isPending}
|
||||||
|
>
|
||||||
|
{t('submit-violation')}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="samples-wrapper"
|
||||||
|
>
|
||||||
|
<h5>Шаблоны</h5>
|
||||||
|
|
||||||
{state?.errorMessage?.textArea && (
|
<ul
|
||||||
<p
|
className="samples-list"
|
||||||
className="text-sm text-red-500"
|
|
||||||
>
|
|
||||||
|
|
||||||
{
|
|
||||||
state?.errorMessage?.textArea.split('&').map((e, index) => {
|
|
||||||
return (
|
|
||||||
<span key={index}>
|
|
||||||
{t(e)}
|
|
||||||
<br />
|
|
||||||
</span>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<div
|
|
||||||
className="button-actions"
|
|
||||||
>
|
>
|
||||||
<button
|
<li
|
||||||
type="submit"
|
className="sample-item"
|
||||||
className="btn-s btn-primary-small"
|
|
||||||
disabled={isPending}
|
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
templateHandler(e)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Сохранить шаблон
|
<div
|
||||||
</button>
|
className="sample-item-title"
|
||||||
|
>
|
||||||
<button
|
title 1
|
||||||
type="submit"
|
</div>
|
||||||
className="btn-s btn-primary-small"
|
<div
|
||||||
disabled={isPending}
|
className="sample-item-text"
|
||||||
|
>
|
||||||
|
1text text text text text text text text text text text text
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li
|
||||||
|
className="sample-item"
|
||||||
|
onClick={(e) => {
|
||||||
|
templateHandler(e)
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{t('submit-violation')}
|
<div
|
||||||
|
className="sample-item-title"
|
||||||
|
>
|
||||||
|
title 2
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="sample-item-text"
|
||||||
|
>
|
||||||
|
2text text text text text text text text text text text text
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li
|
||||||
|
className="sample-item"
|
||||||
|
onClick={(e) => {
|
||||||
|
templateHandler(e)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="sample-item-title"
|
||||||
|
>
|
||||||
|
title 3
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="sample-item-text"
|
||||||
|
>
|
||||||
|
3text text text text text text text text text text text text
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li
|
||||||
|
className="sample-item"
|
||||||
|
onClick={(e) => {
|
||||||
|
templateHandler(e)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="sample-item-title"
|
||||||
|
>
|
||||||
|
title 3
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="sample-item-text"
|
||||||
|
>
|
||||||
|
3text text text text text text text text text text text text
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li
|
||||||
|
className="sample-item"
|
||||||
|
onClick={(e) => {
|
||||||
|
templateHandler(e)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="sample-item-title"
|
||||||
|
>
|
||||||
|
title 3
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="sample-item-text"
|
||||||
|
>
|
||||||
|
3text text text text text text text text text text text text
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ModalWindow
|
||||||
|
state={isTemplateModalOpen}
|
||||||
|
callBack={setIsTemplateModalOpen}
|
||||||
|
>
|
||||||
|
<div className="template-modal-content">
|
||||||
|
<div className="template-modal-header">
|
||||||
|
<h3>{t('save-template')}</h3>
|
||||||
|
<button
|
||||||
|
className="template-modal-close"
|
||||||
|
onClick={() => setIsTemplateModalOpen(false)}
|
||||||
|
>
|
||||||
|
×
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
<div className="template-modal-body">
|
||||||
|
<div className="template-form-group">
|
||||||
|
<label htmlFor="templateName">
|
||||||
|
{t('template-name')}:
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="templateName"
|
||||||
|
type="text"
|
||||||
|
className="template-name-input"
|
||||||
|
placeholder={t('enter-template-name')}
|
||||||
|
value={templateName}
|
||||||
|
onChange={(e) => setTemplateName(e.target.value)}
|
||||||
|
autoFocus
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
<div className="template-preview">
|
||||||
<div
|
<div className="template-preview-label">
|
||||||
className="samples-wrapper"
|
{t('complaint-text-preview')}
|
||||||
>
|
</div>
|
||||||
<h5>Шаблоны</h5>
|
<div className="template-preview-text">
|
||||||
|
{noteText || t('no-text')}
|
||||||
<ul
|
</div>
|
||||||
className="samples-list"
|
|
||||||
>
|
|
||||||
<li
|
|
||||||
className="sample-item"
|
|
||||||
onClick={(e) => {
|
|
||||||
templateHandler(e)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="sample-item-title"
|
|
||||||
>
|
|
||||||
title 1
|
|
||||||
</div>
|
</div>
|
||||||
<div
|
</div>
|
||||||
className="sample-item-text"
|
<div className="template-modal-footer">
|
||||||
|
<button
|
||||||
|
className="btn-s btn-primary-small"
|
||||||
|
onClick={() => setIsTemplateModalOpen(false)}
|
||||||
>
|
>
|
||||||
1text text text text text text text text text text text text
|
{t('cancel')}
|
||||||
</div>
|
</button>
|
||||||
</li>
|
<button
|
||||||
<li
|
className="btn-s btn-resolve"
|
||||||
className="sample-item"
|
onClick={saveTemplateHandler}
|
||||||
onClick={(e) => {
|
|
||||||
templateHandler(e)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="sample-item-title"
|
|
||||||
>
|
>
|
||||||
title 2
|
{t('save')}
|
||||||
</div>
|
</button>
|
||||||
<div
|
</div>
|
||||||
className="sample-item-text"
|
</div>
|
||||||
>
|
</ModalWindow>
|
||||||
2text text text text text text text text text text text text
|
</>
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
<li
|
|
||||||
className="sample-item"
|
|
||||||
onClick={(e) => {
|
|
||||||
templateHandler(e)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="sample-item-title"
|
|
||||||
>
|
|
||||||
title 3
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="sample-item-text"
|
|
||||||
>
|
|
||||||
3text text text text text text text text text text text text
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li
|
|
||||||
className="sample-item"
|
|
||||||
onClick={(e) => {
|
|
||||||
templateHandler(e)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="sample-item-title"
|
|
||||||
>
|
|
||||||
title 3
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="sample-item-text"
|
|
||||||
>
|
|
||||||
3text text text text text text text text text text text text
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li
|
|
||||||
className="sample-item"
|
|
||||||
onClick={(e) => {
|
|
||||||
templateHandler(e)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="sample-item-title"
|
|
||||||
>
|
|
||||||
title 3
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="sample-item-text"
|
|
||||||
>
|
|
||||||
3text text text text text text text text text text text text
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
if (isLoadingComplain) {
|
if (isLoadingComplain) {
|
||||||
|
|||||||
@@ -454,7 +454,16 @@
|
|||||||
"select-at-least-one-filter": "Select at least one filter",
|
"select-at-least-one-filter": "Select at least one filter",
|
||||||
"select-document-to-upload": "Select document(s) to upload",
|
"select-document-to-upload": "Select document(s) to upload",
|
||||||
"uploading-id-images": "Uploading ID images",
|
"uploading-id-images": "Uploading ID images",
|
||||||
"tracking": "Tracking"
|
"tracking": "Tracking",
|
||||||
|
"save-template": "Save template",
|
||||||
|
"save": "Save",
|
||||||
|
"template-name": "Template name",
|
||||||
|
"enter-template-name": "Enter template name",
|
||||||
|
"complaint-text-preview": "Complaint text preview",
|
||||||
|
"no-text": "No text",
|
||||||
|
"please-enter-complaint-text-first": "Please enter complaint text first",
|
||||||
|
"please-enter-template-name": "Please enter template name",
|
||||||
|
"template-saved-successfully": "Template saved successfully"
|
||||||
},
|
},
|
||||||
"Login-register-form": {
|
"Login-register-form": {
|
||||||
"and": "and",
|
"and": "and",
|
||||||
|
|||||||
@@ -454,7 +454,16 @@
|
|||||||
"select-at-least-one-filter": "Выберите хотя бы один фильтр",
|
"select-at-least-one-filter": "Выберите хотя бы один фильтр",
|
||||||
"select-document-to-upload": "Выберите документ(ы) для загрузки",
|
"select-document-to-upload": "Выберите документ(ы) для загрузки",
|
||||||
"uploading-id-images": "Загрузка изображений удостоверения личности",
|
"uploading-id-images": "Загрузка изображений удостоверения личности",
|
||||||
"tracking": "Отслеживание"
|
"tracking": "Отслеживание",
|
||||||
|
"save-template": "Сохранить шаблон",
|
||||||
|
"save": "Сохранить",
|
||||||
|
"template-name": "Название шаблона",
|
||||||
|
"enter-template-name": "Введите название шаблона",
|
||||||
|
"complaint-text-preview": "Предварительный просмотр текста жалобы",
|
||||||
|
"no-text": "Нет текста",
|
||||||
|
"please-enter-complaint-text-first": "Пожалуйста, сначала введите текст жалобы",
|
||||||
|
"please-enter-template-name": "Пожалуйста, введите название шаблона",
|
||||||
|
"template-saved-successfully": "Шаблон успешно сохранен"
|
||||||
},
|
},
|
||||||
"Login-register-form": {
|
"Login-register-form": {
|
||||||
"and": "и",
|
"and": "и",
|
||||||
|
|||||||
Reference in New Issue
Block a user