From 98011f6fa79df28e803df042ebc269fa9a1fe3ce Mon Sep 17 00:00:00 2001 From: iubns Date: Mon, 9 Feb 2026 23:12:06 +0900 Subject: [PATCH 1/3] =?UTF-8?q?fix:=20=EB=94=94=EB=B2=84=EA=B9=85=EC=9A=A9?= =?UTF-8?q?=20=EC=BD=94=EB=93=9C=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/app/leader/attendance/page.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/app/leader/attendance/page.tsx b/client/src/app/leader/attendance/page.tsx index b3a3a471..c5ce8688 100644 --- a/client/src/app/leader/attendance/page.tsx +++ b/client/src/app/leader/attendance/page.tsx @@ -70,7 +70,7 @@ export default function SoonAttendance() { - 출석 관리 {selectedScheduleId} + 출석 관리 순원들의 출석을 관리해보세요 From a18f607030c522898118f81d8024491a0c171d85 Mon Sep 17 00:00:00 2001 From: iubns Date: Sat, 21 Mar 2026 16:05:00 +0900 Subject: [PATCH 2/3] =?UTF-8?q?update:=20=EC=B6=9C=EC=84=9D=ED=98=84?= =?UTF-8?q?=ED=99=A9=20=EB=AA=A8=EB=B0=94=EC=9D=BC=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EB=B3=B4=EA=B8=B0=20=EC=A2=8B=EB=8F=84=EB=A1=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/soon/attendance/AttendanceTable.tsx | 48 +++++++++---------- 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/client/src/app/admin/soon/attendance/AttendanceTable.tsx b/client/src/app/admin/soon/attendance/AttendanceTable.tsx index 59c29b60..665aa386 100644 --- a/client/src/app/admin/soon/attendance/AttendanceTable.tsx +++ b/client/src/app/admin/soon/attendance/AttendanceTable.tsx @@ -13,7 +13,7 @@ interface AttendanceTableProps { leaders: User[] getAttendUserCount: ( attendDataList: AttendData[], - worshipScheduleId: number + worshipScheduleId: number, ) => { count: number; attend: number } } @@ -24,6 +24,7 @@ export default function AttendanceTable({ leaders, getAttendUserCount, }: AttendanceTableProps) { + const isMobile = window.innerWidth < 600 return ( {/* 출석 테이블 제목 */} @@ -52,10 +53,10 @@ export default function AttendanceTable({ > { const { attend, count } = getAttendUserCount( attendDataList, - worshipSchedule.id + worshipSchedule.id, ) const percentage = count > 0 ? Math.round((attend / count) * 100) : 0 @@ -98,10 +99,10 @@ export default function AttendanceTable({ - {isLeader && ( - - )} {isDeputyLeader && ( )} @@ -183,15 +181,15 @@ export default function AttendanceTable({ const attendData = attendDataList.find( (data) => data.user.id === user.id && - data.worshipSchedule.id === worshipSchedule.id + data.worshipSchedule.id === worshipSchedule.id, ) return ( Date: Sat, 21 Mar 2026 16:40:31 +0900 Subject: [PATCH 3/3] =?UTF-8?q?update:=20=EC=83=88=EC=8B=A0=EC=9E=90=20?= =?UTF-8?q?=EB=82=B4=EC=9A=A9=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/app/admin/components/Header/index.tsx | 3 +- .../newcomer/management/NewcomerForm.tsx | 109 ++++++++++++++++++ .../app/leader/newcomer/management/page.tsx | 30 +++++ server/src/entity/newcomer/newcomer.ts | 27 ++++- server/src/entity/types.ts | 7 ++ .../1774077398756-AddNewcomerField.ts | 43 +++++++ server/src/routes/newcomer/newcomerRouter.ts | 36 ++++++ 7 files changed, 253 insertions(+), 2 deletions(-) create mode 100644 server/src/migration/1774077398756-AddNewcomerField.ts diff --git a/client/src/app/admin/components/Header/index.tsx b/client/src/app/admin/components/Header/index.tsx index b00a8b91..a7d46f10 100644 --- a/client/src/app/admin/components/Header/index.tsx +++ b/client/src/app/admin/components/Header/index.tsx @@ -63,6 +63,7 @@ export default function AdminHeader() { path: "/admin/soon/attendance", type: "menu", }, + /* { title: "AI로 데이터 분석", icon: , @@ -71,7 +72,7 @@ export default function AdminHeader() { }, { type: "divider", - }, + },*/ /* Todo: 지울지, 유지할지 결정 필요 { title: "워십 콘테스트", diff --git a/client/src/app/leader/newcomer/management/NewcomerForm.tsx b/client/src/app/leader/newcomer/management/NewcomerForm.tsx index e70b8bfc..faa78d8e 100644 --- a/client/src/app/leader/newcomer/management/NewcomerForm.tsx +++ b/client/src/app/leader/newcomer/management/NewcomerForm.tsx @@ -12,6 +12,13 @@ interface Newcomer { phone: string | null gender: "man" | "woman" | "" | null status?: "NORMAL" | "PROMOTED" | "PENDING" | "DELETED" + address?: string | null + occupation?: string | null + visitPath?: string | null + registrationMotivation?: string | null + faithLevel?: "초신자" | "세례" | "입교" | "학습" | null + previousChurch?: string | null + carNumber?: string | null newcomerManager?: { id: string user: { id: string; name: string } @@ -206,6 +213,108 @@ export default function NewcomerForm({ + + + 주소 : + + onDataChange("address", e.target.value)} + variant="outlined" + size="small" + sx={{ flex: 1 }} + /> + + + + + 신분 : + + onDataChange("occupation", e.target.value)} + variant="outlined" + size="small" + placeholder="학생-학교/전공, 직장인-계열/분야 등" + sx={{ flex: 1 }} + /> + + + + + 방문경로 : + + onDataChange("visitPath", e.target.value)} + variant="outlined" + size="small" + sx={{ flex: 1 }} + /> + + + + + 등록계기 : + + + onDataChange("registrationMotivation", e.target.value) + } + variant="outlined" + size="small" + sx={{ flex: 1 }} + /> + + + + + 신앙생활 : + + onDataChange("faithLevel", e.target.value)} + variant="outlined" + size="small" + sx={{ flex: 1 }} + > + 선택 + 초신자 + 학습 + 세례 + 입교 + + + + + + 전 출석교회 : + + onDataChange("previousChurch", e.target.value)} + variant="outlined" + size="small" + placeholder="교회명 / 담임목사님 성함" + sx={{ flex: 1 }} + /> + + + + + 차량번호 : + + onDataChange("carNumber", e.target.value)} + variant="outlined" + size="small" + sx={{ flex: 1 }} + /> + + 담당자 : diff --git a/client/src/app/leader/newcomer/management/page.tsx b/client/src/app/leader/newcomer/management/page.tsx index 7f61ebaf..4fd76d04 100644 --- a/client/src/app/leader/newcomer/management/page.tsx +++ b/client/src/app/leader/newcomer/management/page.tsx @@ -34,6 +34,13 @@ interface Newcomer { deletedAt?: string | null pendingDate?: string | null promotionDate?: string | null + address: string | null + occupation: string | null + visitPath: string | null + registrationMotivation: string | null + faithLevel: "초신자" | "세례" | "입교" | "학습" | null + previousChurch: string | null + carNumber: string | null } interface Manager { @@ -55,6 +62,13 @@ const emptyNewcomer: Newcomer = { deletedAt: null, pendingDate: null, promotionDate: null, + address: null, + occupation: null, + visitPath: null, + registrationMotivation: null, + faithLevel: null, + previousChurch: null, + carNumber: null, } export default function NewcomerManagement() { @@ -120,6 +134,15 @@ export default function NewcomerManagement() { guiderId: selectedNewcomer.guider?.id || null, assignmentId: selectedNewcomer.assignment?.id || null, status: selectedNewcomer.status, + pendingDate: selectedNewcomer.pendingDate, + promotionDate: selectedNewcomer.promotionDate, + address: selectedNewcomer.address, + occupation: selectedNewcomer.occupation, + visitPath: selectedNewcomer.visitPath, + registrationMotivation: selectedNewcomer.registrationMotivation, + faithLevel: selectedNewcomer.faithLevel, + previousChurch: selectedNewcomer.previousChurch, + carNumber: selectedNewcomer.carNumber, }) notification.success("새신자 정보가 수정되었습니다.") } else { @@ -129,6 +152,13 @@ export default function NewcomerManagement() { gender: selectedNewcomer.gender, phone: selectedNewcomer.phone, newcomerManagerId: selectedNewcomer.newcomerManager?.id || null, + address: selectedNewcomer.address, + occupation: selectedNewcomer.occupation, + visitPath: selectedNewcomer.visitPath, + registrationMotivation: selectedNewcomer.registrationMotivation, + faithLevel: selectedNewcomer.faithLevel, + previousChurch: selectedNewcomer.previousChurch, + carNumber: selectedNewcomer.carNumber, }) notification.success("새신자가 추가되었습니다.") } diff --git a/server/src/entity/newcomer/newcomer.ts b/server/src/entity/newcomer/newcomer.ts index 64272941..a079dc63 100644 --- a/server/src/entity/newcomer/newcomer.ts +++ b/server/src/entity/newcomer/newcomer.ts @@ -11,7 +11,7 @@ import { } from "typeorm" import { User } from "../user" import { Community } from "../community" -import { NewcomerStatus } from "../types" +import { NewcomerStatus, FaithLevel } from "../types" import { NewcomerEducation } from "./newcomerEducation" import { NewcomerManager } from "./newcomerManager" @@ -32,6 +32,31 @@ export class Newcomer { @Column({ nullable: true }) phone: string // 연락처 + @Column({ nullable: true }) + address: string // 주소 + + @Column({ nullable: true }) + occupation: string // 신분(학생-학교/전공, 대학원생-학교/전공, 취업준비-준비계열/분야, 직장인-계열/분야) + + @Column({ nullable: true }) + visitPath: string // 방문경로 + + @Column({ nullable: true }) + registrationMotivation: string // 등록계기 + + @Column({ + type: "enum", + enum: FaithLevel, + nullable: true, + }) + faithLevel: FaithLevel // 신앙생활(초신자, 세례, 입교, 학습) + + @Column({ nullable: true }) + previousChurch: string // 전 출석교회/담임목사님 성함 + + @Column({ nullable: true }) + carNumber: string // 차량번호 + @ManyToOne(() => User) @JoinColumn({ name: "guiderId" }) guider: User // 인도자 diff --git a/server/src/entity/types.ts b/server/src/entity/types.ts index 1f01716c..91a3250c 100644 --- a/server/src/entity/types.ts +++ b/server/src/entity/types.ts @@ -73,3 +73,10 @@ export enum NewcomerStatus { DELETED = "DELETED", PENDING = "PENDING", } + +export enum FaithLevel { + BEGINNER = "초신자", + BAPTIZED = "세례", + CONFIRMED = "입교", + LEARNING = "학습", +} diff --git a/server/src/migration/1774077398756-AddNewcomerField.ts b/server/src/migration/1774077398756-AddNewcomerField.ts new file mode 100644 index 00000000..96633389 --- /dev/null +++ b/server/src/migration/1774077398756-AddNewcomerField.ts @@ -0,0 +1,43 @@ +import { MigrationInterface, QueryRunner } from "typeorm" + +export class AddNewcomerField1774077398756 implements MigrationInterface { + name = "AddNewcomerField1774077398756" + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + "ALTER TABLE `newcomer` ADD `address` varchar(255) NULL", + ) + await queryRunner.query( + "ALTER TABLE `newcomer` ADD `occupation` varchar(255) NULL", + ) + await queryRunner.query( + "ALTER TABLE `newcomer` ADD `visitPath` varchar(255) NULL", + ) + await queryRunner.query( + "ALTER TABLE `newcomer` ADD `registrationMotivation` varchar(255) NULL", + ) + await queryRunner.query( + "ALTER TABLE `newcomer` ADD `faithLevel` enum ('초신자', '세례', '입교', '학습') NULL", + ) + await queryRunner.query( + "ALTER TABLE `newcomer` ADD `previousChurch` varchar(255) NULL", + ) + await queryRunner.query( + "ALTER TABLE `newcomer` ADD `carNumber` varchar(255) NULL", + ) + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query("ALTER TABLE `newcomer` DROP COLUMN `carNumber`") + await queryRunner.query( + "ALTER TABLE `newcomer` DROP COLUMN `previousChurch`", + ) + await queryRunner.query("ALTER TABLE `newcomer` DROP COLUMN `faithLevel`") + await queryRunner.query( + "ALTER TABLE `newcomer` DROP COLUMN `registrationMotivation`", + ) + await queryRunner.query("ALTER TABLE `newcomer` DROP COLUMN `visitPath`") + await queryRunner.query("ALTER TABLE `newcomer` DROP COLUMN `occupation`") + await queryRunner.query("ALTER TABLE `newcomer` DROP COLUMN `address`") + } +} diff --git a/server/src/routes/newcomer/newcomerRouter.ts b/server/src/routes/newcomer/newcomerRouter.ts index 8365cb96..323a7e60 100644 --- a/server/src/routes/newcomer/newcomerRouter.ts +++ b/server/src/routes/newcomer/newcomerRouter.ts @@ -43,6 +43,13 @@ router.post("/", async (req, res) => { guiderId, assignmentId, newcomerManagerId, + address, + occupation, + visitPath, + registrationMotivation, + faithLevel, + previousChurch, + carNumber, } = req.body if (!name) { @@ -82,6 +89,13 @@ router.post("/", async (req, res) => { yearOfBirth: yearOfBirth ? parseInt(yearOfBirth, 10) : null, gender: gender || null, phone: phone?.replace(/[^\d]/g, "") || null, + address, + occupation, + visitPath, + registrationMotivation, + faithLevel: faithLevel || null, + previousChurch, + carNumber, guider, assignment, newcomerManager, @@ -115,6 +129,13 @@ router.put("/:id", async (req, res) => { status, pendingDate, promotionDate, + address, + occupation, + visitPath, + registrationMotivation, + faithLevel, + previousChurch, + carNumber, } = req.body try { @@ -130,6 +151,14 @@ router.put("/:id", async (req, res) => { if (gender !== undefined) newcomer.gender = gender || null if (phone !== undefined) newcomer.phone = phone?.replace(/[^\d]/g, "") || null + if (address !== undefined) newcomer.address = address + if (occupation !== undefined) newcomer.occupation = occupation + if (visitPath !== undefined) newcomer.visitPath = visitPath + if (registrationMotivation !== undefined) + newcomer.registrationMotivation = registrationMotivation + if (faithLevel !== undefined) newcomer.faithLevel = faithLevel || null + if (previousChurch !== undefined) newcomer.previousChurch = previousChurch + if (carNumber !== undefined) newcomer.carNumber = carNumber if (status) newcomer.status = status if (pendingDate !== undefined) newcomer.pendingDate = pendingDate if (promotionDate !== undefined) newcomer.promotionDate = promotionDate @@ -343,6 +372,13 @@ router.get("/education", async (req, res) => { yearOfBirth: newcomer.yearOfBirth, gender: newcomer.gender, phone: newcomer.phone, + address: newcomer.address, + occupation: newcomer.occupation, + visitPath: newcomer.visitPath, + registrationMotivation: newcomer.registrationMotivation, + faithLevel: newcomer.faithLevel, + previousChurch: newcomer.previousChurch, + carNumber: newcomer.carNumber, status: newcomer.status, guider: newcomer.guider ? { id: newcomer.guider.id, name: newcomer.guider.name }