task-f
This commit is contained in:
@@ -40,7 +40,6 @@ import {
|
||||
deleteQuotationFollowupMutation,
|
||||
deleteQuotationItemMutation,
|
||||
deleteQuotationTopicMutation,
|
||||
updateQuotationMutation,
|
||||
updateQuotationAttachmentMutation,
|
||||
updateQuotationCustomerMutation,
|
||||
updateQuotationFollowupMutation,
|
||||
@@ -69,7 +68,9 @@ import type {
|
||||
QuotationTopicMutationPayload,
|
||||
QuotationTopicRecord
|
||||
} from '../api/types';
|
||||
import { submitQuotationApprovalMutation } from '@/features/foundation/approval/mutations';
|
||||
import { QuotationFormSheet } from './quotation-form-sheet';
|
||||
import { QuotationApprovalTab } from './quotation-approval-tab';
|
||||
import { QuotationStatusBadge } from './quotation-status-badge';
|
||||
|
||||
function FieldItem({ label, value }: { label: string; value: string | null | undefined }) {
|
||||
@@ -473,7 +474,14 @@ export function QuotationDetail({
|
||||
canManageTopics,
|
||||
canManageFollowups,
|
||||
canManageAttachments,
|
||||
canCreateRevision
|
||||
canCreateRevision,
|
||||
canSubmitApproval,
|
||||
canApproveApproval,
|
||||
canRejectApproval,
|
||||
canReturnApproval,
|
||||
activeBusinessRole,
|
||||
isOrgAdmin,
|
||||
currentUserId
|
||||
}: {
|
||||
quotationId: string;
|
||||
referenceData: QuotationReferenceData;
|
||||
@@ -484,6 +492,13 @@ export function QuotationDetail({
|
||||
canManageFollowups: boolean;
|
||||
canManageAttachments: boolean;
|
||||
canCreateRevision: boolean;
|
||||
canSubmitApproval: boolean;
|
||||
canApproveApproval: boolean;
|
||||
canRejectApproval: boolean;
|
||||
canReturnApproval: boolean;
|
||||
activeBusinessRole: string | null;
|
||||
isOrgAdmin: boolean;
|
||||
currentUserId: string;
|
||||
}) {
|
||||
const { data } = useSuspenseQuery(quotationByIdOptions(quotationId));
|
||||
const { data: itemsData } = useSuspenseQuery(quotationItemsOptions(quotationId));
|
||||
@@ -611,7 +626,7 @@ export function QuotationDetail({
|
||||
onError: (error) => toast.error(error instanceof Error ? error.message : 'Failed to create revision')
|
||||
});
|
||||
const submitForApproval = useMutation({
|
||||
...updateQuotationMutation,
|
||||
...submitQuotationApprovalMutation,
|
||||
onSuccess: () => toast.success('Quotation moved to pending approval'),
|
||||
onError: (error) =>
|
||||
toast.error(error instanceof Error ? error.message : 'Failed to submit for approval')
|
||||
@@ -655,7 +670,8 @@ export function QuotationDetail({
|
||||
const canReviseByStatus = ['accepted', 'rejected', 'sent', 'approved'].includes(
|
||||
status?.code ?? ''
|
||||
);
|
||||
const canSubmitApproval = ['draft', 'revised'].includes(status?.code ?? '');
|
||||
const canSubmitCurrentQuotation =
|
||||
canSubmitApproval && ['draft', 'revised'].includes(status?.code ?? '');
|
||||
|
||||
return (
|
||||
<div className='space-y-6'>
|
||||
@@ -814,44 +830,11 @@ export function QuotationDetail({
|
||||
</div>
|
||||
</div>
|
||||
<div className='flex flex-wrap gap-2'>
|
||||
{canUpdate && canSubmitApproval ? (
|
||||
{canSubmitCurrentQuotation ? (
|
||||
<Button
|
||||
variant='outline'
|
||||
isLoading={submitForApproval.isPending}
|
||||
onClick={() =>
|
||||
submitForApproval.mutate({
|
||||
id: quotationId,
|
||||
values: {
|
||||
enquiryId: quotation.enquiryId,
|
||||
customerId: quotation.customerId,
|
||||
contactId: quotation.contactId,
|
||||
quotationDate: quotation.quotationDate,
|
||||
validUntil: quotation.validUntil,
|
||||
quotationType: quotation.quotationType,
|
||||
projectName: quotation.projectName ?? '',
|
||||
projectLocation: quotation.projectLocation ?? '',
|
||||
attention: quotation.attention ?? '',
|
||||
branchId: quotation.branchId,
|
||||
currency: quotation.currency,
|
||||
exchangeRate: quotation.exchangeRate,
|
||||
status:
|
||||
referenceData.statuses.find((item) => item.code === 'pending_approval')?.id ??
|
||||
quotation.status,
|
||||
chancePercent: quotation.chancePercent,
|
||||
isHotProject: quotation.isHotProject,
|
||||
competitor: quotation.competitor ?? '',
|
||||
reference: quotation.reference ?? '',
|
||||
notes: quotation.notes ?? '',
|
||||
salesmanId: quotation.salesmanId,
|
||||
discount: quotation.discount,
|
||||
discountType: quotation.discountType,
|
||||
taxRate: quotation.taxRate,
|
||||
sentVia: quotation.sentVia,
|
||||
revisionRemark: quotation.revisionRemark,
|
||||
isActive: quotation.isActive
|
||||
}
|
||||
})
|
||||
}
|
||||
onClick={() => submitForApproval.mutate({ id: quotationId })}
|
||||
>
|
||||
<Icons.send className='mr-2 h-4 w-4' /> Submit for approval
|
||||
</Button>
|
||||
@@ -1191,15 +1174,17 @@ export function QuotationDetail({
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value='approval'>
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Approval Placeholder</CardTitle>
|
||||
<CardDescription>Approval workflow is deferred beyond Task E.</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<EmptyState message='Approval state and approver routing will land in a later task.' />
|
||||
</CardContent>
|
||||
</Card>
|
||||
<QuotationApprovalTab
|
||||
quotationId={quotationId}
|
||||
quotationStatusCode={status?.code ?? null}
|
||||
canSubmitApproval={canSubmitApproval}
|
||||
canApproveApproval={canApproveApproval}
|
||||
canRejectApproval={canRejectApproval}
|
||||
canReturnApproval={canReturnApproval}
|
||||
activeBusinessRole={activeBusinessRole}
|
||||
isOrgAdmin={isOrgAdmin}
|
||||
currentUserId={currentUserId}
|
||||
/>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value='preview'>
|
||||
|
||||
Reference in New Issue
Block a user