Add files via upload

This commit is contained in:
jasonMPM
2026-03-06 00:19:24 -06:00
committed by GitHub
parent f8dc6563b8
commit 748acc41c3
4 changed files with 365 additions and 156 deletions

View File

@@ -17,9 +17,9 @@ export default function MainCalendar({ onCalendarReady }) {
const calRef = useRef(null)
const wrapperRef = useRef(null)
const { projects, updateDeliverable: storeUpdate, removeDeliverable } = useProjectStore()
const openFocus = useFocusStore(s => s.openFocus)
const { showHeatmap, toggleHeatmap } = useUIStore()
const addToast = useToastStore(s => s.addToast)
const openFocus = useFocusStore(s => s.openFocus)
const { showHeatmap, toggleHeatmap, heatmapJumpDate, clearJumpDate } = useUIStore()
const addToast = useToastStore(s => s.addToast)
const [modal, setModal] = useState({ open: false, deliverable: null, defaultDate: '' })
const [contextMenu, setContextMenu] = useState(null)
@@ -27,23 +27,25 @@ export default function MainCalendar({ onCalendarReady }) {
// Expose calendar API to App.jsx for keyboard shortcuts
useEffect(() => {
if (calRef.current && onCalendarReady) {
onCalendarReady(calRef.current.getApi())
}
if (calRef.current && onCalendarReady) onCalendarReady(calRef.current.getApi())
}, [])
// ResizeObserver: call updateSize() on every frame the container changes width
// during the sidebar CSS transition so FullCalendar reflows smoothly
// ResizeObserver: smooth reflow during sidebar CSS transition
useEffect(() => {
const el = wrapperRef.current
if (!el) return
const ro = new ResizeObserver(() => {
calRef.current?.getApi().updateSize()
})
const ro = new ResizeObserver(() => calRef.current?.getApi().updateSize())
ro.observe(el)
return () => ro.disconnect()
}, [])
// Jump to date commanded by HeatmapDayPanel
useEffect(() => {
if (!heatmapJumpDate || !calRef.current) return
calRef.current.getApi().gotoDate(heatmapJumpDate)
clearJumpDate()
}, [heatmapJumpDate, clearJumpDate])
const events = projects.flatMap(p =>
(p.deliverables || []).map(d => ({
id: String(d.id),
@@ -82,17 +84,14 @@ export default function MainCalendar({ onCalendarReady }) {
})
}, [storeUpdate, addToast])
// Click empty date - open add modal
const handleDateClick = useCallback(({ dateStr }) => {
setModal({ open: true, deliverable: null, defaultDate: dateStr.substring(0, 10) })
}, [])
// Date range drag-select - pre-fill modal with start date
const handleSelect = useCallback(({ startStr }) => {
setModal({ open: true, deliverable: null, defaultDate: startStr.substring(0, 10) })
}, [])
// Attach dblclick + contextmenu + tooltip via eventDidMount
const handleEventDidMount = useCallback(({ event, el }) => {
const { deliverableId, projectId } = event.extendedProps
@@ -104,14 +103,12 @@ export default function MainCalendar({ onCalendarReady }) {
el.addEventListener('mousemove', (e) => {
setTooltip(prev => prev ? { ...prev, x: e.clientX, y: e.clientY } : null)
})
el.addEventListener('dblclick', (e) => {
e.preventDefault(); e.stopPropagation()
setTooltip(null)
const { deliverable } = getCtx(projectId, deliverableId)
if (deliverable) setModal({ open: true, deliverable, defaultDate: '' })
})
el.addEventListener('contextmenu', (e) => {
e.preventDefault(); e.stopPropagation()
setTooltip(null)
@@ -121,15 +118,16 @@ export default function MainCalendar({ onCalendarReady }) {
x: e.clientX, y: e.clientY,
items: [
{ icon: '\u2714\ufe0e', label: 'Edit Deliverable', action: () => setModal({ open: true, deliverable, defaultDate: '' }) },
{ icon: '\u2756', label: 'Open Focus View', action: () => openFocus(projectId, deliverableId) },
{ icon: '\u2756', label: 'Open Focus View', action: () => openFocus(projectId, deliverableId) },
...(project?.drive_url ? [{ icon: '\u2b21', label: 'Open Drive Folder', action: () => window.open(project.drive_url, '_blank') }] : []),
{ separator: true },
{ icon: '\u2715', label: 'Delete Deliverable', danger: true,
action: async () => {
if (window.confirm(`Delete "${deliverable.title}"?`)) {
await deleteDeliverable(deliverableId); removeDeliverable(deliverableId)
await deleteDeliverable(deliverableId)
removeDeliverable(deliverableId)
}
}
},
},
],
})
@@ -138,19 +136,22 @@ export default function MainCalendar({ onCalendarReady }) {
return (
<div className="h-full flex flex-col bg-surface" onContextMenu={e => e.preventDefault()}>
{/* View toggle toolbar */}
<div className="flex items-center justify-end gap-2 px-4 pt-3 pb-0 flex-shrink-0">
<button onClick={toggleHeatmap}
<button
onClick={toggleHeatmap}
className={`text-xs px-3 py-1.5 rounded-lg border transition-all font-medium
${showHeatmap
? 'bg-gold text-surface border-gold'
: 'bg-surface-elevated border-surface-border text-text-muted hover:border-gold/40 hover:text-gold'
}`}>
}`}
>
{showHeatmap ? '\u2190 Calendar' : '\u2b21 Heatmap'}
</button>
</div>
{/* Main content area */}
{/* Main content */}
<div className="flex-1 overflow-hidden">
{showHeatmap ? (
<WorkloadHeatmap />