@hed-hog/contact 0.0.333 → 0.0.347
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/person/person.controller.d.ts +4 -5
- package/dist/person/person.controller.d.ts.map +1 -1
- package/dist/person/person.controller.js +7 -3
- package/dist/person/person.controller.js.map +1 -1
- package/dist/person/person.service.d.ts +6 -3
- package/dist/person/person.service.d.ts.map +1 -1
- package/dist/person/person.service.js +104 -23
- package/dist/person/person.service.js.map +1 -1
- package/hedhog/data/role.yaml +9 -1
- package/hedhog/endpoint/person.yaml +263 -0
- package/hedhog/frontend/app/_components/person-picker.tsx.ejs +7 -5
- package/hedhog/frontend/app/accounts/page.tsx.ejs +6 -1
- package/hedhog/frontend/app/activities/page.tsx.ejs +6 -1
- package/hedhog/frontend/app/contact-type/page.tsx.ejs +6 -1
- package/hedhog/frontend/app/document-type/page.tsx.ejs +6 -1
- package/hedhog/frontend/app/follow-ups/page.tsx.ejs +6 -1
- package/hedhog/frontend/app/person/_components/person-form-sheet.tsx.ejs +24 -23
- package/hedhog/frontend/app/person/_components/person-import-sheet.tsx.ejs +102 -102
- package/hedhog/frontend/app/person/page.tsx.ejs +6 -1
- package/hedhog/frontend/app/proposals/_components/proposal-form-sheet.tsx.ejs +1306 -1306
- package/hedhog/frontend/app/proposals/_components/proposal-types.ts.ejs +172 -172
- package/hedhog/frontend/app/proposals/_components/proposals-management-page.tsx.ejs +74 -95
- package/package.json +5 -5
- package/src/person/person.controller.ts +29 -22
- package/src/person/person.service.ts +128 -26
|
@@ -1,172 +1,172 @@
|
|
|
1
|
-
export type ProposalStatus =
|
|
2
|
-
| 'draft'
|
|
3
|
-
| 'pending_approval'
|
|
4
|
-
| 'approved'
|
|
5
|
-
| 'rejected'
|
|
6
|
-
| 'cancelled'
|
|
7
|
-
| 'expired'
|
|
8
|
-
| 'contract_generated';
|
|
9
|
-
|
|
10
|
-
export type ProposalContractCategory =
|
|
11
|
-
| 'employee'
|
|
12
|
-
| 'contractor'
|
|
13
|
-
| 'client'
|
|
14
|
-
| 'supplier'
|
|
15
|
-
| 'vendor'
|
|
16
|
-
| 'partner'
|
|
17
|
-
| 'internal'
|
|
18
|
-
| 'other';
|
|
19
|
-
|
|
20
|
-
export type ProposalContractType =
|
|
21
|
-
| 'clt'
|
|
22
|
-
| 'pj'
|
|
23
|
-
| 'freelancer_agreement'
|
|
24
|
-
| 'service_agreement'
|
|
25
|
-
| 'fixed_term'
|
|
26
|
-
| 'recurring_service'
|
|
27
|
-
| 'nda'
|
|
28
|
-
| 'amendment'
|
|
29
|
-
| 'addendum'
|
|
30
|
-
| 'other';
|
|
31
|
-
|
|
32
|
-
export type ProposalBillingModel =
|
|
33
|
-
| 'time_and_material'
|
|
34
|
-
| 'monthly_retainer'
|
|
35
|
-
| 'fixed_price';
|
|
36
|
-
|
|
37
|
-
export type ProposalItemType =
|
|
38
|
-
| 'service'
|
|
39
|
-
| 'product'
|
|
40
|
-
| 'fee'
|
|
41
|
-
| 'discount'
|
|
42
|
-
| 'note'
|
|
43
|
-
| 'other';
|
|
44
|
-
|
|
45
|
-
export type ProposalRecurrence =
|
|
46
|
-
| 'one_time'
|
|
47
|
-
| 'monthly'
|
|
48
|
-
| 'quarterly'
|
|
49
|
-
| 'yearly'
|
|
50
|
-
| 'other';
|
|
51
|
-
|
|
52
|
-
export type ProposalItem = {
|
|
53
|
-
id?: number;
|
|
54
|
-
name: string;
|
|
55
|
-
description?: string | null;
|
|
56
|
-
quantity?: number | null;
|
|
57
|
-
unit_amount_cents?: number | null;
|
|
58
|
-
total_amount_cents?: number | null;
|
|
59
|
-
item_type?: ProposalItemType | string | null;
|
|
60
|
-
term_type?: string | null;
|
|
61
|
-
recurrence?: ProposalRecurrence | string | null;
|
|
62
|
-
start_date?: string | null;
|
|
63
|
-
end_date?: string | null;
|
|
64
|
-
due_day?: number | null;
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
export type ProposalRevision = {
|
|
68
|
-
id: number;
|
|
69
|
-
revision_number: number;
|
|
70
|
-
is_current?: boolean;
|
|
71
|
-
title: string;
|
|
72
|
-
summary?: string | null;
|
|
73
|
-
valid_until?: string | null;
|
|
74
|
-
status?: ProposalStatus | string;
|
|
75
|
-
proposal_item?: ProposalItem[];
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
export type ProposalApproval = {
|
|
79
|
-
id: number;
|
|
80
|
-
status?: string | null;
|
|
81
|
-
decision_note?: string | null;
|
|
82
|
-
submitted_at?: string | null;
|
|
83
|
-
decided_at?: string | null;
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
export type ProposalDocument = {
|
|
87
|
-
id: number;
|
|
88
|
-
file_id?: number | null;
|
|
89
|
-
file_name?: string | null;
|
|
90
|
-
mime_type?: string | null;
|
|
91
|
-
document_type?: string | null;
|
|
92
|
-
is_current?: boolean | null;
|
|
93
|
-
created_at?: string | null;
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
export type ProposalIntegrationLink = {
|
|
97
|
-
targetModule?: string;
|
|
98
|
-
targetEntityType?: string;
|
|
99
|
-
targetEntityId?: string;
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
export type ProposalRecord = {
|
|
103
|
-
id: number;
|
|
104
|
-
person_id: number;
|
|
105
|
-
code?: string | null;
|
|
106
|
-
title: string;
|
|
107
|
-
status: ProposalStatus;
|
|
108
|
-
contract_category?: ProposalContractCategory | null;
|
|
109
|
-
contract_type?: ProposalContractType | null;
|
|
110
|
-
billing_model?: ProposalBillingModel | null;
|
|
111
|
-
currency_code?: string | null;
|
|
112
|
-
subtotal_amount_cents?: number | null;
|
|
113
|
-
discount_amount_cents?: number | null;
|
|
114
|
-
tax_amount_cents?: number | null;
|
|
115
|
-
total_amount_cents?: number | null;
|
|
116
|
-
valid_until?: string | null;
|
|
117
|
-
current_revision_number?: number | null;
|
|
118
|
-
approval_count?: number | null;
|
|
119
|
-
required_approvals?: number | null;
|
|
120
|
-
current_user_has_approved?: boolean | null;
|
|
121
|
-
notes?: string | null;
|
|
122
|
-
created_at?: string | null;
|
|
123
|
-
updated_at?: string | null;
|
|
124
|
-
approved_at?: string | null;
|
|
125
|
-
person?: {
|
|
126
|
-
id: number;
|
|
127
|
-
name?: string | null;
|
|
128
|
-
trade_name?: string | null;
|
|
129
|
-
email?: string | null;
|
|
130
|
-
phone?: string | null;
|
|
131
|
-
avatar_id?: number | null;
|
|
132
|
-
} | null;
|
|
133
|
-
proposal_revision?: ProposalRevision[];
|
|
134
|
-
proposal_approval?: ProposalApproval[];
|
|
135
|
-
proposal_document?: ProposalDocument[];
|
|
136
|
-
integration_links?: ProposalIntegrationLink[];
|
|
137
|
-
};
|
|
138
|
-
|
|
139
|
-
export type GenerateProposalDocumentResponse = {
|
|
140
|
-
fileId?: number | null;
|
|
141
|
-
fileName?: string | null;
|
|
142
|
-
downloadUrl?: string | null;
|
|
143
|
-
};
|
|
144
|
-
|
|
145
|
-
// ─── Shared utilities ────────────────────────────────────────────────────────
|
|
146
|
-
|
|
147
|
-
export function formatEnumLabel(value?: string | null) {
|
|
148
|
-
if (!value) return '—';
|
|
149
|
-
return value
|
|
150
|
-
.split('_')
|
|
151
|
-
.filter(Boolean)
|
|
152
|
-
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
|
153
|
-
.join(' ');
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
export function getCurrentRevision(proposal?: ProposalRecord | null) {
|
|
157
|
-
if (!proposal?.proposal_revision?.length) return null;
|
|
158
|
-
return (
|
|
159
|
-
proposal.proposal_revision.find((revision) => revision.is_current) ??
|
|
160
|
-
proposal.proposal_revision[0]
|
|
161
|
-
);
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
export function openStoredFile(fileId?: number | null) {
|
|
165
|
-
if (!fileId) return;
|
|
166
|
-
const baseUrl = String(process.env.NEXT_PUBLIC_API_BASE_URL || '');
|
|
167
|
-
window.open(
|
|
168
|
-
`${baseUrl}/file/open/${fileId}`,
|
|
169
|
-
'_blank',
|
|
170
|
-
'noopener,noreferrer'
|
|
171
|
-
);
|
|
172
|
-
}
|
|
1
|
+
export type ProposalStatus =
|
|
2
|
+
| 'draft'
|
|
3
|
+
| 'pending_approval'
|
|
4
|
+
| 'approved'
|
|
5
|
+
| 'rejected'
|
|
6
|
+
| 'cancelled'
|
|
7
|
+
| 'expired'
|
|
8
|
+
| 'contract_generated';
|
|
9
|
+
|
|
10
|
+
export type ProposalContractCategory =
|
|
11
|
+
| 'employee'
|
|
12
|
+
| 'contractor'
|
|
13
|
+
| 'client'
|
|
14
|
+
| 'supplier'
|
|
15
|
+
| 'vendor'
|
|
16
|
+
| 'partner'
|
|
17
|
+
| 'internal'
|
|
18
|
+
| 'other';
|
|
19
|
+
|
|
20
|
+
export type ProposalContractType =
|
|
21
|
+
| 'clt'
|
|
22
|
+
| 'pj'
|
|
23
|
+
| 'freelancer_agreement'
|
|
24
|
+
| 'service_agreement'
|
|
25
|
+
| 'fixed_term'
|
|
26
|
+
| 'recurring_service'
|
|
27
|
+
| 'nda'
|
|
28
|
+
| 'amendment'
|
|
29
|
+
| 'addendum'
|
|
30
|
+
| 'other';
|
|
31
|
+
|
|
32
|
+
export type ProposalBillingModel =
|
|
33
|
+
| 'time_and_material'
|
|
34
|
+
| 'monthly_retainer'
|
|
35
|
+
| 'fixed_price';
|
|
36
|
+
|
|
37
|
+
export type ProposalItemType =
|
|
38
|
+
| 'service'
|
|
39
|
+
| 'product'
|
|
40
|
+
| 'fee'
|
|
41
|
+
| 'discount'
|
|
42
|
+
| 'note'
|
|
43
|
+
| 'other';
|
|
44
|
+
|
|
45
|
+
export type ProposalRecurrence =
|
|
46
|
+
| 'one_time'
|
|
47
|
+
| 'monthly'
|
|
48
|
+
| 'quarterly'
|
|
49
|
+
| 'yearly'
|
|
50
|
+
| 'other';
|
|
51
|
+
|
|
52
|
+
export type ProposalItem = {
|
|
53
|
+
id?: number;
|
|
54
|
+
name: string;
|
|
55
|
+
description?: string | null;
|
|
56
|
+
quantity?: number | null;
|
|
57
|
+
unit_amount_cents?: number | null;
|
|
58
|
+
total_amount_cents?: number | null;
|
|
59
|
+
item_type?: ProposalItemType | string | null;
|
|
60
|
+
term_type?: string | null;
|
|
61
|
+
recurrence?: ProposalRecurrence | string | null;
|
|
62
|
+
start_date?: string | null;
|
|
63
|
+
end_date?: string | null;
|
|
64
|
+
due_day?: number | null;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export type ProposalRevision = {
|
|
68
|
+
id: number;
|
|
69
|
+
revision_number: number;
|
|
70
|
+
is_current?: boolean;
|
|
71
|
+
title: string;
|
|
72
|
+
summary?: string | null;
|
|
73
|
+
valid_until?: string | null;
|
|
74
|
+
status?: ProposalStatus | string;
|
|
75
|
+
proposal_item?: ProposalItem[];
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export type ProposalApproval = {
|
|
79
|
+
id: number;
|
|
80
|
+
status?: string | null;
|
|
81
|
+
decision_note?: string | null;
|
|
82
|
+
submitted_at?: string | null;
|
|
83
|
+
decided_at?: string | null;
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
export type ProposalDocument = {
|
|
87
|
+
id: number;
|
|
88
|
+
file_id?: number | null;
|
|
89
|
+
file_name?: string | null;
|
|
90
|
+
mime_type?: string | null;
|
|
91
|
+
document_type?: string | null;
|
|
92
|
+
is_current?: boolean | null;
|
|
93
|
+
created_at?: string | null;
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
export type ProposalIntegrationLink = {
|
|
97
|
+
targetModule?: string;
|
|
98
|
+
targetEntityType?: string;
|
|
99
|
+
targetEntityId?: string;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
export type ProposalRecord = {
|
|
103
|
+
id: number;
|
|
104
|
+
person_id: number;
|
|
105
|
+
code?: string | null;
|
|
106
|
+
title: string;
|
|
107
|
+
status: ProposalStatus;
|
|
108
|
+
contract_category?: ProposalContractCategory | null;
|
|
109
|
+
contract_type?: ProposalContractType | null;
|
|
110
|
+
billing_model?: ProposalBillingModel | null;
|
|
111
|
+
currency_code?: string | null;
|
|
112
|
+
subtotal_amount_cents?: number | null;
|
|
113
|
+
discount_amount_cents?: number | null;
|
|
114
|
+
tax_amount_cents?: number | null;
|
|
115
|
+
total_amount_cents?: number | null;
|
|
116
|
+
valid_until?: string | null;
|
|
117
|
+
current_revision_number?: number | null;
|
|
118
|
+
approval_count?: number | null;
|
|
119
|
+
required_approvals?: number | null;
|
|
120
|
+
current_user_has_approved?: boolean | null;
|
|
121
|
+
notes?: string | null;
|
|
122
|
+
created_at?: string | null;
|
|
123
|
+
updated_at?: string | null;
|
|
124
|
+
approved_at?: string | null;
|
|
125
|
+
person?: {
|
|
126
|
+
id: number;
|
|
127
|
+
name?: string | null;
|
|
128
|
+
trade_name?: string | null;
|
|
129
|
+
email?: string | null;
|
|
130
|
+
phone?: string | null;
|
|
131
|
+
avatar_id?: number | null;
|
|
132
|
+
} | null;
|
|
133
|
+
proposal_revision?: ProposalRevision[];
|
|
134
|
+
proposal_approval?: ProposalApproval[];
|
|
135
|
+
proposal_document?: ProposalDocument[];
|
|
136
|
+
integration_links?: ProposalIntegrationLink[];
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
export type GenerateProposalDocumentResponse = {
|
|
140
|
+
fileId?: number | null;
|
|
141
|
+
fileName?: string | null;
|
|
142
|
+
downloadUrl?: string | null;
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
// ─── Shared utilities ────────────────────────────────────────────────────────
|
|
146
|
+
|
|
147
|
+
export function formatEnumLabel(value?: string | null) {
|
|
148
|
+
if (!value) return '—';
|
|
149
|
+
return value
|
|
150
|
+
.split('_')
|
|
151
|
+
.filter(Boolean)
|
|
152
|
+
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
|
153
|
+
.join(' ');
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export function getCurrentRevision(proposal?: ProposalRecord | null) {
|
|
157
|
+
if (!proposal?.proposal_revision?.length) return null;
|
|
158
|
+
return (
|
|
159
|
+
proposal.proposal_revision.find((revision) => revision.is_current) ??
|
|
160
|
+
proposal.proposal_revision[0]
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export function openStoredFile(fileId?: number | null) {
|
|
165
|
+
if (!fileId) return;
|
|
166
|
+
const baseUrl = String(process.env.NEXT_PUBLIC_API_BASE_URL || '');
|
|
167
|
+
window.open(
|
|
168
|
+
`${baseUrl}/file/open/${fileId}`,
|
|
169
|
+
'_blank',
|
|
170
|
+
'noopener,noreferrer'
|
|
171
|
+
);
|
|
172
|
+
}
|
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
TableRow,
|
|
31
31
|
} from '@/components/ui/table';
|
|
32
32
|
import { ToggleGroup, ToggleGroupItem } from '@/components/ui/toggle-group';
|
|
33
|
+
import { usePersistedPageSize } from '@/hooks/use-persisted-page-size';
|
|
33
34
|
import { cn } from '@/lib/utils';
|
|
34
35
|
import { useApp, useQuery } from '@hed-hog/next-app-provider';
|
|
35
36
|
import {
|
|
@@ -197,7 +198,11 @@ export function ProposalsManagementPage({
|
|
|
197
198
|
const [statusFilter, setStatusFilter] =
|
|
198
199
|
useState<ProposalStatusFilter>(defaultStatus);
|
|
199
200
|
const [page, setPage] = useState(1);
|
|
200
|
-
const [pageSize, setPageSize] =
|
|
201
|
+
const [pageSize, setPageSize] = usePersistedPageSize({
|
|
202
|
+
storageKey: 'pagination:global:pageSize',
|
|
203
|
+
defaultValue: 12,
|
|
204
|
+
allowedValues: [12, 24, 36, 48],
|
|
205
|
+
});
|
|
201
206
|
const [viewMode, setViewMode] = useState<ProposalViewMode>('table');
|
|
202
207
|
const [actionKey, setActionKey] = useState<string | null>(null);
|
|
203
208
|
const [editSheetOpen, setEditSheetOpen] = useState(false);
|
|
@@ -677,101 +682,86 @@ export function ProposalsManagementPage({
|
|
|
677
682
|
</TableCell>
|
|
678
683
|
|
|
679
684
|
<TableCell className="text-right">
|
|
680
|
-
<
|
|
681
|
-
|
|
685
|
+
<DropdownMenu>
|
|
686
|
+
<DropdownMenuTrigger asChild>
|
|
682
687
|
<Button
|
|
683
|
-
variant="
|
|
684
|
-
size="
|
|
685
|
-
className="
|
|
686
|
-
onClick={() => handleEdit(proposal)}
|
|
688
|
+
variant="ghost"
|
|
689
|
+
size="icon"
|
|
690
|
+
className="h-8 w-8"
|
|
687
691
|
>
|
|
688
|
-
|
|
689
|
-
{
|
|
692
|
+
{actionKey?.startsWith(`${proposal.id}-`) ||
|
|
693
|
+
actionKey === `generate-pdf-${proposal.id}` ||
|
|
694
|
+
actionKey === `submit-${proposal.id}` ||
|
|
695
|
+
actionKey === `approve-${proposal.id}` ||
|
|
696
|
+
actionKey === `reject-${proposal.id}` ? (
|
|
697
|
+
<Loader2 className="h-4 w-4 animate-spin" />
|
|
698
|
+
) : (
|
|
699
|
+
<MoreHorizontal className="h-4 w-4" />
|
|
700
|
+
)}
|
|
690
701
|
</Button>
|
|
691
|
-
|
|
692
|
-
<
|
|
693
|
-
|
|
694
|
-
<
|
|
695
|
-
|
|
696
|
-
size="icon"
|
|
697
|
-
className="h-8 w-8"
|
|
702
|
+
</DropdownMenuTrigger>
|
|
703
|
+
<DropdownMenuContent align="end">
|
|
704
|
+
{canEditProposal(proposal.status) ? (
|
|
705
|
+
<DropdownMenuItem
|
|
706
|
+
onClick={() => handleEdit(proposal)}
|
|
698
707
|
>
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
)
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
708
|
+
<Pencil className="mr-2 h-4 w-4" />
|
|
709
|
+
{proposalT('actions.edit')}
|
|
710
|
+
</DropdownMenuItem>
|
|
711
|
+
) : null}
|
|
712
|
+
|
|
713
|
+
{canSubmitProposal(proposal.status) ? (
|
|
714
|
+
<DropdownMenuItem
|
|
715
|
+
disabled={actionKey === `submit-${proposal.id}`}
|
|
716
|
+
onClick={() =>
|
|
717
|
+
void handleStatusAction(proposal, 'submit')
|
|
718
|
+
}
|
|
719
|
+
>
|
|
720
|
+
<Send className="mr-2 h-4 w-4" />
|
|
721
|
+
{proposalT('actions.submit')}
|
|
722
|
+
</DropdownMenuItem>
|
|
723
|
+
) : null}
|
|
724
|
+
|
|
725
|
+
{proposal.status === 'pending_approval' &&
|
|
726
|
+
!proposal.current_user_has_approved ? (
|
|
727
|
+
<>
|
|
712
728
|
<DropdownMenuItem
|
|
713
|
-
|
|
729
|
+
disabled={
|
|
730
|
+
actionKey === `approve-${proposal.id}`
|
|
731
|
+
}
|
|
732
|
+
onClick={() =>
|
|
733
|
+
void handleStatusAction(proposal, 'approve')
|
|
734
|
+
}
|
|
714
735
|
>
|
|
715
|
-
<
|
|
716
|
-
{proposalT('actions.
|
|
736
|
+
<CheckCircle2 className="mr-2 h-4 w-4" />
|
|
737
|
+
{proposalT('actions.approve')}
|
|
717
738
|
</DropdownMenuItem>
|
|
718
|
-
) : null}
|
|
719
|
-
|
|
720
|
-
{canSubmitProposal(proposal.status) ? (
|
|
721
739
|
<DropdownMenuItem
|
|
722
|
-
disabled={actionKey === `
|
|
740
|
+
disabled={actionKey === `reject-${proposal.id}`}
|
|
741
|
+
className="text-destructive focus:text-destructive"
|
|
723
742
|
onClick={() =>
|
|
724
|
-
void handleStatusAction(proposal, '
|
|
743
|
+
void handleStatusAction(proposal, 'reject')
|
|
725
744
|
}
|
|
726
745
|
>
|
|
727
|
-
<
|
|
728
|
-
{proposalT('actions.
|
|
746
|
+
<XCircle className="mr-2 h-4 w-4" />
|
|
747
|
+
{proposalT('actions.reject')}
|
|
729
748
|
</DropdownMenuItem>
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
{proposal.status === 'pending_approval' &&
|
|
733
|
-
!proposal.current_user_has_approved ? (
|
|
734
|
-
<>
|
|
735
|
-
<DropdownMenuItem
|
|
736
|
-
disabled={
|
|
737
|
-
actionKey === `approve-${proposal.id}`
|
|
738
|
-
}
|
|
739
|
-
onClick={() =>
|
|
740
|
-
void handleStatusAction(proposal, 'approve')
|
|
741
|
-
}
|
|
742
|
-
>
|
|
743
|
-
<CheckCircle2 className="mr-2 h-4 w-4" />
|
|
744
|
-
{proposalT('actions.approve')}
|
|
745
|
-
</DropdownMenuItem>
|
|
746
|
-
<DropdownMenuItem
|
|
747
|
-
disabled={
|
|
748
|
-
actionKey === `reject-${proposal.id}`
|
|
749
|
-
}
|
|
750
|
-
className="text-destructive focus:text-destructive"
|
|
751
|
-
onClick={() =>
|
|
752
|
-
void handleStatusAction(proposal, 'reject')
|
|
753
|
-
}
|
|
754
|
-
>
|
|
755
|
-
<XCircle className="mr-2 h-4 w-4" />
|
|
756
|
-
{proposalT('actions.reject')}
|
|
757
|
-
</DropdownMenuItem>
|
|
758
|
-
</>
|
|
759
|
-
) : null}
|
|
760
|
-
|
|
761
|
-
<DropdownMenuSeparator />
|
|
749
|
+
</>
|
|
750
|
+
) : null}
|
|
762
751
|
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
752
|
+
<DropdownMenuSeparator />
|
|
753
|
+
|
|
754
|
+
<DropdownMenuItem
|
|
755
|
+
disabled={
|
|
756
|
+
actionKey === `generate-pdf-${proposal.id}`
|
|
757
|
+
}
|
|
758
|
+
onClick={() => void handleGeneratePdf(proposal)}
|
|
759
|
+
>
|
|
760
|
+
<FileText className="mr-2 h-4 w-4" />
|
|
761
|
+
{proposalT('actions.generatePdf')}
|
|
762
|
+
</DropdownMenuItem>
|
|
763
|
+
</DropdownMenuContent>
|
|
764
|
+
</DropdownMenu>
|
|
775
765
|
</TableCell>
|
|
776
766
|
</TableRow>
|
|
777
767
|
);
|
|
@@ -867,18 +857,7 @@ export function ProposalsManagementPage({
|
|
|
867
857
|
</div>
|
|
868
858
|
</div>
|
|
869
859
|
|
|
870
|
-
<div className="mt-auto flex justify-end
|
|
871
|
-
{canEditProposal(proposal.status) ? (
|
|
872
|
-
<Button
|
|
873
|
-
variant="outline"
|
|
874
|
-
size="sm"
|
|
875
|
-
className="gap-1.5"
|
|
876
|
-
onClick={() => handleEdit(proposal)}
|
|
877
|
-
>
|
|
878
|
-
<Pencil className="h-3.5 w-3.5" />
|
|
879
|
-
{proposalT('actions.edit')}
|
|
880
|
-
</Button>
|
|
881
|
-
) : null}
|
|
860
|
+
<div className="mt-auto flex justify-end">
|
|
882
861
|
<DropdownMenu>
|
|
883
862
|
<DropdownMenuTrigger asChild>
|
|
884
863
|
<Button variant="outline" size="sm" className="gap-1.5">
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hed-hog/contact",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.347",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"dependencies": {
|
|
@@ -10,13 +10,13 @@
|
|
|
10
10
|
"@nestjs/jwt": "^11",
|
|
11
11
|
"@nestjs/mapped-types": "*",
|
|
12
12
|
"playwright": "^1.49.0",
|
|
13
|
+
"@hed-hog/address": "0.0.347",
|
|
14
|
+
"@hed-hog/core": "0.0.347",
|
|
13
15
|
"@hed-hog/api": "0.0.8",
|
|
14
|
-
"@hed-hog/api-locale": "0.0.14",
|
|
15
16
|
"@hed-hog/api-prisma": "0.0.6",
|
|
16
|
-
"@hed-hog/api-mail": "0.0.9",
|
|
17
17
|
"@hed-hog/api-pagination": "0.0.7",
|
|
18
|
-
"@hed-hog/
|
|
19
|
-
"@hed-hog/
|
|
18
|
+
"@hed-hog/api-mail": "0.0.9",
|
|
19
|
+
"@hed-hog/api-locale": "0.0.14"
|
|
20
20
|
},
|
|
21
21
|
"exports": {
|
|
22
22
|
".": {
|
|
@@ -2,28 +2,28 @@ import { DeleteDTO, Public, Role, User } from '@hed-hog/api';
|
|
|
2
2
|
import { Locale } from '@hed-hog/api-locale';
|
|
3
3
|
import { Pagination } from '@hed-hog/api-pagination';
|
|
4
4
|
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
5
|
+
BadRequestException,
|
|
6
|
+
Body,
|
|
7
|
+
Controller,
|
|
8
|
+
Delete,
|
|
9
|
+
Get,
|
|
10
|
+
Inject,
|
|
11
|
+
Param,
|
|
12
|
+
ParseIntPipe,
|
|
13
|
+
Patch,
|
|
14
|
+
Post,
|
|
15
|
+
Query,
|
|
16
|
+
Res,
|
|
17
|
+
UploadedFile,
|
|
18
|
+
UseInterceptors,
|
|
19
|
+
forwardRef
|
|
20
20
|
} from '@nestjs/common';
|
|
21
21
|
import { FileInterceptor } from '@nestjs/platform-express';
|
|
22
22
|
import { Response } from 'express';
|
|
23
23
|
import {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
AccountListQueryDTO,
|
|
25
|
+
CreateAccountDTO,
|
|
26
|
+
UpdateAccountDTO,
|
|
27
27
|
} from './dto/account.dto';
|
|
28
28
|
import { ActivityListQueryDTO } from './dto/activity.dto';
|
|
29
29
|
import { CreateFollowupDTO } from './dto/create-followup.dto';
|
|
@@ -32,8 +32,8 @@ import { CreateDTO } from './dto/create.dto';
|
|
|
32
32
|
import { DashboardQueryDTO } from './dto/dashboard-query.dto';
|
|
33
33
|
import { CheckPersonDuplicatesQueryDTO } from './dto/duplicates-query.dto';
|
|
34
34
|
import {
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
FollowupListQueryDTO,
|
|
36
|
+
FollowupStatsQueryDTO,
|
|
37
37
|
} from './dto/followup-query.dto';
|
|
38
38
|
import { MergePersonDTO } from './dto/merge.dto';
|
|
39
39
|
import { ReportsQueryDTO } from './dto/reports-query.dto';
|
|
@@ -264,8 +264,15 @@ export class PersonController {
|
|
|
264
264
|
}
|
|
265
265
|
|
|
266
266
|
@Post()
|
|
267
|
-
async create(
|
|
268
|
-
|
|
267
|
+
async create(
|
|
268
|
+
@Body() data: CreateDTO,
|
|
269
|
+
@Locale() locale: string,
|
|
270
|
+
@User() user,
|
|
271
|
+
) {
|
|
272
|
+
return this.personService.create(data, locale, {
|
|
273
|
+
id: Number(user?.id || 0),
|
|
274
|
+
name: user?.name,
|
|
275
|
+
});
|
|
269
276
|
}
|
|
270
277
|
|
|
271
278
|
@Post('merge')
|