style: make CalendarEventModal more compact for mobile
Reduce padding, gaps, font sizes, and combine Status/Visibility into a single row for better usability on smaller screens. v1.36.1
This commit is contained in:
parent
b9c05571be
commit
d991e7a65b
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "my-weekly-todo-list",
|
||||
"version": "1.36.0",
|
||||
"version": "1.36.1",
|
||||
"description": "A web-based weekly task management application that organizes to-dos and calendar events in a single, intuitive weekly view",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
|
||||
@ -87,7 +87,6 @@ export default function CalendarEventModal({
|
||||
);
|
||||
const [newAttachmentUrl, setNewAttachmentUrl] = useState('');
|
||||
const [showMoreOptions, setShowMoreOptions] = useState(
|
||||
// Auto-expand if event has these fields set
|
||||
!!(event?.attendees?.length || event?.attachments?.length || (event?.busyStatus && event.busyStatus !== 'busy') || (event?.visibility && event.visibility !== 'default'))
|
||||
);
|
||||
|
||||
@ -143,7 +142,7 @@ export default function CalendarEventModal({
|
||||
case 'google': return <FontAwesomeIcon icon={faGoogle} style={{ opacity: 0.8 }} />;
|
||||
case 'apple': return <FontAwesomeIcon icon={faApple} style={{ opacity: 0.8 }} />;
|
||||
case 'outlook': return <FontAwesomeIcon icon={faMicrosoft} style={{ opacity: 0.8 }} />;
|
||||
case 'synology': return <FontAwesomeIcon icon={faServer} style={{ opacity: 0.8, fontSize: '0.8rem' }} />;
|
||||
case 'synology': return <FontAwesomeIcon icon={faServer} style={{ opacity: 0.8, fontSize: '0.75rem' }} />;
|
||||
default: return null;
|
||||
}
|
||||
};
|
||||
@ -165,7 +164,6 @@ export default function CalendarEventModal({
|
||||
setIsSaving(true);
|
||||
setError('');
|
||||
try {
|
||||
// Filter out "none" reminders
|
||||
const activeReminders = reminders.filter(r => r.minutes >= 0);
|
||||
|
||||
await onSave({
|
||||
@ -255,7 +253,6 @@ export default function CalendarEventModal({
|
||||
|
||||
const updateReminder = (index: number, minutes: number) => {
|
||||
if (minutes === -1) {
|
||||
// Remove this reminder
|
||||
setReminders(reminders.filter((_, i) => i !== index));
|
||||
return;
|
||||
}
|
||||
@ -270,30 +267,32 @@ export default function CalendarEventModal({
|
||||
|
||||
const rowStyle: React.CSSProperties = {
|
||||
display: 'flex', alignItems: 'center', justifyContent: 'space-between',
|
||||
padding: '0 10px', minHeight: '32px',
|
||||
};
|
||||
const labelStyle: React.CSSProperties = {
|
||||
fontSize: '0.9rem', color: 'var(--weekly-text-light)', fontWeight: 500,
|
||||
fontSize: '0.82rem', color: 'var(--weekly-text-light)', fontWeight: 500,
|
||||
};
|
||||
const selectStyle: React.CSSProperties = {
|
||||
background: 'transparent', border: 'none', textAlign: 'right' as const,
|
||||
fontSize: '0.9rem', cursor: 'pointer', outline: 'none', color: 'var(--weekly-text)',
|
||||
fontSize: '0.82rem', cursor: 'pointer', outline: 'none', color: 'var(--weekly-text)',
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="weekly-modal-overlay" onClick={onClose}>
|
||||
<div className="weekly-modal-content" onClick={e => e.stopPropagation()} style={{
|
||||
maxWidth: '450px',
|
||||
padding: '20px',
|
||||
borderRadius: '12px',
|
||||
maxWidth: '400px',
|
||||
width: 'calc(100vw - 16px)',
|
||||
padding: '12px',
|
||||
borderRadius: '10px',
|
||||
boxShadow: '0 10px 25px rgba(0,0,0,0.15)',
|
||||
border: '1px solid var(--weekly-border)',
|
||||
maxHeight: '90vh',
|
||||
maxHeight: '85vh',
|
||||
overflowY: 'auto',
|
||||
}}>
|
||||
{error && <div style={{ color: '#ef4444', marginBottom: '1rem', fontSize: '0.85rem', textAlign: 'center' }}>{error}</div>}
|
||||
{error && <div style={{ color: '#ef4444', marginBottom: '6px', fontSize: '0.8rem', textAlign: 'center' }}>{error}</div>}
|
||||
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: '12px' }}>
|
||||
{/* Title Input */}
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: '4px' }}>
|
||||
{/* Title */}
|
||||
<input
|
||||
type="text"
|
||||
value={title}
|
||||
@ -301,87 +300,74 @@ export default function CalendarEventModal({
|
||||
placeholder="New Event"
|
||||
autoFocus
|
||||
style={{
|
||||
width: '100%',
|
||||
padding: '12px 16px',
|
||||
fontSize: '1.25rem',
|
||||
fontWeight: 600,
|
||||
border: 'none',
|
||||
borderBottom: '1px solid var(--weekly-border)',
|
||||
borderRadius: '0',
|
||||
background: 'transparent',
|
||||
outline: 'none',
|
||||
marginBottom: '4px'
|
||||
width: '100%', padding: '6px 10px', fontSize: '1.05rem', fontWeight: 600,
|
||||
border: 'none', borderBottom: '1px solid var(--weekly-border)',
|
||||
borderRadius: '0', background: 'transparent', outline: 'none',
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Location Input */}
|
||||
{/* Location */}
|
||||
<input
|
||||
type="text"
|
||||
value={location}
|
||||
onChange={e => setLocation(e.target.value)}
|
||||
placeholder="Location or Video Call"
|
||||
style={{
|
||||
width: '100%',
|
||||
padding: '8px 16px',
|
||||
border: 'none',
|
||||
width: '100%', padding: '5px 10px', border: 'none',
|
||||
borderBottom: '1px solid var(--weekly-border)',
|
||||
borderRadius: '0',
|
||||
background: 'transparent',
|
||||
outline: 'none',
|
||||
fontSize: '0.95rem'
|
||||
borderRadius: '0', background: 'transparent', outline: 'none', fontSize: '0.82rem',
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Calendar row */}
|
||||
<div style={{ ...rowStyle, padding: '4px 16px', position: 'relative' }}>
|
||||
<div style={{ ...rowStyle, position: 'relative' }}>
|
||||
<span style={labelStyle}>Calendar</span>
|
||||
|
||||
<div ref={calendarSelectorRef} style={{ position: 'relative', flex: 1, display: 'flex', justifyContent: 'flex-end' }}>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => !event && setIsCalendarSelectorOpen(!isCalendarSelectorOpen)}
|
||||
disabled={!!event}
|
||||
style={{
|
||||
display: 'flex', alignItems: 'center', gap: '8px',
|
||||
display: 'flex', alignItems: 'center', gap: '6px',
|
||||
background: 'transparent', border: 'none', fontWeight: 500,
|
||||
cursor: event ? 'default' : 'pointer', outline: 'none',
|
||||
color: 'var(--weekly-text)', fontSize: '0.95rem',
|
||||
padding: '4px 0', maxWidth: '200px', justifyContent: 'flex-end'
|
||||
color: 'var(--weekly-text)', fontSize: '0.82rem',
|
||||
padding: '2px 0', maxWidth: '180px', justifyContent: 'flex-end'
|
||||
}}
|
||||
>
|
||||
<span style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
|
||||
{selectedCal?.summary || selectedCal?.title || 'Select Calendar'}
|
||||
</span>
|
||||
<div style={{
|
||||
width: '12px', height: '12px', borderRadius: '50%',
|
||||
width: '10px', height: '10px', borderRadius: '50%', flexShrink: 0,
|
||||
backgroundColor: selectedCal?.backgroundColor || selectedCal?.color || '#3b82f6'
|
||||
}} />
|
||||
{!event && (isCalendarSelectorOpen ? <ChevronUp size={14} /> : <ChevronDown size={14} />)}
|
||||
{!event && (isCalendarSelectorOpen ? <ChevronUp size={12} /> : <ChevronDown size={12} />)}
|
||||
</button>
|
||||
|
||||
{isCalendarSelectorOpen && (
|
||||
<div style={{
|
||||
position: 'absolute', top: '100%', right: 0, zIndex: 100,
|
||||
minWidth: '220px', backgroundColor: 'var(--weekly-bg-popover, #ffffff)',
|
||||
borderRadius: '10px', boxShadow: '0 4px 15px rgba(0,0,0,0.1)',
|
||||
border: '1px solid var(--weekly-border)', marginTop: '5px',
|
||||
padding: '6px', maxHeight: '250px', overflowY: 'auto'
|
||||
minWidth: '200px', backgroundColor: 'var(--weekly-bg-popover, #ffffff)',
|
||||
borderRadius: '8px', boxShadow: '0 4px 15px rgba(0,0,0,0.1)',
|
||||
border: '1px solid var(--weekly-border)', marginTop: '2px',
|
||||
padding: '4px', maxHeight: '200px', overflowY: 'auto'
|
||||
}}>
|
||||
{availableCalendars.map((cal: any) => (
|
||||
<div
|
||||
key={cal.id}
|
||||
onClick={() => { setCalendarId(cal.id); setIsCalendarSelectorOpen(false); }}
|
||||
style={{
|
||||
display: 'flex', alignItems: 'center', gap: '10px',
|
||||
padding: '8px 12px', borderRadius: '6px', cursor: 'pointer',
|
||||
fontSize: '0.9rem', color: 'var(--weekly-text)',
|
||||
display: 'flex', alignItems: 'center', gap: '8px',
|
||||
padding: '6px 10px', borderRadius: '5px', cursor: 'pointer',
|
||||
fontSize: '0.82rem', color: 'var(--weekly-text)',
|
||||
backgroundColor: calendarId === cal.id ? 'var(--weekly-selection, rgba(59, 130, 246, 0.1))' : 'transparent',
|
||||
transition: 'background 0.2s', textAlign: 'left'
|
||||
}}
|
||||
onMouseEnter={(e) => e.currentTarget.style.backgroundColor = 'var(--weekly-hover, rgba(0,0,0,0.05))'}
|
||||
onMouseLeave={(e) => e.currentTarget.style.backgroundColor = calendarId === cal.id ? 'var(--weekly-selection, rgba(59, 130, 246, 0.1))' : 'transparent'}
|
||||
>
|
||||
<div style={{ width: '10px', height: '10px', borderRadius: '50%', backgroundColor: cal.backgroundColor || cal.color || '#3b82f6', flexShrink: 0 }} />
|
||||
<div style={{ width: '8px', height: '8px', borderRadius: '50%', backgroundColor: cal.backgroundColor || cal.color || '#3b82f6', flexShrink: 0 }} />
|
||||
<span style={{ flex: 1, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
|
||||
{cal.summary || cal.title}
|
||||
</span>
|
||||
@ -395,50 +381,51 @@ export default function CalendarEventModal({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* All Day row */}
|
||||
<div style={{ ...rowStyle, padding: '4px 16px' }}>
|
||||
{/* All Day */}
|
||||
<div style={rowStyle}>
|
||||
<span style={labelStyle}>All Day</span>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={allDay}
|
||||
onChange={e => setAllDay(e.target.checked)}
|
||||
style={{ width: '18px', height: '18px', cursor: 'pointer' }}
|
||||
style={{ width: '16px', height: '16px', cursor: 'pointer' }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Date/Time rows */}
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: '8px', padding: '0 16px' }}>
|
||||
<div style={rowStyle}>
|
||||
{/* Start / End on same row when not all-day */}
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: '2px', padding: '0 10px' }}>
|
||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', minHeight: '30px' }}>
|
||||
<span style={labelStyle}>Starts</span>
|
||||
<input
|
||||
type={allDay ? "date" : "datetime-local"}
|
||||
value={allDay ? startDate.toISOString().split('T')[0] : toLocalISOString(startDate)}
|
||||
onChange={e => handleStartDateChange(e.target.value)}
|
||||
style={{
|
||||
padding: '4px 8px', border: 'none', borderRadius: '6px',
|
||||
padding: '2px 6px', border: 'none', borderRadius: '4px',
|
||||
background: 'var(--weekly-bg-secondary, #f3f4f6)',
|
||||
fontSize: '0.9rem', textAlign: 'center'
|
||||
fontSize: '0.8rem', textAlign: 'center',
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div style={rowStyle}>
|
||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', minHeight: '30px' }}>
|
||||
<span style={labelStyle}>Ends</span>
|
||||
<input
|
||||
type={allDay ? "date" : "datetime-local"}
|
||||
value={allDay ? endDate.toISOString().split('T')[0] : toLocalISOString(endDate)}
|
||||
onChange={e => setEndDate(new Date(e.target.value))}
|
||||
style={{
|
||||
padding: '4px 8px', border: 'none', borderRadius: '6px',
|
||||
padding: '2px 6px', border: 'none', borderRadius: '4px',
|
||||
background: 'var(--weekly-bg-secondary, #f3f4f6)',
|
||||
fontSize: '0.9rem', textAlign: 'center'
|
||||
fontSize: '0.8rem', textAlign: 'center',
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Meta Fields Group */}
|
||||
<div style={{ padding: '8px 16px', display: 'flex', flexDirection: 'column', gap: '12px', marginTop: '4px' }}>
|
||||
{/* Recurrence */}
|
||||
{/* Divider */}
|
||||
<div style={{ borderTop: '1px solid var(--weekly-border)', margin: '2px 10px' }} />
|
||||
|
||||
{/* Repeat */}
|
||||
<div style={rowStyle}>
|
||||
<span style={labelStyle}>Repeat</span>
|
||||
<select value={recurrence} onChange={e => setRecurrence(e.target.value)} style={selectStyle}>
|
||||
@ -450,11 +437,11 @@ export default function CalendarEventModal({
|
||||
</select>
|
||||
</div>
|
||||
|
||||
{/* Reminders */}
|
||||
<div>
|
||||
<div style={{ ...rowStyle, marginBottom: reminders.length > 0 ? '6px' : 0 }}>
|
||||
<span style={{ ...labelStyle, display: 'flex', alignItems: 'center', gap: '6px' }}>
|
||||
<Bell size={14} /> Alert
|
||||
{/* Alert */}
|
||||
<div style={{ padding: '0 10px' }}>
|
||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', minHeight: '32px' }}>
|
||||
<span style={{ ...labelStyle, display: 'flex', alignItems: 'center', gap: '4px' }}>
|
||||
<Bell size={12} /> Alert
|
||||
</span>
|
||||
{reminders.length === 0 && (
|
||||
<button onClick={addReminder} style={{ ...selectStyle, color: '#3b82f6', cursor: 'pointer', background: 'none', border: 'none' }}>
|
||||
@ -463,7 +450,7 @@ export default function CalendarEventModal({
|
||||
)}
|
||||
</div>
|
||||
{reminders.map((reminder, idx) => (
|
||||
<div key={idx} style={{ display: 'flex', alignItems: 'center', justifyContent: 'flex-end', gap: '8px', marginBottom: '4px' }}>
|
||||
<div key={idx} style={{ display: 'flex', alignItems: 'center', justifyContent: 'flex-end', gap: '4px', marginBottom: '2px' }}>
|
||||
<select
|
||||
value={reminder.minutes}
|
||||
onChange={e => updateReminder(idx, parseInt(e.target.value))}
|
||||
@ -474,20 +461,21 @@ export default function CalendarEventModal({
|
||||
))}
|
||||
</select>
|
||||
<button onClick={() => setReminders(reminders.filter((_, i) => i !== idx))}
|
||||
style={{ background: 'none', border: 'none', cursor: 'pointer', padding: '2px', color: 'var(--weekly-text-light)' }}>
|
||||
<X size={14} />
|
||||
style={{ background: 'none', border: 'none', cursor: 'pointer', padding: '1px', color: 'var(--weekly-text-light)' }}>
|
||||
<X size={12} />
|
||||
</button>
|
||||
</div>
|
||||
))}
|
||||
{reminders.length > 0 && reminders.length < 2 && (
|
||||
<button onClick={addReminder} style={{ fontSize: '0.85rem', color: '#3b82f6', background: 'none', border: 'none', cursor: 'pointer', padding: '2px 0' }}>
|
||||
<button onClick={addReminder} style={{ fontSize: '0.78rem', color: '#3b82f6', background: 'none', border: 'none', cursor: 'pointer', padding: '1px 0' }}>
|
||||
+ Add another alert
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Busy Status */}
|
||||
<div style={rowStyle}>
|
||||
{/* Status & Visibility side by side */}
|
||||
<div style={{ display: 'flex', gap: '8px', padding: '0 10px' }}>
|
||||
<div style={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'space-between', minHeight: '32px' }}>
|
||||
<span style={labelStyle}>Status</span>
|
||||
<select value={busyStatus} onChange={e => setBusyStatus(e.target.value)} style={selectStyle}>
|
||||
{BUSY_STATUS_OPTIONS.map(opt => (
|
||||
@ -495,9 +483,8 @@ export default function CalendarEventModal({
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
{/* Visibility */}
|
||||
<div style={rowStyle}>
|
||||
<div style={{ width: '1px', background: 'var(--weekly-border)', margin: '4px 0' }} />
|
||||
<div style={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'space-between', minHeight: '32px' }}>
|
||||
<span style={labelStyle}>Visibility</span>
|
||||
<select value={visibility} onChange={e => setVisibility(e.target.value)} style={selectStyle}>
|
||||
{VISIBILITY_OPTIONS.map(opt => (
|
||||
@ -505,6 +492,7 @@ export default function CalendarEventModal({
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* URL (Conditional) */}
|
||||
{supportsURL && (
|
||||
@ -514,50 +502,50 @@ export default function CalendarEventModal({
|
||||
onChange={e => setUrl(e.target.value)}
|
||||
placeholder="URL"
|
||||
style={{
|
||||
width: '100%', padding: '6px 0', border: 'none',
|
||||
width: '100%', padding: '4px 10px', border: 'none',
|
||||
borderBottom: '1px solid var(--weekly-border)',
|
||||
background: 'transparent', fontSize: '0.9rem', outline: 'none'
|
||||
background: 'transparent', fontSize: '0.82rem', outline: 'none'
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Expandable section: Attendees & Attachments */}
|
||||
{/* Expandable: Invitees & Attachments */}
|
||||
<button
|
||||
onClick={() => setShowMoreOptions(!showMoreOptions)}
|
||||
style={{
|
||||
display: 'flex', alignItems: 'center', gap: '6px',
|
||||
display: 'flex', alignItems: 'center', gap: '4px',
|
||||
background: 'none', border: 'none', cursor: 'pointer',
|
||||
color: '#3b82f6', fontSize: '0.9rem', padding: '4px 0',
|
||||
color: '#3b82f6', fontSize: '0.8rem', padding: '2px 10px',
|
||||
}}
|
||||
>
|
||||
{showMoreOptions ? <ChevronUp size={14} /> : <ChevronDown size={14} />}
|
||||
{showMoreOptions ? <ChevronUp size={12} /> : <ChevronDown size={12} />}
|
||||
Invitees & Attachments
|
||||
</button>
|
||||
|
||||
{showMoreOptions && (
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: '12px' }}>
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: '8px', padding: '0 10px' }}>
|
||||
{/* Attendees */}
|
||||
<div>
|
||||
<span style={{ ...labelStyle, display: 'flex', alignItems: 'center', gap: '6px', marginBottom: '6px' }}>
|
||||
<Users size={14} /> Invitees
|
||||
<span style={{ ...labelStyle, display: 'flex', alignItems: 'center', gap: '4px', marginBottom: '4px' }}>
|
||||
<Users size={12} /> Invitees
|
||||
</span>
|
||||
{attendees.map((att, idx) => (
|
||||
<div key={idx} style={{
|
||||
display: 'flex', alignItems: 'center', justifyContent: 'space-between',
|
||||
padding: '4px 8px', marginBottom: '4px',
|
||||
background: 'var(--weekly-bg-secondary, #f3f4f6)', borderRadius: '6px',
|
||||
fontSize: '0.85rem',
|
||||
padding: '3px 6px', marginBottom: '2px',
|
||||
background: 'var(--weekly-bg-secondary, #f3f4f6)', borderRadius: '4px',
|
||||
fontSize: '0.78rem',
|
||||
}}>
|
||||
<span style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
|
||||
{att.displayName ? `${att.displayName} (${att.email})` : att.email}
|
||||
</span>
|
||||
<button onClick={() => removeAttendee(att.email)}
|
||||
style={{ background: 'none', border: 'none', cursor: 'pointer', padding: '2px', color: 'var(--weekly-text-light)', flexShrink: 0 }}>
|
||||
<X size={14} />
|
||||
style={{ background: 'none', border: 'none', cursor: 'pointer', padding: '1px', color: 'var(--weekly-text-light)', flexShrink: 0 }}>
|
||||
<X size={12} />
|
||||
</button>
|
||||
</div>
|
||||
))}
|
||||
<div style={{ display: 'flex', gap: '6px' }}>
|
||||
<div style={{ display: 'flex', gap: '4px' }}>
|
||||
<input
|
||||
type="email"
|
||||
value={newAttendeeEmail}
|
||||
@ -565,43 +553,43 @@ export default function CalendarEventModal({
|
||||
placeholder="Add email address"
|
||||
onKeyDown={e => e.key === 'Enter' && addAttendee()}
|
||||
style={{
|
||||
flex: 1, padding: '6px 8px', border: 'none',
|
||||
flex: 1, padding: '4px 6px', border: 'none',
|
||||
borderBottom: '1px solid var(--weekly-border)',
|
||||
background: 'transparent', fontSize: '0.85rem', outline: 'none',
|
||||
background: 'transparent', fontSize: '0.78rem', outline: 'none',
|
||||
}}
|
||||
/>
|
||||
<button onClick={addAttendee} style={{
|
||||
background: 'none', border: 'none', cursor: 'pointer',
|
||||
color: '#3b82f6', padding: '4px',
|
||||
color: '#3b82f6', padding: '2px',
|
||||
}}>
|
||||
<Plus size={16} />
|
||||
<Plus size={14} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Attachments (URL-based, Apple/Synology only) */}
|
||||
{/* Attachments (Apple/Synology only) */}
|
||||
{supportsAttachments && (
|
||||
<div>
|
||||
<span style={{ ...labelStyle, display: 'flex', alignItems: 'center', gap: '6px', marginBottom: '6px' }}>
|
||||
<Paperclip size={14} /> Attachments
|
||||
<span style={{ ...labelStyle, display: 'flex', alignItems: 'center', gap: '4px', marginBottom: '4px' }}>
|
||||
<Paperclip size={12} /> Attachments
|
||||
</span>
|
||||
{attachments.map((att, idx) => (
|
||||
<div key={idx} style={{
|
||||
display: 'flex', alignItems: 'center', justifyContent: 'space-between',
|
||||
padding: '4px 8px', marginBottom: '4px',
|
||||
background: 'var(--weekly-bg-secondary, #f3f4f6)', borderRadius: '6px',
|
||||
fontSize: '0.85rem',
|
||||
padding: '3px 6px', marginBottom: '2px',
|
||||
background: 'var(--weekly-bg-secondary, #f3f4f6)', borderRadius: '4px',
|
||||
fontSize: '0.78rem',
|
||||
}}>
|
||||
<span style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
|
||||
{att.title || att.url}
|
||||
</span>
|
||||
<button onClick={() => removeAttachment(att.url)}
|
||||
style={{ background: 'none', border: 'none', cursor: 'pointer', padding: '2px', color: 'var(--weekly-text-light)', flexShrink: 0 }}>
|
||||
<X size={14} />
|
||||
style={{ background: 'none', border: 'none', cursor: 'pointer', padding: '1px', color: 'var(--weekly-text-light)', flexShrink: 0 }}>
|
||||
<X size={12} />
|
||||
</button>
|
||||
</div>
|
||||
))}
|
||||
<div style={{ display: 'flex', gap: '6px' }}>
|
||||
<div style={{ display: 'flex', gap: '4px' }}>
|
||||
<input
|
||||
type="url"
|
||||
value={newAttachmentUrl}
|
||||
@ -609,16 +597,16 @@ export default function CalendarEventModal({
|
||||
placeholder="Add attachment URL"
|
||||
onKeyDown={e => e.key === 'Enter' && addAttachment()}
|
||||
style={{
|
||||
flex: 1, padding: '6px 8px', border: 'none',
|
||||
flex: 1, padding: '4px 6px', border: 'none',
|
||||
borderBottom: '1px solid var(--weekly-border)',
|
||||
background: 'transparent', fontSize: '0.85rem', outline: 'none',
|
||||
background: 'transparent', fontSize: '0.78rem', outline: 'none',
|
||||
}}
|
||||
/>
|
||||
<button onClick={addAttachment} style={{
|
||||
background: 'none', border: 'none', cursor: 'pointer',
|
||||
color: '#3b82f6', padding: '4px',
|
||||
color: '#3b82f6', padding: '2px',
|
||||
}}>
|
||||
<Plus size={16} />
|
||||
<Plus size={14} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@ -627,37 +615,37 @@ export default function CalendarEventModal({
|
||||
)}
|
||||
|
||||
{/* Notes */}
|
||||
<div style={{ marginTop: '4px' }}>
|
||||
<div style={{ padding: '0 10px' }}>
|
||||
<Suspense fallback={
|
||||
<textarea
|
||||
value={description}
|
||||
onChange={e => setDescription(e.target.value)}
|
||||
placeholder="Notes"
|
||||
rows={3}
|
||||
style={{ width: '100%', padding: '8px 0', border: 'none', borderBottom: '1px solid var(--weekly-border)', background: 'transparent', resize: 'none', fontSize: '0.9rem', outline: 'none' }}
|
||||
rows={2}
|
||||
style={{ width: '100%', padding: '4px 0', border: 'none', borderBottom: '1px solid var(--weekly-border)', background: 'transparent', resize: 'none', fontSize: '0.82rem', outline: 'none' }}
|
||||
/>
|
||||
}>
|
||||
<RichTextEditor
|
||||
value={description}
|
||||
onChange={setDescription}
|
||||
placeholder="Notes"
|
||||
minHeight="80px"
|
||||
minHeight="60px"
|
||||
/>
|
||||
</Suspense>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="weekly-modal-actions" style={{ marginTop: '20px', display: 'flex', justifyContent: 'space-between', borderTop: '1px solid var(--weekly-border)', paddingTop: '15px' }}>
|
||||
<div style={{ display: 'flex', gap: '12px', alignItems: 'center' }}>
|
||||
{/* Actions */}
|
||||
<div style={{ marginTop: '10px', display: 'flex', justifyContent: 'space-between', alignItems: 'center', borderTop: '1px solid var(--weekly-border)', paddingTop: '10px' }}>
|
||||
<div style={{ display: 'flex', gap: '8px', alignItems: 'center' }}>
|
||||
{event && onDelete && (
|
||||
<button
|
||||
onClick={handleDelete}
|
||||
disabled={isSaving || isDeleting}
|
||||
style={{
|
||||
padding: '8px 12px', background: 'none', color: '#ef4444',
|
||||
border: 'none', borderRadius: '6px', fontSize: '0.9rem',
|
||||
fontWeight: 500, cursor: 'pointer', transition: 'all 0.2s',
|
||||
padding: '6px 10px', background: 'none', color: '#ef4444',
|
||||
border: 'none', borderRadius: '6px', fontSize: '0.82rem',
|
||||
fontWeight: 500, cursor: 'pointer',
|
||||
opacity: isSaving || isDeleting ? 0.5 : 1
|
||||
}}
|
||||
>
|
||||
@ -665,15 +653,15 @@ export default function CalendarEventModal({
|
||||
</button>
|
||||
)}
|
||||
{!event && (
|
||||
<button className="weekly-btn-ghost" onClick={onClose} style={{ padding: '8px 12px', fontSize: '0.9rem', color: 'var(--weekly-text-light)', border: 'none', background: 'none', cursor: 'pointer' }}>
|
||||
<button onClick={onClose} style={{ padding: '6px 10px', fontSize: '0.82rem', color: 'var(--weekly-text-light)', border: 'none', background: 'none', cursor: 'pointer' }}>
|
||||
Cancel
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div style={{ display: 'flex', gap: '8px' }}>
|
||||
<div style={{ display: 'flex', gap: '6px' }}>
|
||||
{event && (
|
||||
<button className="weekly-btn-ghost" onClick={onClose} style={{ padding: '8px 12px', fontSize: '0.9rem', color: 'var(--weekly-text-light)', border: 'none', background: 'none', cursor: 'pointer' }}>
|
||||
<button onClick={onClose} style={{ padding: '6px 10px', fontSize: '0.82rem', color: 'var(--weekly-text-light)', border: 'none', background: 'none', cursor: 'pointer' }}>
|
||||
Cancel
|
||||
</button>
|
||||
)}
|
||||
@ -682,7 +670,7 @@ export default function CalendarEventModal({
|
||||
onClick={handleSubmit}
|
||||
disabled={isSaving || isDeleting}
|
||||
style={{
|
||||
padding: '8px 20px', borderRadius: '8px', fontSize: '0.95rem',
|
||||
padding: '6px 16px', borderRadius: '6px', fontSize: '0.85rem',
|
||||
fontWeight: 600, backgroundColor: '#3b82f6', color: 'white',
|
||||
border: 'none', cursor: 'pointer',
|
||||
opacity: isSaving || isDeleting ? 0.7 : 1
|
||||
|
||||
Loading…
Reference in New Issue
Block a user