Skip to content

Commit da2a386

Browse files
authored
[Feat] 백엔드 API 응답 필드 추가 반영 - 계약 목록/급여 상세
* [Feat] 백엔드 API 응답 필드 추가 반영 (급여명세서) (#17) - ContractListItem에 workplaceId, workplaceName, paymentDay, payrollDeductionType 필드 추가 - SalaryDetailResponse에 4대보험 개별 항목 및 주휴수당 필드 추가 - useWorkplaces: getContractDetail N+1 호출 제거, 리스트 응답에서 직접 사용 - useSalaryStatement: getContractDetail N+1 호출 제거, 리스트 응답에서 직접 사용 - DeductionSection: 4대보험 개별 항목 실제 값 표시 (국민연금/건강보험/장기요양보험/고용보험) * [Chore] 가족수당/노동조합비 항목 삭제 - DeductionSection에서 노동조합비 행 제거 - PaymentSection에서 가족수당 행 제거 - 백엔드와 협의하여 미사용 확정 * [Feat] 주휴수당 급여명세서 UI 표시 추가 - PaymentSection에 weeklyPaidLeaveAmount(주휴수당) SalaryItemRow 추가 - 휴일근로수당 아래에 배치
1 parent 451e85e commit da2a386

5 files changed

Lines changed: 42 additions & 49 deletions

File tree

src/api/worker/types.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,17 @@ export type PayrollDeductionType = 'FREELANCER' | 'PART_TIME_NONE' | 'PART_TIME_
66
// 계약 목록 아이템 (GET /api/worker/contracts)
77
export interface ContractListItem {
88
id: number;
9+
workplaceId: number;
10+
workplaceName: string;
911
workerName: string;
1012
workerCode: string;
1113
workerPhone: string;
1214
hourlyWage: number;
1315
contractStartDate: string;
1416
contractEndDate: string | null;
17+
paymentDay: number;
18+
payrollDeductionType: PayrollDeductionType;
1519
isActive: boolean;
16-
workplaceName?: string;
1720
}
1821

1922
// 계약 상세 (GET /api/worker/contracts/{id})
@@ -170,8 +173,13 @@ export interface SalaryDetailResponse {
170173
overtimePay: number;
171174
nightPay: number;
172175
holidayPay: number;
176+
weeklyPaidLeaveAmount: number;
173177
totalGrossPay: number;
174178
fourMajorInsurance: number;
179+
nationalPension: number;
180+
healthInsurance: number;
181+
longTermCare: number;
182+
employmentInsurance: number;
175183
incomeTax: number;
176184
localIncomeTax: number;
177185
totalDeduction: number;

src/components/worker/salary/DeductionSection.tsx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,10 @@ const DeductionSection: React.FC<DeductionSectionProps> = ({ salary }) => {
2424
label="지방소득세"
2525
value={salary?.localIncomeTax ?? null}
2626
/>
27-
{/* 4대보험 개별 항목: 백엔드에서 개별 필드 추가 전까지 ? 표시 */}
28-
<SalaryItemRow label="국민연금" value={null} />
29-
<SalaryItemRow label="고용보험" value={null} />
30-
<SalaryItemRow label="건강보험" value={null} />
31-
<SalaryItemRow label="장기요양보험" value={null} />
32-
<SalaryItemRow label="노동조합비" value={null} />
27+
<SalaryItemRow label="국민연금" value={salary?.nationalPension ?? null} />
28+
<SalaryItemRow label="고용보험" value={salary?.employmentInsurance ?? null} />
29+
<SalaryItemRow label="건강보험" value={salary?.healthInsurance ?? null} />
30+
<SalaryItemRow label="장기요양보험" value={salary?.longTermCare ?? null} />
3331
<View style={styles.divider} />
3432
<View style={styles.subtotalRow}>
3533
<Text style={styles.subtotalText} weight="SemiBold">

src/components/worker/salary/PaymentSection.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,10 @@ const PaymentSection: React.FC<PaymentSectionProps> = ({ salary }) => {
3232
label="휴일근로수당"
3333
value={salary?.holidayPay ?? null}
3434
/>
35-
<SalaryItemRow label="가족수당" value={null} />
35+
<SalaryItemRow
36+
label="주휴수당"
37+
value={salary?.weeklyPaidLeaveAmount ?? null}
38+
/>
3639
<View style={styles.divider} />
3740
<View style={styles.subtotalRow}>
3841
<Text style={styles.subtotalText} weight="SemiBold">

src/hooks/worker/useSalaryStatement.ts

Lines changed: 17 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,10 @@
11
/**
22
* 급여명세서 바텀시트 데이터 관리 훅.
3-
* 계약 목록 → 계약 상세(근무지명, payrollDeductionType) + 급여 계산을 병렬 호출하여
4-
* 근무지별 급여명세서 데이터를 구성.
3+
* 계약 목록 응답에서 근무지명, payrollDeductionType을 직접 사용하고
4+
* 급여 계산만 병렬 호출하여 근무지별 급여명세서 데이터를 구성.
55
*/
66
import { useState, useCallback } from "react";
7-
import {
8-
getContracts,
9-
getContractDetail,
10-
calculateSalary,
11-
} from "../../api/worker";
7+
import { getContracts, calculateSalary } from "../../api/worker";
128
import type {
139
PayrollDeductionType,
1410
SalaryCalculateResponse,
@@ -35,29 +31,23 @@ const useSalaryStatement = (year: number, month: number) => {
3531

3632
const results = await Promise.all(
3733
activeContracts.map(async (contract) => {
38-
const [detailRes, salaryRes] = await Promise.allSettled([
39-
getContractDetail(contract.id),
40-
calculateSalary(contract.id, year, month),
41-
]);
42-
43-
const detail =
44-
detailRes.status === "fulfilled"
45-
? detailRes.value.data
46-
: null;
47-
const salary =
48-
salaryRes.status === "fulfilled"
49-
? salaryRes.value.data
50-
: null;
34+
let salary: SalaryCalculateResponse | null = null;
35+
try {
36+
const salaryRes = await calculateSalary(
37+
contract.id,
38+
year,
39+
month
40+
);
41+
salary = salaryRes.data ?? null;
42+
} catch {
43+
// 급여 계산 실패 시 null
44+
}
5145

5246
return {
5347
contractId: contract.id,
54-
workplaceName:
55-
detail?.workplaceName ??
56-
contract.workplaceName ??
57-
"알 수 없음",
58-
payrollDeductionType:
59-
detail?.payrollDeductionType ?? "PART_TIME_NONE",
60-
salary: salary ?? null,
48+
workplaceName: contract.workplaceName,
49+
payrollDeductionType: contract.payrollDeductionType,
50+
salary,
6151
};
6252
})
6353
);

src/hooks/worker/useWorkplaces.ts

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
/**
22
* 근로자의 활성 근무지 목록을 조회하는 커스텀 훅
3-
* - 계약 목록 → 상세 조회를 통해 근무지명, 시급 정보를 가공
3+
* - 계약 목록 응답에서 근무지명, 시급 정보를 직접 사용
44
* - WheelPicker용 items 변환까지 포함
55
*/
66
import { useState, useMemo, useCallback } from "react";
7-
import { getContracts, getContractDetail } from "../../api/worker";
7+
import { getContracts } from "../../api/worker";
88
import type { WheelPickerItem } from "../../components/common/WheelPicker";
99

1010
export interface WorkplaceOption {
@@ -25,18 +25,12 @@ const useWorkplaces = () => {
2525
const activeContracts =
2626
contractsRes.data?.filter((c) => c.isActive) ?? [];
2727

28-
const details = await Promise.all(
29-
activeContracts.map(async (contract) => {
30-
const detailRes = await getContractDetail(contract.id);
31-
return {
32-
contractId: contract.id,
33-
workplaceId: detailRes.data?.workplaceId ?? 0,
34-
workplaceName:
35-
detailRes.data?.workplaceName ?? "알 수 없음",
36-
hourlyWage: detailRes.data?.hourlyWage ?? 0,
37-
};
38-
})
39-
);
28+
const details = activeContracts.map((contract) => ({
29+
contractId: contract.id,
30+
workplaceId: contract.workplaceId,
31+
workplaceName: contract.workplaceName,
32+
hourlyWage: contract.hourlyWage,
33+
}));
4034

4135
setWorkplaces(details);
4236
} catch {

0 commit comments

Comments
 (0)