/** * Visit card component for rendering individual visit cards in the side panel */ export class VisitCard { /** * Create HTML for a visit card * @param {Object} visit - Visit object with id, name, status, started_at, ended_at, duration, place * @param {Object} options - { isSelected, onSelect, onConfirm, onDecline, onHover } * @returns {string} HTML string */ static create(visit, options = {}) { const { isSelected = false, onSelect, onConfirm, onDecline, onHover } = options const isSuggested = visit.status === 'suggested' const isConfirmed = visit.status === 'confirmed' const isDeclined = visit.status === 'declined' // Format date and time const startDate = new Date(visit.started_at) const endDate = new Date(visit.ended_at) const dateStr = startDate.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' }) const timeRange = `${startDate.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' })} - ${endDate.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' })}` // Format duration (duration is in minutes from the backend) const hours = Math.floor(visit.duration / 60) const minutes = visit.duration % 60 const durationStr = hours > 0 ? `${hours}h ${minutes}m` : `${minutes}m` // Border style based on status const borderClass = isSuggested ? 'border-dashed' : '' const bgClass = isDeclined ? 'bg-base-200 opacity-60' : 'bg-base-100' const selectedClass = isSelected ? 'ring-2 ring-primary' : '' return `

${visit.name || visit.place?.name || 'Unnamed Visit'}

${dateStr}
${timeRange}
${durationStr}
${isSuggested ? `
` : ''} ${isConfirmed || isDeclined ? `
${visit.status}
` : ''}
` } /** * Create bulk action buttons HTML * @param {number} selectedCount - Number of selected visits * @returns {string} HTML string */ static createBulkActions(selectedCount) { if (selectedCount < 2) return '' return `
${selectedCount} visit${selectedCount === 1 ? '' : 's'} selected
` } }