[st] refactor: 알림톡발송 코드 분리

This commit is contained in:
2026-05-08 13:28:50 +09:00
parent 9898251563
commit f344ff50d7
6 changed files with 202 additions and 145 deletions
@@ -3,9 +3,7 @@
import { useMemo, useState } from "react";
import { useConfirm } from "@frontend-opensource/use-react-hooks";
import { useQuery } from "@tanstack/react-query";
import {
type ColumnDef,
getCoreRowModel,
type RowSelectionState,
useReactTable,
@@ -14,17 +12,21 @@ import {
import { client } from "@/shared/api/client";
import { ENDPOINT } from "@/shared/config";
import { useAlertStore } from "@/shared/lib";
import type { PageableList } from "@/shared/model";
import {
type AdstZoneResponseDto,
type BusinessSendRequest,
type BusinessSendResponse,
type SelectedRecipient,
type SewerStUserItem,
useNtftalkTemplateList,
useNtftalkTemplateVariables,
userListColumns,
useSewerStUserList,
useStAnlsSidoCombo,
useStAnlsSigunguCombo,
} from "@/entities/statistics";
import {
Button,
Checkbox,
DataTable,
Dialog,
DialogClose,
@@ -49,35 +51,6 @@ import {
TableRow,
} from "@common/components";
interface NtftalkTemplate {
templateCode: string;
templateName: string;
templateContent: string;
}
interface TemplateVariablesResponse {
templateCode: string;
variables: string[];
count: number;
}
interface BusinessSendRequest {
templateCode: string;
callback?: string;
fixedRecipientNum?: string;
recipients: Record<string, string>[];
}
interface BusinessSendResponse {
success: boolean;
sentCount: number;
message: string;
}
interface SelectedRecipient extends SewerStUserItem {
variableOverrides: Record<string, string>;
}
type CommonVariableKey =
| "userNm"
| "sido"
@@ -94,14 +67,6 @@ const GUBUN_OPTIONS = [
{ value: "IDFR", label: "승인자" },
{ value: "MCTPV", label: "검토자" },
] as const;
const DEFAULT_TEMPLATE_PARAMS = {
sort: "createdAt,desc",
senderKey: "",
inspectionStatus: "APR",
templateMessageType: "BA",
page: 0,
size: 10,
};
function getDefaultStatsYear(): string {
return String(new Date().getFullYear() - 1);
@@ -161,38 +126,11 @@ function NtitlkSndng() {
const [userListRowSelection, setUserListRowSelection] =
useState<RowSelectionState>({});
const { data: templatePageData } = useQuery({
queryKey: [
ENDPOINT.NTFTALK_SERVICE.TEMP,
"ntitlk-sndng",
DEFAULT_TEMPLATE_PARAMS,
],
queryFn: async () => {
const response = await client.get<PageableList<NtftalkTemplate>>(
ENDPOINT.NTFTALK_SERVICE.TEMP,
{ params: DEFAULT_TEMPLATE_PARAMS },
);
return response.data;
},
});
const { data: templatePageData } = useNtftalkTemplateList();
const templates = templatePageData?.content ?? [];
const { data: templateVariablesData } = useQuery({
queryKey: [
ENDPOINT.NTFTALK_SERVICE.ATA_SEND,
"template-variables",
selectedTemplateCode,
],
queryFn: async () => {
const response = await client.get<TemplateVariablesResponse>(
`${ENDPOINT.NTFTALK_SERVICE.ATA_SEND}/template-variables/${selectedTemplateCode}`,
);
return response.data;
},
enabled: Boolean(selectedTemplateCode),
});
const { data: templateVariablesData } =
useNtftalkTemplateVariables(selectedTemplateCode);
const variableNames = templateVariablesData?.variables ?? [];
const { data: sidoData } = useStAnlsSidoCombo();
@@ -203,80 +141,6 @@ function NtitlkSndng() {
const { data: userListResponse, isLoading: isUserListLoading } =
useSewerStUserList(appliedParams);
const userList = (userListResponse as unknown as SewerStUserItem[]) ?? [];
const userListColumns = useMemo<ColumnDef<SewerStUserItem>[]>(
() => [
{
id: "select",
header: ({ table }) => (
<div
className="flex justify-center"
onClick={(e) => e.stopPropagation()}
onKeyDown={(e) => e.stopPropagation()}
role="presentation"
>
<Checkbox
checked={
table.getIsAllPageRowsSelected() ||
(table.getIsSomePageRowsSelected() &&
"indeterminate")
}
onCheckedChange={(value) =>
table.toggleAllPageRowsSelected(!!value)
}
aria-label="전체 선택"
/>
</div>
),
cell: ({ row }) => (
<div
className="flex justify-center"
onClick={(e) => e.stopPropagation()}
onKeyDown={(e) => e.stopPropagation()}
role="presentation"
>
<Checkbox
checked={row.getIsSelected()}
onCheckedChange={(value) =>
row.toggleSelected(!!value)
}
aria-label="행 선택"
/>
</div>
),
enableSorting: false,
enableHiding: false,
},
{
accessorKey: "userNm",
header: "이름",
},
{
accessorKey: "sido",
header: "시도",
},
{
accessorKey: "gugun",
header: "시군구",
},
{
accessorKey: "gubunNm",
header: "구분",
},
{
accessorKey: "deptNm",
header: "소속",
},
{
accessorKey: "jbgdNm",
header: "직급",
},
{
accessorKey: "telNo",
header: "전화번호",
},
],
[],
);
const userListTable = useReactTable({
data: userList,
columns: userListColumns,
@@ -0,0 +1,43 @@
import { client } from "@/shared/api/client";
import { ENDPOINT } from "@/shared/config";
import type { PageableList } from "@/shared/model";
import type {
NtftalkTemplate,
TemplateVariablesResponse,
} from "../../model/notice-talk/notice-talk-sending-interface";
export const NTFTALK_TEMPLATE_LIST_PARAMS = {
sort: "createdAt,desc",
senderKey: "",
inspectionStatus: "APR",
templateMessageType: "BA",
page: 0,
size: 10,
};
/**
* 알림톡 발송 화면용 Ntftalk API
*/
export class NoticeTalkSendingApiService {
async getTemplatePage(
params: typeof NTFTALK_TEMPLATE_LIST_PARAMS = NTFTALK_TEMPLATE_LIST_PARAMS,
): Promise<PageableList<NtftalkTemplate>> {
const response = await client.get<PageableList<NtftalkTemplate>>(
ENDPOINT.NTFTALK_SERVICE.TEMP,
{ params },
);
return response.data;
}
async getTemplateVariables(
templateCode: string,
): Promise<TemplateVariablesResponse> {
const response = await client.get<TemplateVariablesResponse>(
`${ENDPOINT.NTFTALK_SERVICE.ATA_SEND}/template-variables/${templateCode}`,
);
return response.data;
}
}
export const noticeTalkSendingApi = new NoticeTalkSendingApiService();
@@ -0,0 +1,33 @@
import { useQuery } from "@tanstack/react-query";
import { ENDPOINT } from "@/shared/config";
import {
noticeTalkSendingApi,
NTFTALK_TEMPLATE_LIST_PARAMS,
} from "./notice-talk-sending-service";
export function useNtftalkTemplateList() {
return useQuery({
queryKey: [
ENDPOINT.NTFTALK_SERVICE.TEMP,
"ntitlk-sndng",
NTFTALK_TEMPLATE_LIST_PARAMS,
],
queryFn: () =>
noticeTalkSendingApi.getTemplatePage(NTFTALK_TEMPLATE_LIST_PARAMS),
});
}
export function useNtftalkTemplateVariables(templateCode: string) {
return useQuery({
queryKey: [
ENDPOINT.NTFTALK_SERVICE.ATA_SEND,
"template-variables",
templateCode,
],
queryFn: () =>
noticeTalkSendingApi.getTemplateVariables(templateCode),
enabled: Boolean(templateCode),
});
}
+13
View File
@@ -8,6 +8,11 @@ export {
export { dashboardApi } from "./api/dashboard/dashboard-service";
export { useScheduleInfo } from "./api/dashboard/schedule-info-queries";
export { scheduleInfoApi } from "./api/dashboard/schedule-info-service";
export { noticeTalkSendingApi } from "./api/notice-talk/notice-talk-sending-service";
export {
useNtftalkTemplateList,
useNtftalkTemplateVariables,
} from "./api/notice-talk/queries";
export {
useSewerStUserList,
useStAnlsSidoCombo,
@@ -64,6 +69,14 @@ export {
} from "./model/imr/imr-interface";
export { imrVerificationHistoryColumns } from "./model/imr/imr-verification-history-columns";
export { type StatsInputStatusList } from "./model/input/statistics-input-status-interface";
export { userListColumns } from "./model/notice-talk/notice-talk-sending-columns";
export {
type BusinessSendRequest,
type BusinessSendResponse,
type NtftalkTemplate,
type SelectedRecipient,
type TemplateVariablesResponse,
} from "./model/notice-talk/notice-talk-sending-interface";
export {
type SewerStUserItem,
type SewerStUserListResponse,
@@ -0,0 +1,74 @@
import type { ColumnDef } from "@tanstack/react-table";
import { Checkbox } from "@common/components";
import type { SewerStUserItem } from "../sewer-st-user-interface";
export const userListColumns: ColumnDef<SewerStUserItem>[] = [
{
id: "select",
header: ({ table }) => (
<div
className="flex justify-center"
onClick={(e) => e.stopPropagation()}
onKeyDown={(e) => e.stopPropagation()}
role="presentation"
>
<Checkbox
checked={
table.getIsAllPageRowsSelected() ||
(table.getIsSomePageRowsSelected() && "indeterminate")
}
onCheckedChange={(value) =>
table.toggleAllPageRowsSelected(!!value)
}
aria-label="전체 선택"
/>
</div>
),
cell: ({ row }) => (
<div
className="flex justify-center"
onClick={(e) => e.stopPropagation()}
onKeyDown={(e) => e.stopPropagation()}
role="presentation"
>
<Checkbox
checked={row.getIsSelected()}
onCheckedChange={(value) => row.toggleSelected(!!value)}
aria-label="행 선택"
/>
</div>
),
enableSorting: false,
enableHiding: false,
},
{
accessorKey: "userNm",
header: "이름",
},
{
accessorKey: "sido",
header: "시도",
},
{
accessorKey: "gugun",
header: "시군구",
},
{
accessorKey: "gubunNm",
header: "구분",
},
{
accessorKey: "deptNm",
header: "소속",
},
{
accessorKey: "jbgdNm",
header: "직급",
},
{
accessorKey: "telNo",
header: "전화번호",
},
];
@@ -0,0 +1,30 @@
import type { SewerStUserItem } from "../sewer-st-user-interface";
export interface NtftalkTemplate {
templateCode: string;
templateName: string;
templateContent: string;
}
export interface TemplateVariablesResponse {
templateCode: string;
variables: string[];
count: number;
}
export interface BusinessSendRequest {
templateCode: string;
callback?: string;
fixedRecipientNum?: string;
recipients: Record<string, string>[];
}
export interface BusinessSendResponse {
success: boolean;
sentCount: number;
message: string;
}
export interface SelectedRecipient extends SewerStUserItem {
variableOverrides: Record<string, string>;
}