fixed back button with source, and customer in customer lsit clickable

This commit is contained in:
duffyduck 2026-03-21 12:16:04 +01:00
parent a9643206bb
commit 0121c82412
7 changed files with 38 additions and 23 deletions

View File

@ -282,7 +282,7 @@ export default function ContractCockpit() {
<div className="flex items-center gap-2 flex-wrap">
<Link
to={`/contracts/${contract.id}`}
state={{ from: 'cockpit', filter: filter !== 'all' ? filter : undefined }}
state={{ from: '/contracts/cockpit' }}
className="font-medium hover:underline"
onClick={(e) => e.stopPropagation()}
>
@ -399,7 +399,7 @@ export default function ContractCockpit() {
<Link
to={`/contracts/${contract.id}`}
state={{ from: 'cockpit', filter: filter !== 'all' ? filter : undefined }}
state={{ from: '/contracts/cockpit' }}
className="p-2 hover:bg-white hover:bg-opacity-50 rounded"
onClick={(e) => e.stopPropagation()}
title="Zum Vertrag"

View File

@ -1,5 +1,5 @@
import { useState, useEffect } from 'react';
import { useParams, Link, useNavigate } from 'react-router-dom';
import { useParams, Link, useNavigate, useLocation } from 'react-router-dom';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { contractApi, uploadApi, meterApi, contractTaskApi, appSettingsApi, gdprApi } from '../../services/api';
import { ContractEmailsSection } from '../../components/email';
@ -1210,7 +1210,9 @@ function ContractTaskModal({
export default function ContractDetail() {
const { id } = useParams();
const navigate = useNavigate();
const location = useLocation();
const queryClient = useQueryClient();
const backTo = (location.state as any)?.from as string | undefined;
const { hasPermission, isCustomer, isCustomerPortal } = useAuth();
const contractId = parseInt(id!);
@ -1428,7 +1430,7 @@ export default function ContractDetail() {
return (
<div>
<div className="flex items-center gap-4 mb-6">
<Button variant="ghost" size="sm" onClick={() => navigate(isCustomerPortal ? '/contracts' : (c.customer ? `/customers/${c.customer.id}?tab=contracts` : '/contracts'))}>
<Button variant="ghost" size="sm" onClick={() => navigate(backTo || (isCustomerPortal ? '/contracts' : (c.customer ? `/customers/${c.customer.id}?tab=contracts` : '/contracts')))}>
<ArrowLeft className="w-4 h-4" />
</Button>
<h1 className="text-2xl font-bold">Vertrag {c.contractNumber}</h1>
@ -1463,7 +1465,7 @@ export default function ContractDetail() {
<Button
variant="ghost"
size="sm"
onClick={() => navigate(isCustomerPortal ? '/contracts' : (c.customer ? `/customers/${c.customer.id}?tab=contracts` : '/contracts'))}
onClick={() => navigate(backTo || (isCustomerPortal ? '/contracts' : (c.customer ? `/customers/${c.customer.id}?tab=contracts` : '/contracts')))}
>
<ArrowLeft className="w-4 h-4" />
</Button>
@ -1497,7 +1499,7 @@ export default function ContractDetail() {
{c.customer && (
<p className="text-gray-500 ml-10">
Kunde:{' '}
<Link to={`/customers/${c.customer.id}`} className="text-blue-600 hover:underline">
<Link to={`/customers/${c.customer.id}`} state={{ from: `/contracts/${id}` }} className="text-blue-600 hover:underline">
{c.customer.companyName || `${c.customer.firstName} ${c.customer.lastName}`}
</Link>
</p>
@ -1532,7 +1534,7 @@ export default function ContractDetail() {
</Link>
)}
{hasPermission('contracts:update') && (
<Link to={`/contracts/${id}/edit`}>
<Link to={`/contracts/${id}/edit`} state={{ from: `/contracts/${id}` }}>
<Button variant="secondary">
<Edit className="w-4 h-4 mr-2" />
Bearbeiten

View File

@ -1,5 +1,5 @@
import { useEffect, useState } from 'react';
import { useNavigate, useParams, useSearchParams } from 'react-router-dom';
import { useNavigate, useParams, useSearchParams, useLocation } from 'react-router-dom';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { useForm } from 'react-hook-form';
import { contractApi, customerApi, platformApi, cancellationPeriodApi, contractDurationApi, providerApi, contractCategoryApi } from '../../services/api';
@ -61,8 +61,10 @@ export default function ContractForm() {
const { id } = useParams();
const [searchParams] = useSearchParams();
const navigate = useNavigate();
const location = useLocation();
const queryClient = useQueryClient();
const isEdit = !!id;
const backTo = (location.state as any)?.from as string | undefined;
const preselectedCustomerId = searchParams.get('customerId');
@ -656,7 +658,7 @@ export default function ContractForm() {
return (
<div>
<div className="flex items-center gap-4 mb-6">
<Button variant="ghost" size="sm" onClick={() => navigate(isEdit ? `/contracts/${id}` : '/contracts')}>
<Button variant="ghost" size="sm" onClick={() => navigate(backTo || (isEdit ? `/contracts/${id}` : '/contracts'))}>
<ArrowLeft className="w-4 h-4" />
</Button>
<h1 className="text-2xl font-bold">
@ -1407,7 +1409,7 @@ export default function ContractForm() {
</Card>
<div className="flex justify-end gap-4">
<Button type="button" variant="secondary" onClick={() => navigate(isEdit ? `/contracts/${id}` : '/contracts')}>
<Button type="button" variant="secondary" onClick={() => navigate(backTo || (isEdit ? `/contracts/${id}` : '/contracts'))}>
Abbrechen
</Button>
<Button type="submit" disabled={isLoading}>

View File

@ -271,7 +271,7 @@ export default function ContractList() {
<div className="w-6" /> // Platzhalter für Ausrichtung
) : null}
<Link to={`/contracts/${contract.id}`} className="font-mono flex items-center gap-1 hover:text-blue-600 hover:underline">
<Link to={`/contracts/${contract.id}`} state={{ from: '/contracts' }} className="font-mono flex items-center gap-1 hover:text-blue-600 hover:underline">
{contract.contractNumber}
<CopyButton value={contract.contractNumber} />
</Link>
@ -456,7 +456,7 @@ export default function ContractList() {
{data.data.map((contract) => (
<tr key={contract.id} className="border-b hover:bg-gray-50">
<td className="py-3 px-4 font-mono text-sm">
<Link to={`/contracts/${contract.id}`} className="text-blue-600 hover:underline">
<Link to={`/contracts/${contract.id}`} state={{ from: '/contracts' }} className="text-blue-600 hover:underline">
{contract.contractNumber}
</Link>
</td>
@ -465,6 +465,7 @@ export default function ContractList() {
{contract.customer && (
<Link
to={`/customers/${contract.customer.id}`}
state={{ from: '/contracts' }}
className="text-blue-600 hover:underline"
>
{contract.customer.companyName ||
@ -504,7 +505,7 @@ export default function ContractList() {
<Eye className="w-4 h-4" />
</Button>
{hasPermission('contracts:update') && !isCustomer && (
<Link to={`/contracts/${contract.id}/edit`}>
<Link to={`/contracts/${contract.id}/edit`} state={{ from: '/contracts' }}>
<Button variant="ghost" size="sm">
<Edit className="w-4 h-4" />
</Button>

View File

@ -1,5 +1,5 @@
import { useState, useEffect } from 'react';
import { useParams, Link, useNavigate, useSearchParams } from 'react-router-dom';
import { useParams, Link, useNavigate, useSearchParams, useLocation } from 'react-router-dom';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { customerApi, addressApi, bankCardApi, documentApi, meterApi, uploadApi, contractApi, stressfreiEmailApi, emailProviderApi, gdprApi, StressfreiEmail, ContractTreeNode } from '../../services/api';
import { EmailClientTab } from '../../components/email';
@ -21,6 +21,8 @@ export default function CustomerDetail({ portalCustomerId }: { portalCustomerId?
const navigate = useNavigate();
const queryClient = useQueryClient();
const { hasPermission, isCustomerPortal } = useAuth();
const location = useLocation();
const backTo = (location.state as any)?.from as string | undefined;
const [searchParams, setSearchParams] = useSearchParams();
const customerId = portalCustomerId || parseInt(id!);
const defaultTab = searchParams.get('tab') || 'addresses';
@ -202,7 +204,7 @@ export default function CustomerDetail({ portalCustomerId }: { portalCustomerId?
<div>
<div className="flex items-center justify-between mb-6">
<div className="flex items-center gap-3">
<Button variant="ghost" size="sm" onClick={() => navigate(isCustomerPortal ? '/' : '/customers')}>
<Button variant="ghost" size="sm" onClick={() => navigate(backTo || (isCustomerPortal ? '/' : '/customers'))}>
<ArrowLeft className="w-4 h-4" />
</Button>
<div>
@ -219,7 +221,7 @@ export default function CustomerDetail({ portalCustomerId }: { portalCustomerId?
</div>
<div className="flex gap-2">
{hasPermission('customers:update') && (
<Link to={`/customers/${id}/edit`}>
<Link to={`/customers/${id}/edit`} state={{ from: `/customers/${id}` }}>
<Button variant="secondary">
<Edit className="w-4 h-4 mr-2" />
Bearbeiten
@ -1547,7 +1549,7 @@ function ContractsTab({
<div className="w-6" /> // Platzhalter für Ausrichtung
) : null}
<Link to={`/contracts/${contract.id}`} className="font-mono flex items-center gap-1 text-blue-600 hover:underline">
<Link to={`/contracts/${contract.id}`} state={{ from: `/customers/${customerId}?tab=contracts` }} className="font-mono flex items-center gap-1 text-blue-600 hover:underline">
{contract.contractNumber}
<CopyButton value={contract.contractNumber} />
</Link>

View File

@ -1,5 +1,5 @@
import { useEffect } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import { useNavigate, useParams, useLocation } from 'react-router-dom';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { useForm } from 'react-hook-form';
import { customerApi } from '../../services/api';
@ -14,8 +14,10 @@ type CustomerFormData = Omit<Customer, 'id' | 'customerNumber' | 'createdAt' | '
export default function CustomerForm() {
const { id } = useParams();
const navigate = useNavigate();
const location = useLocation();
const queryClient = useQueryClient();
const isEdit = !!id;
const backTo = (location.state as any)?.from as string | undefined;
const { register, handleSubmit, reset, watch, setValue, formState: { errors } } = useForm<CustomerFormData>();
const customerType = watch('type');
@ -232,7 +234,7 @@ export default function CustomerForm() {
</Card>
<div className="flex justify-end gap-4">
<Button type="button" variant="secondary" onClick={() => navigate(isEdit ? `/customers/${id}` : '/customers')}>
<Button type="button" variant="secondary" onClick={() => navigate(backTo || (isEdit ? `/customers/${id}` : '/customers'))}>
Abbrechen
</Button>
<Button type="submit" disabled={isLoading}>

View File

@ -77,11 +77,17 @@ export default function CustomerList() {
<tbody>
{data.data.map((customer) => (
<tr key={customer.id} className="border-b hover:bg-gray-50">
<td className="py-3 px-4 font-mono text-sm">{customer.customerNumber}</td>
<td className="py-3 px-4 font-mono text-sm">
<Link to={`/customers/${customer.id}`} state={{ from: '/customers' }} className="text-blue-600 hover:underline">
{customer.customerNumber}
</Link>
</td>
<td className="py-3 px-4">
{customer.type === 'BUSINESS' && customer.companyName
? customer.companyName
: `${customer.firstName} ${customer.lastName}`}
<Link to={`/customers/${customer.id}`} state={{ from: '/customers' }} className="text-blue-600 hover:underline">
{customer.type === 'BUSINESS' && customer.companyName
? customer.companyName
: `${customer.firstName} ${customer.lastName}`}
</Link>
</td>
<td className="py-3 px-4">
<Badge variant={customer.type === 'BUSINESS' ? 'info' : 'default'}>