diff --git a/frontend/src/components/balance/BalanceFlow.tsx b/frontend/src/components/balance/BalanceFlow.tsx index d587db2..b678621 100644 --- a/frontend/src/components/balance/BalanceFlow.tsx +++ b/frontend/src/components/balance/BalanceFlow.tsx @@ -14,6 +14,7 @@ import type { PersonalData } from '@/types' import { QRCodeModal } from '@/components/modals/QRCodeModal' import { ParentBalanceForm, type ParentBalanceInitial } from '@/components/modals/ParentBalanceForm' import { LoadingSpinner } from '@/components/common/LoadingSpinner' +import { Alert } from '@/components/common/Alert' import './balance-flow.css' export interface BalanceFlowProps { @@ -325,11 +326,7 @@ export function BalanceFlow({ disabled={isAddingDeducedPartner} /> - {deducedPartnerError && ( -
- {deducedPartnerError} -
- )} + {deducedPartnerError && {deducedPartnerError}}
diff --git a/frontend/src/components/modals/PlannedDayModal.tsx b/frontend/src/components/modals/PlannedDayModal.tsx index 724e7e1..5b658e3 100644 --- a/frontend/src/components/modals/PlannedDayModal.tsx +++ b/frontend/src/components/modals/PlannedDayModal.tsx @@ -2,6 +2,8 @@ import { ReactNode, useEffect, useState } from 'react' import type { PlannedLeaveDay } from '@/types' import { useTranslation } from '@/i18n' import { Icon } from '@/components/common/Icon' +import { FormField } from '@/components/common/FormField' +import { Alert } from '@/components/common/Alert' import './planned-day-modal.css' /** The default path — todo.md #10/#11: the planner decides which day type @@ -283,11 +285,7 @@ export function PlannedDayModal({
{!isRangeMode &&

{displayDate}

} - {(error || localError) && ( -
- {error || localError} -
- )} + {(error || localError) && {error || localError}} {!isRangeMode && excludedEntries.map((entry) => ( @@ -313,12 +311,8 @@ export function PlannedDayModal({
{!forcedAdvanced && hasMultipleParents && ( -
- + -
+ )} {!forcedAdvanced && hasMultipleParents && ( @@ -382,12 +376,8 @@ export function PlannedDayModal({ {showPinnedControls && (
-
- + -
+ {freeDaysWillStayOff && (

@@ -419,12 +409,8 @@ export function PlannedDayModal({ )} {hasMultipleParents && ( -

- + -
+ )} {dayType !== 'auto' && ( diff --git a/frontend/src/components/modals/QRCodeModal.tsx b/frontend/src/components/modals/QRCodeModal.tsx index 0909418..d08dfe2 100644 --- a/frontend/src/components/modals/QRCodeModal.tsx +++ b/frontend/src/components/modals/QRCodeModal.tsx @@ -2,6 +2,7 @@ import { ReactNode } from 'react' import type { ScraperStatus } from '@/hooks/useScraperFetch' import { useTranslation, type TranslationKey } from '@/i18n' import { Icon } from '@/components/common/Icon' +import { Alert } from '@/components/common/Alert' import './qrcode-modal.css' // Every `ScraperStatus` maps to a translated `balance.status.*` label — the @@ -113,9 +114,9 @@ export function QRCodeModal({ )} {error && ( -
+ {t('qrModal.errorLabel')} {error} -
+ )}
diff --git a/frontend/src/components/settings/PartnerInvitePanel.tsx b/frontend/src/components/settings/PartnerInvitePanel.tsx index fefe68c..57b234c 100644 --- a/frontend/src/components/settings/PartnerInvitePanel.tsx +++ b/frontend/src/components/settings/PartnerInvitePanel.tsx @@ -2,6 +2,7 @@ import { useCallback, useEffect, useState } from 'react' import * as api from '@/services/api' import { useTranslation } from '@/i18n' import type { Invitation } from '@/types' +import { Alert } from '@/components/common/Alert' import './partner-invite-panel.css' export interface PartnerInvitePanelProps { @@ -118,11 +119,7 @@ export function PartnerInvitePanel({ workspaceId }: PartnerInvitePanelProps) { {isCreating ? t('invite.generatingButton') : t('invite.generateButton')} - {createError && ( -

- {createError} -

- )} + {createError && {createError}} {inviteLink && (
@@ -157,9 +154,7 @@ export function PartnerInvitePanel({ workspaceId }: PartnerInvitePanelProps) { {isListLoading ? (

{t('common.loading')}

) : listError ? ( -

- {listError} -

+ {listError} ) : pending.length === 0 ? (

{t('invite.noPending')}

) : ( @@ -183,11 +178,7 @@ export function PartnerInvitePanel({ workspaceId }: PartnerInvitePanelProps) { )} - {revokeError && ( -

- {revokeError} -

- )} + {revokeError && {revokeError}}
) } diff --git a/frontend/src/components/settings/partner-invite-panel.css b/frontend/src/components/settings/partner-invite-panel.css index f1c2e11..ff48506 100644 --- a/frontend/src/components/settings/partner-invite-panel.css +++ b/frontend/src/components/settings/partner-invite-panel.css @@ -75,9 +75,3 @@ font-size: var(--fs-sm); color: var(--c-text-muted); } - -.partner-invite-panel__error { - margin: 0; - font-size: var(--fs-sm); - color: var(--c-danger); -} diff --git a/frontend/src/pages/Auth.tsx b/frontend/src/pages/Auth.tsx index 09939fb..1ecdbbe 100644 --- a/frontend/src/pages/Auth.tsx +++ b/frontend/src/pages/Auth.tsx @@ -4,6 +4,8 @@ import { useAuth } from '@/context/AuthContext' import { useWorkspace } from '@/context/WorkspaceContext' import { useTranslation } from '@/i18n' import { LanguageToggle } from '@/components/layout/LanguageToggle' +import { FormField } from '@/components/common/FormField' +import { Alert } from '@/components/common/Alert' import './auth.css' export function Auth() { @@ -77,25 +79,17 @@ export function Auth() {
void handleSubmit(e)}> {isRegister && ( -
- + setDisplayName(e.target.value)} /> -
+ )} -
- + setEmail(e.target.value)} /> -
-
- + + setPassword(e.target.value)} /> -
- {error && ( -

- {error} -

- )} + + {error && {error}} diff --git a/frontend/src/pages/Dashboard.tsx b/frontend/src/pages/Dashboard.tsx index 44a2690..7341df5 100644 --- a/frontend/src/pages/Dashboard.tsx +++ b/frontend/src/pages/Dashboard.tsx @@ -29,6 +29,7 @@ import { VacationRescueTip } from '@/components/dashboard/VacationRescueTip' import { ParentalLeaveBreakdown } from '@/components/dashboard/ParentalLeaveBreakdown' import { TipCard } from '@/components/inputs/TipCard' import { Onboarding } from '@/pages/Onboarding' +import { Alert } from '@/components/common/Alert' import type { RescueDay, Tip } from '@/types' /** Key matching `rescueDayGroups`' own `Map` key below — shared so a @@ -332,9 +333,9 @@ export function Dashboard(): ReactNode {
{analyticsError && ( -
+ {analyticsError} -
+ )} {analytics && selectedChild && ( @@ -371,9 +372,9 @@ export function Dashboard(): ReactNode {

{t('dashboard.leaveOverviewTitle')}

{age4Bars.length > 0 && } {proposalError && ( -
+ {proposalError} -
+ )} -

+ {errorKey ? t(errorKey) : t('invite.joinGenericError')} -

+ {isAuthenticated && (
- {familyError && ( -
- {familyError} -
- )} + {familyError && {familyError}}