From f344ff50d7d7677947bd0605f1f7d7ddd13a2aed Mon Sep 17 00:00:00 2001 From: bicochan Date: Fri, 8 May 2026 13:28:50 +0900 Subject: [PATCH] =?UTF-8?q?[st]=20refactor:=20=EC=95=8C=EB=A6=BC=ED=86=A1?= =?UTF-8?q?=EB=B0=9C=EC=86=A1=20=EC=BD=94=EB=93=9C=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../management/NoticeTalkSending.tsx | 154 +----------------- .../notice-talk-sending-service.ts | 43 +++++ .../statistics/api/notice-talk/queries.ts | 33 ++++ apps/st/src/entities/statistics/index.ts | 13 ++ .../notice-talk-sending-columns.tsx | 74 +++++++++ .../notice-talk-sending-interface.ts | 30 ++++ 6 files changed, 202 insertions(+), 145 deletions(-) create mode 100644 apps/st/src/entities/statistics/api/notice-talk/notice-talk-sending-service.ts create mode 100644 apps/st/src/entities/statistics/api/notice-talk/queries.ts create mode 100644 apps/st/src/entities/statistics/model/notice-talk/notice-talk-sending-columns.tsx create mode 100644 apps/st/src/entities/statistics/model/notice-talk/notice-talk-sending-interface.ts diff --git a/apps/st/src/components/statistics/management/NoticeTalkSending.tsx b/apps/st/src/components/statistics/management/NoticeTalkSending.tsx index 6ead463fb..ff0cae557 100644 --- a/apps/st/src/components/statistics/management/NoticeTalkSending.tsx +++ b/apps/st/src/components/statistics/management/NoticeTalkSending.tsx @@ -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[]; -} - -interface BusinessSendResponse { - success: boolean; - sentCount: number; - message: string; -} - -interface SelectedRecipient extends SewerStUserItem { - variableOverrides: Record; -} - 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({}); - const { data: templatePageData } = useQuery({ - queryKey: [ - ENDPOINT.NTFTALK_SERVICE.TEMP, - "ntitlk-sndng", - DEFAULT_TEMPLATE_PARAMS, - ], - queryFn: async () => { - const response = await client.get>( - 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( - `${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[]>( - () => [ - { - id: "select", - header: ({ table }) => ( -
e.stopPropagation()} - onKeyDown={(e) => e.stopPropagation()} - role="presentation" - > - - table.toggleAllPageRowsSelected(!!value) - } - aria-label="전체 선택" - /> -
- ), - cell: ({ row }) => ( -
e.stopPropagation()} - onKeyDown={(e) => e.stopPropagation()} - role="presentation" - > - - row.toggleSelected(!!value) - } - aria-label="행 선택" - /> -
- ), - 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, diff --git a/apps/st/src/entities/statistics/api/notice-talk/notice-talk-sending-service.ts b/apps/st/src/entities/statistics/api/notice-talk/notice-talk-sending-service.ts new file mode 100644 index 000000000..476c8fecd --- /dev/null +++ b/apps/st/src/entities/statistics/api/notice-talk/notice-talk-sending-service.ts @@ -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> { + const response = await client.get>( + ENDPOINT.NTFTALK_SERVICE.TEMP, + { params }, + ); + return response.data; + } + + async getTemplateVariables( + templateCode: string, + ): Promise { + const response = await client.get( + `${ENDPOINT.NTFTALK_SERVICE.ATA_SEND}/template-variables/${templateCode}`, + ); + return response.data; + } +} + +export const noticeTalkSendingApi = new NoticeTalkSendingApiService(); diff --git a/apps/st/src/entities/statistics/api/notice-talk/queries.ts b/apps/st/src/entities/statistics/api/notice-talk/queries.ts new file mode 100644 index 000000000..20d28314d --- /dev/null +++ b/apps/st/src/entities/statistics/api/notice-talk/queries.ts @@ -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), + }); +} diff --git a/apps/st/src/entities/statistics/index.ts b/apps/st/src/entities/statistics/index.ts index 28a485e76..10666214b 100644 --- a/apps/st/src/entities/statistics/index.ts +++ b/apps/st/src/entities/statistics/index.ts @@ -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, diff --git a/apps/st/src/entities/statistics/model/notice-talk/notice-talk-sending-columns.tsx b/apps/st/src/entities/statistics/model/notice-talk/notice-talk-sending-columns.tsx new file mode 100644 index 000000000..03a6663f8 --- /dev/null +++ b/apps/st/src/entities/statistics/model/notice-talk/notice-talk-sending-columns.tsx @@ -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[] = [ + { + id: "select", + header: ({ table }) => ( +
e.stopPropagation()} + onKeyDown={(e) => e.stopPropagation()} + role="presentation" + > + + table.toggleAllPageRowsSelected(!!value) + } + aria-label="전체 선택" + /> +
+ ), + cell: ({ row }) => ( +
e.stopPropagation()} + onKeyDown={(e) => e.stopPropagation()} + role="presentation" + > + row.toggleSelected(!!value)} + aria-label="행 선택" + /> +
+ ), + 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: "전화번호", + }, +]; diff --git a/apps/st/src/entities/statistics/model/notice-talk/notice-talk-sending-interface.ts b/apps/st/src/entities/statistics/model/notice-talk/notice-talk-sending-interface.ts new file mode 100644 index 000000000..e7cf89b58 --- /dev/null +++ b/apps/st/src/entities/statistics/model/notice-talk/notice-talk-sending-interface.ts @@ -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[]; +} + +export interface BusinessSendResponse { + success: boolean; + sentCount: number; + message: string; +} + +export interface SelectedRecipient extends SewerStUserItem { + variableOverrides: Record; +}