M8-T19: add scope-aware energy contract and cost UI
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
*/
|
||||
|
||||
import { useState } from 'react'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import {
|
||||
Table,
|
||||
Button,
|
||||
@@ -24,9 +25,9 @@ import {
|
||||
Modal,
|
||||
Accordion,
|
||||
Code,
|
||||
SegmentedControl,
|
||||
} from '@mantine/core'
|
||||
import {
|
||||
useContracts,
|
||||
useUpdateContract,
|
||||
type ContractResponse,
|
||||
type ContractDetailResponse,
|
||||
@@ -244,7 +245,14 @@ function ContractTable({
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export function ContractManager() {
|
||||
const contractsQuery = useContracts()
|
||||
const [scope, setScope] = useState<'electricity' | 'thermal'>('electricity')
|
||||
const contractsQuery = useQuery({
|
||||
queryKey: ['energy-contracts', scope],
|
||||
queryFn: async () => {
|
||||
const res = await apiClient.GET('/api/energy/contracts', { params: { query: { scope } } })
|
||||
return res.data
|
||||
},
|
||||
})
|
||||
const updateMutation = useUpdateContract()
|
||||
|
||||
const [showCreateForm, setShowCreateForm] = useState(false)
|
||||
@@ -252,6 +260,13 @@ export function ContractManager() {
|
||||
const [historyContract, setHistoryContract] = useState<ContractResponse | null>(null)
|
||||
const [activatingId, setActivatingId] = useState<number | null>(null)
|
||||
|
||||
function handleScopeChange(nextScope: 'electricity' | 'thermal') {
|
||||
setScope(nextScope)
|
||||
setShowCreateForm(false)
|
||||
setAddVersionContract(null)
|
||||
setHistoryContract(null)
|
||||
}
|
||||
|
||||
async function handleActivate(id: number) {
|
||||
setActivatingId(id)
|
||||
try {
|
||||
@@ -265,44 +280,40 @@ export function ContractManager() {
|
||||
// Render states
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
if (contractsQuery.isLoading) {
|
||||
return (
|
||||
<Center py="xl" data-testid="contracts-loading">
|
||||
<Loader />
|
||||
</Center>
|
||||
)
|
||||
}
|
||||
|
||||
if (contractsQuery.isError || !contractsQuery.data) {
|
||||
return (
|
||||
<Alert color="red" data-testid="contracts-load-error">
|
||||
Failed to load contracts. Please refresh.
|
||||
</Alert>
|
||||
)
|
||||
}
|
||||
|
||||
const contracts = contractsQuery.data.items
|
||||
const contracts = contractsQuery.data?.items ?? []
|
||||
|
||||
return (
|
||||
<Stack gap="lg" data-testid="contract-manager">
|
||||
<Group justify="space-between" align="center">
|
||||
<Text fw={500}>Energy Contracts</Text>
|
||||
<Group gap="sm">
|
||||
<Text fw={500}>Energy Contracts</Text>
|
||||
<SegmentedControl
|
||||
value={scope}
|
||||
onChange={(value) => handleScopeChange(value as 'electricity' | 'thermal')}
|
||||
data={[{ label: 'Electricity', value: 'electricity' }, { label: 'Thermal', value: 'thermal' }]}
|
||||
data-testid="contracts-scope-selector"
|
||||
/>
|
||||
</Group>
|
||||
<Button onClick={() => setShowCreateForm(true)} data-testid="contract-new-button">
|
||||
New Contract
|
||||
</Button>
|
||||
</Group>
|
||||
|
||||
<ContractTable
|
||||
{contractsQuery.isLoading && <Center py="xl" data-testid="contracts-loading"><Loader /></Center>}
|
||||
{contractsQuery.isError && <Alert color="red" data-testid="contracts-load-error">Failed to load contracts. Please refresh.</Alert>}
|
||||
{!contractsQuery.isLoading && !contractsQuery.isError && <ContractTable
|
||||
contracts={contracts}
|
||||
onActivate={handleActivate}
|
||||
onAddVersion={(c) => setAddVersionContract(c)}
|
||||
onViewHistory={(c) => setHistoryContract(c)}
|
||||
activatingId={activatingId}
|
||||
/>
|
||||
/>}
|
||||
|
||||
{/* Create new contract */}
|
||||
{showCreateForm && (
|
||||
<ContractForm
|
||||
defaultKind={scope === 'thermal' ? 'district_heating' : undefined}
|
||||
scope={scope}
|
||||
onClose={() => setShowCreateForm(false)}
|
||||
onSaved={() => setShowCreateForm(false)}
|
||||
/>
|
||||
@@ -313,6 +324,7 @@ export function ContractManager() {
|
||||
<ContractForm
|
||||
contractId={addVersionContract.id}
|
||||
defaultKind={addVersionContract.kind}
|
||||
scope={scope}
|
||||
onClose={() => setAddVersionContract(null)}
|
||||
onSaved={() => setAddVersionContract(null)}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user