refactor(arch): eliminate direct service calls in components — route all through hooks

New hook files:
- useAuth.ts: useLogin, useSwitchDemoRole, useSwitchOrganization
- useAI.ts: useParseNeed, useGenerateOfferEmail, useGenerateDecisionBrief, useParseListingText
- useAssistant.ts: useAssistantSuggestions (useQuery), useAssistantAnswer (useMutation)
- useOfferReport.ts: useOfferReportByInquiry, useCreateOfferReport, useUpdateOfferReport, useGenerateOfferReportPdf
- useInquiryReport.ts: useInquiryReportByInquiry, useCreateInquiryReport, useUpdateInquiryReport, useFinalizeInquiryReport
- useMarketReport.ts: useMarketReport
- useWeighting.ts: useDefaultWeights (synchronous wrapper)
- useUnitMatches.ts: useUnitMatchesMap, useUnitBundle, useBundleMatches (useMemo wrappers)

Extended hooks: useProperties (add update/create/remove mutations),
useNeeds (add useCreateNeed), useMatches (add useNeedMatchesForProperty,
useAdditionalMatchesForInquiry), useReviewQueue (add useCreateReviewTask)

Updated 21 components/pages: all direct service imports replaced with hooks.
Deliberate exception: getRecommendedActions in DataQuality.tsx (pure sync utility, no provider access).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Sutter
2026-05-24 14:56:32 +02:00
parent f487435a94
commit e36c5bc979
33 changed files with 666 additions and 407 deletions
+17 -22
View File
@@ -1,5 +1,5 @@
import { useState } from 'react'
import { useNavigate, Navigate } from 'react-router'
import { Navigate } from 'react-router'
import {
Box,
Button,
@@ -12,7 +12,7 @@ import {
Typography,
} from '@mui/material'
import { Building2 } from 'lucide-react'
import { authService } from '../../services/authService'
import { useLogin, useSwitchDemoRole } from '../../hooks/useAuth'
import { useSessionStore } from '../../stores/sessionStore'
import { UserRole } from '../../domain/enums'
@@ -23,42 +23,37 @@ const DEMO_ROLES: { role: UserRole; label: string; description: string }[] = [
export default function LoginScreen() {
const { isAuthenticated } = useSessionStore()
const navigate = useNavigate()
const loginMutation = useLogin()
const switchDemoRoleMutation = useSwitchDemoRole()
const [email, setEmail] = useState('admin@ideal-sharing.ch')
const [password, setPassword] = useState('')
const [loading, setLoading] = useState(false)
const [error, setError] = useState<string | null>(null)
if (isAuthenticated) {
return <Navigate to="/" replace />
}
async function handleLogin(e: React.FormEvent) {
const loading = loginMutation.isPending || switchDemoRoleMutation.isPending
function handleLogin(e: React.FormEvent) {
e.preventDefault()
if (!email) {
setError('Bitte E-Mail-Adresse eingeben.')
return
}
setLoading(true)
setError(null)
try {
await authService.login(email, password)
navigate('/')
} catch {
setError('Anmeldung fehlgeschlagen. Bitte erneut versuchen.')
} finally {
setLoading(false)
}
loginMutation.mutate(
{ email, password },
{
onError: () => {
setError('Anmeldung fehlgeschlagen. Bitte erneut versuchen.')
},
},
)
}
async function handleDemoLogin(role: UserRole) {
setLoading(true)
try {
await authService.switchDemoRole(role)
navigate('/')
} finally {
setLoading(false)
}
function handleDemoLogin(role: UserRole) {
switchDemoRoleMutation.mutate(role)
}
return (