refactor: extract helpers from ReminderDetailDrawer + OfferCreationWizard
- ReminderDetailDrawer (340→257 lines): constants + SectionTitle/DateRow/ActivityEntry → reminderDetailHelpers.tsx - OfferCreationWizard (350→276 lines): PDF step JSX → OfferWizardPdfStep.tsx Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,14 +1,15 @@
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import {
|
||||
Box, Button, CircularProgress, Dialog, DialogContent,
|
||||
IconButton, LinearProgress, Stack, Step, StepLabel, Stepper,
|
||||
IconButton, Stack, Step, StepLabel, Stepper,
|
||||
TextField, Typography,
|
||||
} from '@mui/material'
|
||||
import { Download, Plus, Send, Trash2, X } from 'lucide-react'
|
||||
import { Plus, Trash2, X } from 'lucide-react'
|
||||
import type { OfferReportDraft, ViewingAppointmentOption } from '../../domain/offerReport'
|
||||
import { offerReportService } from '../../services/offerReportService'
|
||||
import { usePropertyById } from '../../hooks/useProperties'
|
||||
import { useToastStore } from '../../stores/toastStore'
|
||||
import { OfferWizardPdfStep } from './OfferWizardPdfStep'
|
||||
|
||||
interface Props {
|
||||
inquiryId: string
|
||||
@@ -213,94 +214,19 @@ export function OfferCreationWizard({ inquiryId, propertyId, tenantName, onClose
|
||||
|
||||
{/* Step 3: PDF */}
|
||||
{step === 3 && (
|
||||
<Box sx={{ display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', height: '100%', gap: 3 }}>
|
||||
{generating ? (
|
||||
<>
|
||||
<CircularProgress size={48} sx={{ color: '#1e3a5f' }} />
|
||||
<Typography variant="body1" sx={{ fontWeight: 600, color: '#1e3a5f' }}>
|
||||
PDF wird generiert…
|
||||
</Typography>
|
||||
<Box sx={{ width: '100%', maxWidth: 400 }}>
|
||||
<LinearProgress variant="determinate" value={progress} sx={{ height: 6, borderRadius: 3 }} />
|
||||
<Typography variant="caption" sx={{ color: '#64748b', display: 'block', textAlign: 'center', mt: 1 }}>
|
||||
{Math.round(progress)}%
|
||||
</Typography>
|
||||
</Box>
|
||||
</>
|
||||
) : ready ? (
|
||||
<Box sx={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 2, width: '100%' }}>
|
||||
<Box
|
||||
sx={{
|
||||
width: '100%',
|
||||
maxWidth: 520,
|
||||
height: 380,
|
||||
bgcolor: '#f8fafc',
|
||||
border: '1px solid #e2e8f0',
|
||||
borderRadius: 1.5,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
overflow: 'hidden',
|
||||
}}
|
||||
>
|
||||
<Box sx={{ bgcolor: '#1e3a5f', px: 2, py: 1, display: 'flex', alignItems: 'center', gap: 1 }}>
|
||||
<Box sx={{ width: 10, height: 10, borderRadius: '50%', bgcolor: '#ef4444' }} />
|
||||
<Box sx={{ width: 10, height: 10, borderRadius: '50%', bgcolor: '#f59e0b' }} />
|
||||
<Box sx={{ width: 10, height: 10, borderRadius: '50%', bgcolor: '#10b981' }} />
|
||||
<Typography variant="caption" sx={{ color: 'rgba(255,255,255,0.7)', ml: 1, fontSize: '0.7rem' }}>
|
||||
Angebot_{draft?.propertyId ?? 'Objekt'}.pdf
|
||||
</Typography>
|
||||
</Box>
|
||||
<Box sx={{ flex: 1, p: 3 }}>
|
||||
<Typography variant="body2" sx={{ fontWeight: 700, color: '#1e3a5f', mb: 1 }}>
|
||||
Angebotsschreiben
|
||||
</Typography>
|
||||
{draft?.editableFields.slice(0, 3).map(f => (
|
||||
<Box key={f.id} sx={{ mb: 1 }}>
|
||||
<Typography variant="caption" sx={{ color: '#94a3b8', fontSize: '0.65rem', display: 'block' }}>{f.label}</Typography>
|
||||
<Typography variant="caption" sx={{ color: '#374151', fontSize: '0.75rem', display: 'block' }}>
|
||||
{f.value.slice(0, 80)}{f.value.length > 80 ? '…' : ''}
|
||||
</Typography>
|
||||
</Box>
|
||||
))}
|
||||
{(draft?.viewingAppointments.length ?? 0) > 0 && (
|
||||
<Box sx={{ mt: 1.5, p: 1, bgcolor: '#f1f5f9', borderRadius: 1 }}>
|
||||
<Typography variant="caption" sx={{ fontWeight: 600, fontSize: '0.72rem', display: 'block', mb: 0.5 }}>
|
||||
Besichtigungstermine
|
||||
</Typography>
|
||||
{draft!.viewingAppointments.map(a => (
|
||||
<Typography key={a.id} variant="caption" sx={{ fontSize: '0.7rem', display: 'block', color: '#475569' }}>
|
||||
{new Date(a.date).toLocaleDateString('de-CH')} · {a.timeSlot}
|
||||
</Typography>
|
||||
))}
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
<Box sx={{ display: 'flex', gap: 1.5 }}>
|
||||
<Button
|
||||
variant="contained"
|
||||
startIcon={<Download size={16} />}
|
||||
onClick={() => showToast('PDF wird heruntergeladen…', 'info')}
|
||||
sx={{ textTransform: 'none', bgcolor: '#1e3a5f', '&:hover': { bgcolor: '#16304d' } }}
|
||||
>
|
||||
Herunterladen
|
||||
</Button>
|
||||
<Button
|
||||
variant="outlined"
|
||||
startIcon={<Send size={16} />}
|
||||
onClick={() => {
|
||||
const label = `Angebot_${property?.title ?? 'Objekt'}.pdf`
|
||||
onAttach(label)
|
||||
showToast('Angebot als Anhang hinzugefügt', 'success')
|
||||
}}
|
||||
sx={{ textTransform: 'none' }}
|
||||
>
|
||||
An Nachricht anhängen
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
) : null}
|
||||
</Box>
|
||||
<OfferWizardPdfStep
|
||||
generating={generating}
|
||||
progress={progress}
|
||||
ready={ready}
|
||||
draft={draft}
|
||||
property={property}
|
||||
onDownload={() => showToast('PDF wird heruntergeladen…', 'info')}
|
||||
onAttach={() => {
|
||||
const label = `Angebot_${property?.title ?? 'Objekt'}.pdf`
|
||||
onAttach(label)
|
||||
showToast('Angebot als Anhang hinzugefügt', 'success')
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</DialogContent>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user