feat: premium UI redesign — glassmorphism, gradient accents, ambient background
All checks were successful
Deploy / deploy (push) Successful in 2m40s

This commit is contained in:
Cosmo
2026-04-22 18:38:31 +00:00
parent 4874466985
commit eb644ff341
8 changed files with 763 additions and 436 deletions

View File

@@ -27,18 +27,24 @@ function AddEventModal({ defaultDate, onClose, onSaved }: { defaultDate: string;
const [saving, setSaving] = useState(false)
const [error, setError] = useState('')
const inputStyle = {
padding: '12px 16px',
borderRadius: 14,
background: 'rgba(255,255,255,0.05)',
border: '1px solid rgba(255,255,255,0.08)',
color: 'var(--text-primary)',
fontSize: 14,
outline: 'none',
fontFamily: 'inherit',
transition: 'border-color 0.2s ease',
}
const save = async () => {
if (!title.trim()) { setError('Введите название'); return }
setSaving(true)
setError('')
try {
const body = {
title: title.trim(),
date,
startTime: allDay ? null : startTime,
endTime: allDay ? null : endTime,
allDay,
}
const body = { title: title.trim(), date, startTime: allDay ? null : startTime, endTime: allDay ? null : endTime, allDay }
const r = await fetch('/api/calendar', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) })
const d = await r.json()
if (d.error) throw new Error(d.error)
@@ -50,31 +56,20 @@ function AddEventModal({ defaultDate, onClose, onSaved }: { defaultDate: string;
}
return (
<div style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.6)', zIndex: 100, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 20 }} onClick={onClose}>
<div style={{ background: 'var(--bg)', border: '1px solid rgba(255,255,255,0.1)', borderRadius: 20, padding: 24, maxWidth: 340, width: '100%' }} onClick={e => e.stopPropagation()}>
<div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 20 }}>
<span style={{ fontSize: 16, fontWeight: 700, color: 'var(--text-primary)' }}>Новое событие</span>
<button onClick={onClose} style={{ background: 'none', border: 'none', color: 'var(--text-secondary)', cursor: 'pointer' }}><X size={18} /></button>
<div style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.6)', backdropFilter: 'blur(8px)', zIndex: 100, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 20 }} onClick={onClose}>
<div style={{ background: 'rgba(18,18,35,0.95)', backdropFilter: 'blur(40px)', border: '1px solid rgba(255,255,255,0.08)', borderRadius: 24, padding: 28, maxWidth: 360, width: '100%', boxShadow: '0 25px 60px rgba(0,0,0,0.5)' }} onClick={e => e.stopPropagation()}>
<div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 24 }}>
<span style={{ fontSize: 18, fontWeight: 700, color: 'var(--text-primary)' }}>Новое событие</span>
<button onClick={onClose} style={{ color: 'var(--text-secondary)', padding: 4 }}><X size={18} /></button>
</div>
<div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
<input
value={title}
onChange={e => setTitle(e.target.value)}
placeholder="Название события"
autoFocus
style={{ padding: '10px 14px', borderRadius: 10, background: 'rgba(255,255,255,0.06)', border: '1px solid rgba(255,255,255,0.1)', color: 'var(--text-primary)', fontSize: 14, outline: 'none' }}
/>
<input
type="date"
value={date}
onChange={e => setDate(e.target.value)}
style={{ padding: '10px 14px', borderRadius: 10, background: 'rgba(255,255,255,0.06)', border: '1px solid rgba(255,255,255,0.1)', color: 'var(--text-primary)', fontSize: 14, outline: 'none' }}
/>
<input value={title} onChange={e => setTitle(e.target.value)} placeholder="Название события" autoFocus style={inputStyle} />
<input type="date" value={date} onChange={e => setDate(e.target.value)} style={inputStyle} />
{!allDay && (
<div style={{ display: 'flex', gap: 8 }}>
<input type="time" value={startTime} onChange={e => setStartTime(e.target.value)} style={{ flex: 1, padding: '10px 14px', borderRadius: 10, background: 'rgba(255,255,255,0.06)', border: '1px solid rgba(255,255,255,0.1)', color: 'var(--text-primary)', fontSize: 14, outline: 'none' }} />
<input type="time" value={endTime} onChange={e => setEndTime(e.target.value)} style={{ flex: 1, padding: '10px 14px', borderRadius: 10, background: 'rgba(255,255,255,0.06)', border: '1px solid rgba(255,255,255,0.1)', color: 'var(--text-primary)', fontSize: 14, outline: 'none' }} />
<input type="time" value={startTime} onChange={e => setStartTime(e.target.value)} style={{ ...inputStyle, flex: 1 }} />
<input type="time" value={endTime} onChange={e => setEndTime(e.target.value)} style={{ ...inputStyle, flex: 1 }} />
</div>
)}
<label style={{ display: 'flex', alignItems: 'center', gap: 8, color: 'var(--text-secondary)', fontSize: 13, cursor: 'pointer' }}>
@@ -85,7 +80,17 @@ function AddEventModal({ defaultDate, onClose, onSaved }: { defaultDate: string;
<button
onClick={save}
disabled={saving}
style={{ padding: '11px', borderRadius: 12, background: saving ? 'rgba(99,102,241,0.3)' : 'rgba(99,102,241,0.5)', border: '1px solid rgba(99,102,241,0.5)', color: '#a5b4fc', fontSize: 14, fontWeight: 600, cursor: saving ? 'default' : 'pointer', touchAction: 'manipulation' }}
style={{
padding: '13px',
borderRadius: 14,
background: saving ? 'rgba(99,102,241,0.2)' : 'linear-gradient(135deg, rgba(99,102,241,0.4), rgba(139,92,246,0.3))',
border: '1px solid rgba(129,140,248,0.3)',
color: '#a5b4fc',
fontSize: 14,
fontWeight: 600,
cursor: saving ? 'default' : 'pointer',
transition: 'all 0.25s ease',
}}
>
{saving ? 'Сохранение...' : 'Создать событие'}
</button>
@@ -102,9 +107,9 @@ export default function CalendarTab() {
const [loading, setLoading] = useState(true)
const [selectedEvent, setSelectedEvent] = useState<CalendarEvent | null>(null)
const [showAddModal, setShowAddModal] = useState(false)
const [addDate, setAddDate] = useState<string>('')
const [deleting, setDeleting] = useState(false)
const [confirmDelete, setConfirmDelete] = useState(false)
const [addDate, setAddDate] = useState<string>('')
useEffect(() => {
setLoading(true)
@@ -114,7 +119,6 @@ export default function CalendarTab() {
.catch(() => setLoading(false))
}, [year, month])
const deleteEvent = async (event: CalendarEvent) => {
setDeleting(true)
try {
@@ -131,15 +135,12 @@ export default function CalendarTab() {
}
}
// Upcoming events (next 30 days)
const upcoming = events
.filter(e => new Date(e.start) >= new Date())
.slice(0, 6)
// Build calendar grid
const firstDay = new Date(year, month, 1)
const lastDay = new Date(year, month + 1, 0)
// Monday-based week: 0=Mon, 6=Sun
const startOffset = (firstDay.getDay() + 6) % 7
const totalCells = Math.ceil((startOffset + lastDay.getDate()) / 7) * 7
const cells: (number | null)[] = []
@@ -161,25 +162,46 @@ export default function CalendarTab() {
const today = new Date()
return (
<div style={{ flex: 1, display: 'flex', overflow: 'hidden', padding: '12px 16px 16px', gap: 16 }}>
<div style={{ flex: 1, display: 'flex', overflow: 'hidden', padding: '16px 24px 24px', gap: 20 }}>
{/* Main calendar grid */}
<div style={{ flex: 1, display: 'flex', flexDirection: 'column', minWidth: 0 }}>
{/* Header */}
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 16 }}>
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 18 }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
<button onClick={prevMonth} style={{ width: 32, height: 32, borderRadius: 8, background: 'rgba(255,255,255,0.06)', border: '1px solid rgba(255,255,255,0.1)', color: 'var(--text-primary)', cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<button onClick={prevMonth} style={{
width: 36, height: 36, borderRadius: 12,
background: 'rgba(255,255,255,0.04)',
border: '1px solid rgba(255,255,255,0.06)',
color: 'var(--text-primary)',
display: 'flex', alignItems: 'center', justifyContent: 'center',
transition: 'all 0.2s ease',
}}>
<ChevronLeft size={16} />
</button>
<span style={{ fontSize: 18, fontWeight: 700, color: 'var(--text-primary)', minWidth: 160, textAlign: 'center' }}>
<span style={{ fontSize: 20, fontWeight: 700, color: 'var(--text-primary)', minWidth: 180, textAlign: 'center' }}>
{MONTHS[month]} {year}
</span>
<button onClick={nextMonth} style={{ width: 32, height: 32, borderRadius: 8, background: 'rgba(255,255,255,0.06)', border: '1px solid rgba(255,255,255,0.1)', color: 'var(--text-primary)', cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<button onClick={nextMonth} style={{
width: 36, height: 36, borderRadius: 12,
background: 'rgba(255,255,255,0.04)',
border: '1px solid rgba(255,255,255,0.06)',
color: 'var(--text-primary)',
display: 'flex', alignItems: 'center', justifyContent: 'center',
transition: 'all 0.2s ease',
}}>
<ChevronRight size={16} />
</button>
</div>
<button
onClick={() => { setAddDate(today.toISOString().split('T')[0]); setShowAddModal(true) }}
style={{ display: 'flex', alignItems: 'center', gap: 6, padding: '8px 14px', borderRadius: 10, background: 'rgba(99,102,241,0.2)', border: '1px solid rgba(99,102,241,0.4)', color: '#a5b4fc', fontSize: 13, fontWeight: 600, cursor: 'pointer', touchAction: 'manipulation' }}
style={{
display: 'flex', alignItems: 'center', gap: 6,
padding: '10px 18px', borderRadius: 14,
background: 'linear-gradient(135deg, rgba(99,102,241,0.2), rgba(139,92,246,0.15))',
border: '1px solid rgba(129,140,248,0.25)',
color: '#a5b4fc', fontSize: 13, fontWeight: 600,
transition: 'all 0.25s ease',
}}
>
<Plus size={15} />
Событие
@@ -187,18 +209,24 @@ export default function CalendarTab() {
</div>
{/* Weekday headers */}
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(7, 1fr)', marginBottom: 4 }}>
{WEEKDAYS.map(d => (
<div key={d} style={{ textAlign: 'center', fontSize: 11, fontWeight: 600, color: 'var(--text-secondary)', textTransform: 'uppercase', padding: '4px 0' }}>{d}</div>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(7, 1fr)', marginBottom: 6 }}>
{WEEKDAYS.map((d, i) => (
<div key={d} style={{
textAlign: 'center', fontSize: 11, fontWeight: 600,
color: i >= 5 ? 'rgba(248,113,113,0.5)' : 'var(--text-secondary)',
textTransform: 'uppercase', padding: '6px 0', letterSpacing: '0.05em',
}}>{d}</div>
))}
</div>
{/* Calendar cells */}
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(7, 1fr)', flex: 1, gap: 2 }}>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(7, 1fr)', flex: 1, gap: 3 }}>
{cells.map((day, idx) => {
if (!day) return <div key={idx} />
const dayEvents = getEventsForDay(day)
const isToday = today.getFullYear() === year && today.getMonth() === month && today.getDate() === day
const dayOfWeek = (startOffset + day - 1) % 7
const isWeekend = dayOfWeek >= 5
return (
<div
key={idx}
@@ -210,34 +238,40 @@ export default function CalendarTab() {
}
}}
style={{
borderRadius: 8,
padding: '4px 3px',
background: isToday ? 'rgba(99,102,241,0.12)' : 'rgba(255,255,255,0.02)',
border: isToday ? '1px solid rgba(99,102,241,0.35)' : '1px solid transparent',
borderRadius: 12,
padding: '5px 4px',
background: isToday
? 'linear-gradient(135deg, rgba(99,102,241,0.15), rgba(139,92,246,0.08))'
: 'rgba(255,255,255,0.015)',
border: isToday
? '1px solid rgba(129,140,248,0.3)'
: '1px solid transparent',
cursor: 'pointer',
minHeight: 52,
minHeight: 56,
display: 'flex',
flexDirection: 'column',
gap: 2,
touchAction: 'manipulation',
transition: 'all 0.2s ease',
}}
>
<span style={{ fontSize: 12, fontWeight: isToday ? 700 : 400, color: isToday ? '#a5b4fc' : 'var(--text-secondary)', textAlign: 'right', paddingRight: 3 }}>{day}</span>
<span style={{
fontSize: 12,
fontWeight: isToday ? 700 : 500,
color: isToday ? '#a5b4fc' : isWeekend ? 'rgba(248,113,113,0.6)' : 'var(--text-secondary)',
textAlign: 'right', paddingRight: 4,
}}>{day}</span>
{dayEvents.slice(0, 2).map(e => (
<div
key={e.id}
onClick={ev => { ev.stopPropagation(); setSelectedEvent(e) }}
style={{
fontSize: 10,
fontWeight: 600,
background: e.color + '33',
border: `1px solid ${e.color}55`,
fontSize: 10, fontWeight: 600,
background: e.color + '1a',
border: `1px solid ${e.color}30`,
color: e.color,
borderRadius: 4,
padding: '1px 4px',
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
borderRadius: 6,
padding: '2px 5px',
overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
cursor: 'pointer',
}}
>
@@ -254,10 +288,18 @@ export default function CalendarTab() {
</div>
{/* Right panel: upcoming events */}
<div style={{ width: 200, flexShrink: 0, display: 'flex', flexDirection: 'column', gap: 8, overflowY: 'auto' }}>
<div style={{ fontSize: 11, fontWeight: 600, color: 'var(--text-secondary)', textTransform: 'uppercase', letterSpacing: '0.08em', marginBottom: 4 }}>Ближайшие</div>
<div style={{
width: 220, flexShrink: 0,
display: 'flex', flexDirection: 'column', gap: 10,
overflowY: 'auto',
background: 'rgba(255,255,255,0.02)',
borderRadius: 22,
padding: '20px 16px',
border: '1px solid rgba(255,255,255,0.04)',
}}>
<div style={{ fontSize: 11, fontWeight: 600, color: 'var(--text-secondary)', textTransform: 'uppercase', letterSpacing: '0.1em', marginBottom: 4 }}>Ближайшие</div>
{upcoming.length === 0 && !loading && (
<div style={{ fontSize: 13, color: 'var(--text-secondary)' }}>Нет событий</div>
<div style={{ fontSize: 13, color: 'var(--text-secondary)', padding: '20px 0', textAlign: 'center' }}>Нет событий</div>
)}
{upcoming.map(e => {
const d = new Date(e.start)
@@ -266,25 +308,29 @@ export default function CalendarTab() {
key={e.id}
onClick={() => setSelectedEvent(e)}
style={{
borderRadius: 12,
padding: '10px 12px',
background: e.color + '18',
border: `1px solid ${e.color}33`,
borderRadius: 16,
padding: '14px 14px',
background: `${e.color}0c`,
border: `1px solid ${e.color}1a`,
cursor: 'pointer',
touchAction: 'manipulation',
transition: 'all 0.25s ease',
}}
>
<div style={{ display: 'flex', alignItems: 'center', gap: 6, marginBottom: 4 }}>
<div style={{ width: 28, height: 28, borderRadius: 8, background: e.color + '33', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 8 }}>
<div style={{
width: 32, height: 32, borderRadius: 10,
background: `${e.color}1a`,
display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0,
}}>
<span style={{ fontSize: 14, fontWeight: 700, color: e.color }}>{d.getDate()}</span>
</div>
<div style={{ fontSize: 10, color: e.color, fontWeight: 600 }}>{MONTHS[d.getMonth()].slice(0, 3)}</div>
</div>
<div style={{ fontSize: 12, fontWeight: 600, color: 'var(--text-primary)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{e.title}</div>
<div style={{ fontSize: 11, color: 'var(--text-secondary)', marginTop: 2 }}>
<div style={{ fontSize: 13, fontWeight: 600, color: 'var(--text-primary)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{e.title}</div>
<div style={{ fontSize: 11, color: 'var(--text-secondary)', marginTop: 4 }}>
{e.allDay ? 'Весь день' : d.toLocaleTimeString('ru-RU', { hour: '2-digit', minute: '2-digit' })}
</div>
<div style={{ fontSize: 10, color: e.color, marginTop: 3, fontWeight: 500 }}>{e.ownerName}</div>
<div style={{ fontSize: 10, color: e.color, marginTop: 4, fontWeight: 500 }}>{e.ownerName}</div>
</div>
)
})}
@@ -292,38 +338,66 @@ export default function CalendarTab() {
{/* Event detail modal */}
{selectedEvent && (
<div style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.6)', zIndex: 100, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 20 }} onClick={() => { setSelectedEvent(null); setConfirmDelete(false) }}>
<div style={{ background: 'var(--bg)', border: '1px solid rgba(255,255,255,0.1)', borderRadius: 20, padding: 24, maxWidth: 360, width: '100%', boxShadow: '0 20px 60px rgba(0,0,0,0.5)' }} onClick={e => e.stopPropagation()}>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', marginBottom: 16 }}>
<div style={{ width: 4, height: 40, borderRadius: 2, background: selectedEvent.color, marginRight: 12, flexShrink: 0, marginTop: 2 }} />
<div style={{ flex: 1 }}>
<div style={{ fontSize: 16, fontWeight: 700, color: 'var(--text-primary)' }}>{selectedEvent.title}</div>
<div style={{ fontSize: 12, color: selectedEvent.color, fontWeight: 500, marginTop: 2 }}>{selectedEvent.ownerName}</div>
<div style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.6)', backdropFilter: 'blur(8px)', zIndex: 100, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 20 }} onClick={() => { setSelectedEvent(null); setConfirmDelete(false) }}>
<div style={{
background: 'rgba(18,18,35,0.95)',
backdropFilter: 'blur(40px)',
border: '1px solid rgba(255,255,255,0.08)',
borderRadius: 24, padding: 28, maxWidth: 380, width: '100%',
boxShadow: '0 25px 60px rgba(0,0,0,0.5)',
}} onClick={e => e.stopPropagation()}>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', marginBottom: 20 }}>
<div style={{ display: 'flex', gap: 14 }}>
<div style={{ width: 4, borderRadius: 3, background: selectedEvent.color, alignSelf: 'stretch', minHeight: 44, flexShrink: 0 }} />
<div>
<div style={{ fontSize: 18, fontWeight: 700, color: 'var(--text-primary)' }}>{selectedEvent.title}</div>
<div style={{ fontSize: 13, color: selectedEvent.color, fontWeight: 500, marginTop: 3 }}>{selectedEvent.ownerName}</div>
</div>
</div>
<button onClick={() => setSelectedEvent(null)} style={{ background: 'none', border: 'none', color: 'var(--text-secondary)', cursor: 'pointer', padding: 4 }}><X size={18} /></button>
<button onClick={() => { setSelectedEvent(null); setConfirmDelete(false) }} style={{ color: 'var(--text-secondary)', padding: 4 }}><X size={18} /></button>
</div>
<div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 8, color: 'var(--text-secondary)', fontSize: 13 }}>
<Clock size={14} />
<div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
<div style={{
display: 'flex', alignItems: 'center', gap: 10,
padding: '10px 14px', borderRadius: 12,
background: 'rgba(255,255,255,0.03)',
color: 'var(--text-secondary)', fontSize: 13,
}}>
<Clock size={15} />
{selectedEvent.allDay
? 'Весь день'
: `${new Date(selectedEvent.start).toLocaleString('ru-RU', { day: 'numeric', month: 'long', hour: '2-digit', minute: '2-digit' })} — ${new Date(selectedEvent.end).toLocaleTimeString('ru-RU', { hour: '2-digit', minute: '2-digit' })}`
}
</div>
{selectedEvent.location && (
<div style={{ display: 'flex', alignItems: 'center', gap: 8, color: 'var(--text-secondary)', fontSize: 13 }}>
<MapPin size={14} /> {selectedEvent.location}
<div style={{
display: 'flex', alignItems: 'center', gap: 10,
padding: '10px 14px', borderRadius: 12,
background: 'rgba(255,255,255,0.03)',
color: 'var(--text-secondary)', fontSize: 13,
}}>
<MapPin size={15} /> {selectedEvent.location}
</div>
)}
{selectedEvent.description && (
<div style={{ fontSize: 13, color: 'var(--text-secondary)', marginTop: 4, lineHeight: 1.5 }}>{selectedEvent.description}</div>
<div style={{ fontSize: 13, color: 'var(--text-secondary)', marginTop: 4, lineHeight: 1.6 }}>{selectedEvent.description}</div>
)}
{/* Delete button */}
<div style={{ marginTop: 8, borderTop: '1px solid rgba(255,255,255,0.08)', paddingTop: 12 }}>
<div style={{ marginTop: 8, borderTop: '1px solid rgba(255,255,255,0.06)', paddingTop: 14 }}>
{!confirmDelete ? (
<button
onClick={() => setConfirmDelete(true)}
style={{ display: 'flex', alignItems: 'center', gap: 6, padding: '8px 14px', borderRadius: 10, background: 'rgba(239,68,68,0.1)', border: '1px solid rgba(239,68,68,0.3)', color: '#f87171', fontSize: 13, fontWeight: 600, cursor: 'pointer', touchAction: 'manipulation', width: '100%', justifyContent: 'center' }}
style={{
display: 'flex', alignItems: 'center', gap: 6,
padding: '10px 14px', borderRadius: 12,
background: 'rgba(239,68,68,0.08)',
border: '1px solid rgba(239,68,68,0.2)',
color: '#f87171', fontSize: 13, fontWeight: 600,
width: '100%', justifyContent: 'center',
transition: 'all 0.25s ease',
}}
>
<Trash2 size={14} />
Удалить событие
@@ -333,13 +407,26 @@ export default function CalendarTab() {
<button
onClick={() => deleteEvent(selectedEvent)}
disabled={deleting}
style={{ flex: 1, padding: '8px 14px', borderRadius: 10, background: deleting ? 'rgba(239,68,68,0.15)' : 'rgba(239,68,68,0.25)', border: '1px solid rgba(239,68,68,0.5)', color: '#f87171', fontSize: 13, fontWeight: 600, cursor: deleting ? 'default' : 'pointer', touchAction: 'manipulation' }}
style={{
flex: 1, padding: '10px 14px', borderRadius: 12,
background: deleting ? 'rgba(239,68,68,0.1)' : 'rgba(239,68,68,0.2)',
border: '1px solid rgba(239,68,68,0.35)',
color: '#f87171', fontSize: 13, fontWeight: 600,
cursor: deleting ? 'default' : 'pointer',
transition: 'all 0.25s ease',
}}
>
{deleting ? 'Удаление...' : 'Да, удалить'}
</button>
<button
onClick={() => setConfirmDelete(false)}
style={{ flex: 1, padding: '8px 14px', borderRadius: 10, background: 'rgba(255,255,255,0.06)', border: '1px solid rgba(255,255,255,0.1)', color: 'var(--text-secondary)', fontSize: 13, fontWeight: 600, cursor: 'pointer', touchAction: 'manipulation' }}
style={{
flex: 1, padding: '10px 14px', borderRadius: 12,
background: 'rgba(255,255,255,0.04)',
border: '1px solid rgba(255,255,255,0.08)',
color: 'var(--text-secondary)', fontSize: 13, fontWeight: 600,
transition: 'all 0.25s ease',
}}
>
Отмена
</button>
@@ -351,7 +438,6 @@ export default function CalendarTab() {
</div>
)}
{/* Add event modal */}
{showAddModal && (
<AddEventModal
defaultDate={addDate}