feat(değerlendirme): geçmiş dönemler ve düzeltme için yeniden açma
- Defter, Plan ve Değerlendirme'de dönem seçici (?donem=) - Kapalı dönem salt okunur; düzeltmedeki dönem düzenlenebilir ve yeniden kapatılır - Hane sahibi için onaylı "Düzeltme için yeniden aç" - Geçmiş dönemler listesi, dönem durum rozeti Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,13 +1,16 @@
|
||||
import { useRef, useState } from 'react'
|
||||
import { useSearchParams } from 'react-router'
|
||||
import { Info } from 'lucide-react'
|
||||
import { PageError, PageHeader, PageLoading } from '@/components/page'
|
||||
import { NoPeriodCard } from '@/features/period-wizard/no-period-card'
|
||||
import { PeriodPicker } from '@/features/periods/period-picker'
|
||||
import { SelectedPeriod } from '@/features/periods/selected-period'
|
||||
import { Section } from '@/features/planning/plan-read'
|
||||
import { useCategories, usePaymentMethods } from '@/lib/catalog'
|
||||
import { useEntries } from '@/lib/entries'
|
||||
import { toIsoDate } from '@/lib/format'
|
||||
import { parseWeekParam, weekIndexFor } from '@/lib/ledger'
|
||||
import { useBudget, useCurrentPeriod } from '@/lib/periods'
|
||||
import { isWritable } from '@/lib/period-select'
|
||||
import { useBudget } from '@/lib/periods'
|
||||
import { t } from '@/lib/strings'
|
||||
import type { Entry } from '@/types/Entry'
|
||||
import type { Period } from '@/types/Period'
|
||||
@@ -17,19 +20,14 @@ import { WeekPicker } from './week-picker'
|
||||
import { WeekSummary } from './week-summary'
|
||||
|
||||
export function LedgerPage() {
|
||||
const current = useCurrentPeriod()
|
||||
return (
|
||||
<>
|
||||
<PageHeader title={t.pages.ledger.title} description={t.pages.ledger.description} />
|
||||
{current.isPending ? (
|
||||
<PageLoading />
|
||||
) : current.isError ? (
|
||||
<PageError message={current.error.message} onRetry={current.refetch} />
|
||||
) : current.data ? (
|
||||
<LedgerView period={current.data} />
|
||||
) : (
|
||||
<NoPeriodCard />
|
||||
)}
|
||||
<PageHeader
|
||||
title={t.pages.ledger.title}
|
||||
description={t.pages.ledger.description}
|
||||
actions={<PeriodPicker />}
|
||||
/>
|
||||
<SelectedPeriod>{(p) => <LedgerView key={p.id} period={p} />}</SelectedPeriod>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -48,6 +46,7 @@ function LedgerView({ period }: { period: Period }) {
|
||||
const index =
|
||||
parseWeekParam(params.get('hafta'), period.weeks.length) ?? weekIndexFor(period.weeks, today)
|
||||
const week = period.weeks[index - 1]
|
||||
const readOnly = !isWritable(period)
|
||||
|
||||
const budget = useBudget(period.id)
|
||||
const categories = useCategories(true)
|
||||
@@ -56,7 +55,15 @@ function LedgerView({ period }: { period: Period }) {
|
||||
|
||||
const goTo = (n: number) => {
|
||||
setEditing(null)
|
||||
setParams(n === todayIndex ? {} : { hafta: String(n) }, { replace: true })
|
||||
setParams(
|
||||
(prev) => {
|
||||
const next = new URLSearchParams(prev) // seçili dönem (`donem`) korunur
|
||||
if (n === todayIndex) next.delete('hafta')
|
||||
else next.set('hafta', String(n))
|
||||
return next
|
||||
},
|
||||
{ replace: true },
|
||||
)
|
||||
}
|
||||
|
||||
function edit(e: Entry) {
|
||||
@@ -78,29 +85,37 @@ function LedgerView({ period }: { period: Period }) {
|
||||
onChange={goTo}
|
||||
/>
|
||||
</div>
|
||||
{readOnly && (
|
||||
<p className="flex items-start gap-2 rounded-xl bg-muted px-3 py-2 text-sm text-muted-foreground">
|
||||
<Info className="mt-0.5 size-4 shrink-0" aria-hidden />
|
||||
{t.ledger.readOnly}
|
||||
</p>
|
||||
)}
|
||||
<div className="grid items-start gap-4 lg:grid-cols-2">
|
||||
<div ref={formRef} className="scroll-mt-4 lg:sticky lg:top-4">
|
||||
<Section title={editing ? t.ledger.editTitle : t.ledger.formTitle}>
|
||||
{catalogFailed?.error ? (
|
||||
<PageError message={catalogFailed.error.message} onRetry={catalogFailed.refetch} />
|
||||
) : !catalog ? (
|
||||
<PageLoading />
|
||||
) : (
|
||||
<EntryForm
|
||||
key={editing?.id ?? 'new'}
|
||||
period={period}
|
||||
week={week}
|
||||
today={today}
|
||||
categories={catalog.c}
|
||||
methods={catalog.m}
|
||||
entry={editing ?? undefined}
|
||||
onSaved={(date) => goTo(weekIndexFor(period.weeks, date))}
|
||||
onCancel={() => setEditing(null)}
|
||||
/>
|
||||
)}
|
||||
</Section>
|
||||
</div>
|
||||
<div className="space-y-4">
|
||||
{!readOnly && (
|
||||
<div ref={formRef} className="scroll-mt-4 lg:sticky lg:top-4">
|
||||
<Section title={editing ? t.ledger.editTitle : t.ledger.formTitle}>
|
||||
{catalogFailed?.error ? (
|
||||
<PageError message={catalogFailed.error.message} onRetry={catalogFailed.refetch} />
|
||||
) : !catalog ? (
|
||||
<PageLoading />
|
||||
) : (
|
||||
<EntryForm
|
||||
key={editing?.id ?? 'new'}
|
||||
period={period}
|
||||
week={week}
|
||||
today={today}
|
||||
categories={catalog.c}
|
||||
methods={catalog.m}
|
||||
entry={editing ?? undefined}
|
||||
onSaved={(date) => goTo(weekIndexFor(period.weeks, date))}
|
||||
onCancel={() => setEditing(null)}
|
||||
/>
|
||||
)}
|
||||
</Section>
|
||||
</div>
|
||||
)}
|
||||
<div className={readOnly ? 'space-y-4 lg:col-span-2' : 'space-y-4'}>
|
||||
<Section title={t.ledger.summaryTitle}>
|
||||
{budget.isError ? (
|
||||
<PageError message={budget.error.message} onRetry={budget.refetch} />
|
||||
@@ -120,6 +135,7 @@ function LedgerView({ period }: { period: Period }) {
|
||||
categories={catalog.c}
|
||||
methods={catalog.m}
|
||||
editingId={editing?.id}
|
||||
readOnly={readOnly}
|
||||
onEdit={edit}
|
||||
onDeleted={(id) => editing?.id === id && setEditing(null)}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user