feat: детальное отображение параметров повторяющихся событий
Backend: - Добавлено поле rule_data в EventSerializer - get_rule_data() возвращает частоту, параметры и описание правила - Использует rule.get_params() для получения распарсенных параметров Frontend: - Добавлены константы FREQUENCY_LABELS и WEEKDAY_LABELS для русификации - Новый блок с детальной информацией о повторении в синем фоне - Отображается частота (WEEKLY, MONTHLY и т.д.) - Дни недели для еженедельных событий (ПН, ВТ, СР...) - Количество повторений (count) - Дата окончания повторения (end_recurring_period) - Подсказка о невозможности редактирования параметров Проблема: пользователь не видел детали повторяющихся событий. Решение: красивый информационный блок с полной информацией о правиле.
This commit is contained in:
parent
bdfc0f247c
commit
4988f1eee7
@ -309,6 +309,7 @@ class EventSerializer(serializers.ModelSerializer):
|
||||
|
||||
calendar_name = serializers.CharField(source='calendar.name', read_only=True)
|
||||
rule_description = serializers.CharField(source='rule.description', read_only=True, allow_null=True)
|
||||
rule_data = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
model = Event
|
||||
@ -322,6 +323,7 @@ class EventSerializer(serializers.ModelSerializer):
|
||||
'calendar_name',
|
||||
'rule',
|
||||
'rule_description',
|
||||
'rule_data',
|
||||
'end_recurring_period',
|
||||
'color_event',
|
||||
'creator',
|
||||
@ -330,6 +332,20 @@ class EventSerializer(serializers.ModelSerializer):
|
||||
]
|
||||
read_only_fields = ['id', 'created_on', 'updated_on']
|
||||
|
||||
def get_rule_data(self, obj):
|
||||
"""Возвращает детальную информацию о правиле повторения."""
|
||||
if not obj.rule:
|
||||
return None
|
||||
|
||||
rule = obj.rule
|
||||
params = rule.get_params()
|
||||
|
||||
return {
|
||||
'frequency': rule.frequency,
|
||||
'params': params,
|
||||
'description': rule.description,
|
||||
}
|
||||
|
||||
def validate(self, attrs):
|
||||
"""Валидация start/end."""
|
||||
start = attrs.get('start')
|
||||
|
||||
@ -15,6 +15,28 @@ interface ViewEventDetailsModalProps {
|
||||
showParticipants?: boolean;
|
||||
}
|
||||
|
||||
// Маппинг частот на русский
|
||||
const FREQUENCY_LABELS: Record<string, string> = {
|
||||
YEARLY: "Каждый год",
|
||||
MONTHLY: "Каждый месяц",
|
||||
WEEKLY: "Каждую неделю",
|
||||
DAILY: "Каждый день",
|
||||
HOURLY: "Каждый час",
|
||||
MINUTELY: "Каждую минуту",
|
||||
SECONDLY: "Каждую секунду",
|
||||
};
|
||||
|
||||
// Маппинг дней недели (0 = Monday в dateutil.rrule)
|
||||
const WEEKDAY_LABELS: Record<number, string> = {
|
||||
0: "ПН",
|
||||
1: "ВТ",
|
||||
2: "СР",
|
||||
3: "ЧТ",
|
||||
4: "ПТ",
|
||||
5: "СБ",
|
||||
6: "ВС",
|
||||
};
|
||||
|
||||
export function ViewEventDetailsModal({
|
||||
isOpen,
|
||||
onClose,
|
||||
@ -111,14 +133,36 @@ export function ViewEventDetailsModal({
|
||||
</div>
|
||||
|
||||
{/* Recurring Info */}
|
||||
{event.rule && event.end_recurring_period && (
|
||||
<div className="flex items-start gap-2.5">
|
||||
<Calendar size={18} className="text-gray-400 mt-0.5 flex-shrink-0" />
|
||||
<div className="flex-1">
|
||||
<p className="text-sm font-medium text-gray-700 mb-1">Повторение</p>
|
||||
<p className="text-xs text-gray-600">
|
||||
До {formatDate(event.end_recurring_period)}
|
||||
</p>
|
||||
{event.rule && event.rule_data && (
|
||||
<div className="rounded-lg bg-blue-50 border border-blue-200 p-4 space-y-2">
|
||||
<div className="flex items-center gap-2 text-blue-700 font-medium text-sm">
|
||||
<Calendar size={16} />
|
||||
<span>Повторяющееся событие</span>
|
||||
</div>
|
||||
<div className="text-sm text-blue-600 space-y-1">
|
||||
<div>
|
||||
Частота: <span className="font-medium">{FREQUENCY_LABELS[event.rule_data.frequency] || event.rule_data.frequency}</span>
|
||||
</div>
|
||||
{event.rule_data.params?.byweekday && (
|
||||
<div>
|
||||
Дни недели: <span className="font-medium">
|
||||
{event.rule_data.params.byweekday.map((day: number) => WEEKDAY_LABELS[day]).join(", ")}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
{event.rule_data.params?.count && (
|
||||
<div>
|
||||
Повторений: <span className="font-medium">{event.rule_data.params.count}</span>
|
||||
</div>
|
||||
)}
|
||||
{event.end_recurring_period && (
|
||||
<div>
|
||||
До: <span className="font-medium">{formatDate(event.end_recurring_period)}</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="text-xs text-blue-600 mt-2">
|
||||
💡 Редактирование параметров повторения пока не поддерживается
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user