This commit is contained in:
206
panel/modals/ReactionEditModal.tsx
Normal file
206
panel/modals/ReactionEditModal.tsx
Normal file
@@ -0,0 +1,206 @@
|
||||
import { Component, createSignal, createEffect } from 'solid-js'
|
||||
import styles from '../styles/Modal.module.css'
|
||||
import Button from '../ui/Button'
|
||||
import Modal from '../ui/Modal'
|
||||
import HTMLEditor from '../ui/HTMLEditor'
|
||||
|
||||
interface ReactionEditModalProps {
|
||||
reaction: {
|
||||
id: number
|
||||
kind: string
|
||||
body: string
|
||||
created_at: number
|
||||
updated_at?: number
|
||||
deleted_at?: number
|
||||
reply_to?: number
|
||||
created_by: {
|
||||
id: number
|
||||
name: string
|
||||
email: string
|
||||
slug: string
|
||||
}
|
||||
shout: {
|
||||
id: number
|
||||
title: string
|
||||
slug: string
|
||||
layout: string
|
||||
created_at: number
|
||||
published_at?: number
|
||||
deleted_at?: number
|
||||
}
|
||||
stat: {
|
||||
comments_count: number
|
||||
rating: number
|
||||
}
|
||||
}
|
||||
isOpen: boolean
|
||||
onClose: () => void
|
||||
onSave: (reaction: { id: number; body?: string; deleted_at?: number }) => Promise<void>
|
||||
}
|
||||
|
||||
/**
|
||||
* Модальное окно для редактирования реакции
|
||||
*/
|
||||
const ReactionEditModal: Component<ReactionEditModalProps> = (props) => {
|
||||
const [body, setBody] = createSignal('')
|
||||
const [loading, setLoading] = createSignal(false)
|
||||
const [error, setError] = createSignal('')
|
||||
|
||||
// Инициализация данных при изменении реакции
|
||||
createEffect(() => {
|
||||
if (props.reaction) {
|
||||
setBody(props.reaction.body || '')
|
||||
setError('')
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* Обработка сохранения изменений
|
||||
*/
|
||||
async function handleSave() {
|
||||
try {
|
||||
setLoading(true)
|
||||
setError('')
|
||||
|
||||
const updateData: { id: number; body?: string; deleted_at?: number } = {
|
||||
id: props.reaction.id,
|
||||
body: body(),
|
||||
}
|
||||
|
||||
await props.onSave(updateData)
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : 'Ошибка сохранения')
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Получает название типа реакции на русском
|
||||
*/
|
||||
const getReactionName = (kind: string): string => {
|
||||
switch (kind) {
|
||||
case 'LIKE':
|
||||
return 'Лайк'
|
||||
case 'DISLIKE':
|
||||
return 'Дизлайк'
|
||||
case 'COMMENT':
|
||||
return 'Комментарий'
|
||||
case 'QUOTE':
|
||||
return 'Цитата'
|
||||
case 'AGREE':
|
||||
return 'Согласен'
|
||||
case 'DISAGREE':
|
||||
return 'Не согласен'
|
||||
case 'ASK':
|
||||
return 'Вопрос'
|
||||
case 'PROPOSE':
|
||||
return 'Предложение'
|
||||
case 'PROOF':
|
||||
return 'Доказательство'
|
||||
case 'DISPROOF':
|
||||
return 'Опровержение'
|
||||
case 'ACCEPT':
|
||||
return 'Принять'
|
||||
case 'REJECT':
|
||||
return 'Отклонить'
|
||||
case 'CREDIT':
|
||||
return 'Упоминание'
|
||||
case 'SILENT':
|
||||
return 'Причастность'
|
||||
default:
|
||||
return kind
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal isOpen={props.isOpen} onClose={props.onClose} title="Редактирование реакции">
|
||||
<div class={styles['modal-content']}>
|
||||
{error() && (
|
||||
<div class={styles['error-message']}>
|
||||
{error()}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div class={styles['form-group']}>
|
||||
<label class={styles['form-label']}>ID реакции:</label>
|
||||
<input
|
||||
type="text"
|
||||
value={props.reaction.id}
|
||||
disabled
|
||||
class={styles['form-input']}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class={styles['form-group']}>
|
||||
<label class={styles['form-label']}>Тип реакции:</label>
|
||||
<input
|
||||
type="text"
|
||||
value={getReactionName(props.reaction.kind)}
|
||||
disabled
|
||||
class={styles['form-input']}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class={styles['form-group']}>
|
||||
<label class={styles['form-label']}>Автор:</label>
|
||||
<input
|
||||
type="text"
|
||||
value={`${props.reaction.created_by.name || 'Без имени'} (${props.reaction.created_by.email})`}
|
||||
disabled
|
||||
class={styles['form-input']}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class={styles['form-group']}>
|
||||
<label class={styles['form-label']}>Публикация:</label>
|
||||
<input
|
||||
type="text"
|
||||
value={`${props.reaction.shout.title} (ID: ${props.reaction.shout.id})`}
|
||||
disabled
|
||||
class={styles['form-input']}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class={styles['form-group']}>
|
||||
<label class={styles['form-label']}>Текст реакции:</label>
|
||||
<HTMLEditor
|
||||
value={body()}
|
||||
onInput={(value) => setBody(value)}
|
||||
placeholder="Введите текст реакции (поддерживается HTML)..."
|
||||
rows={6}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class={styles['form-group']}>
|
||||
<label class={styles['form-label']}>Статистика:</label>
|
||||
<div class={styles['stat-info']}>
|
||||
<span>Рейтинг: {props.reaction.stat.rating}</span>
|
||||
<span>Комментариев: {props.reaction.stat.comments_count}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class={styles['form-group']}>
|
||||
<label class={styles['form-label']}>Статус:</label>
|
||||
<input
|
||||
type="text"
|
||||
value={props.reaction.deleted_at ? 'Удалено' : 'Активно'}
|
||||
disabled
|
||||
class={styles['form-input']}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class={styles['modal-actions']}>
|
||||
<Button variant="secondary" onClick={props.onClose} disabled={loading()}>
|
||||
Отмена
|
||||
</Button>
|
||||
<Button variant="primary" onClick={handleSave} disabled={loading()}>
|
||||
{loading() ? 'Сохранение...' : 'Сохранить'}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
|
||||
export default ReactionEditModal
|
Reference in New Issue
Block a user