From c5ca4034428a2bfadb97204e7436d3ed62a1ee6d Mon Sep 17 00:00:00 2001 From: hyoseung930 <35983843+hyoseung930@users.noreply.github.com> Date: Fri, 26 Jun 2026 15:05:36 +0900 Subject: [PATCH] =?UTF-8?q?autoCoupon:=20alliance=20=EC=97=B0=EB=A7=B9?= =?UTF-8?q?=EC=9B=90=20=EB=AA=A9=EB=A1=9D=20=EC=97=B0=EB=8F=99=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - /api/alliances: alliance 백엔드 프록시 - /api/alliance-members: R5 PIN 인증 후 연맹원 목록 반환 (쿠폰 등록 여부 포함) - AlliancePanel.vue: 연맹 선택 + R5 PIN 인증 + 역할별 필터 + 쿠폰 등록 현황 - HomeView.vue에 AlliancePanel 추가 --- back/src/wos/wos.controller.ts | 26 +- front/src/components/AlliancePanel.vue | 326 +++++++++++++++++++++++++ front/src/views/HomeView.vue | 3 + 3 files changed, 354 insertions(+), 1 deletion(-) create mode 100644 front/src/components/AlliancePanel.vue diff --git a/back/src/wos/wos.controller.ts b/back/src/wos/wos.controller.ts index 71b9dcb..ccb7fb2 100644 --- a/back/src/wos/wos.controller.ts +++ b/back/src/wos/wos.controller.ts @@ -1,5 +1,8 @@ -import { Controller, Post, Get, Delete, Patch, Body, Param, Query, HttpCode } from '@nestjs/common'; +import { Controller, Post, Get, Delete, Patch, Body, Param, Query, HttpCode, BadRequestException, ForbiddenException } from '@nestjs/common'; import { WosService } from './wos.service'; +import axios from 'axios'; + +const ALLIANCE_API = 'http://localhost:3005/api'; @Controller('api') export class WosController { @@ -59,4 +62,25 @@ export class WosController { async deleteCoupon(@Param('id') id: string) { return this.wosService.deleteCoupon(Number(id)); } + + @Get('alliances') + async getAlliances() { + const { data } = await axios.get(`${ALLIANCE_API}/alliances`); + return data; + } + + @Post('alliance-members') + @HttpCode(200) + async getAllianceMembers(@Body() body: { alliance_id: number; pin: string }) { + if (!body.alliance_id || !body.pin) throw new BadRequestException('alliance_id와 pin이 필요합니다'); + try { + await axios.get(`${ALLIANCE_API}/alliances/${body.alliance_id}/pending`, { params: { pin: body.pin } }); + } catch { + throw new ForbiddenException('PIN이 틀렸습니다'); + } + const { data: members } = await axios.get(`${ALLIANCE_API}/members`, { params: { alliance_id: body.alliance_id } }); + const wosUsers = await this.wosService.listUsers(); + const nicknameSet = new Set(wosUsers.map((u: any) => u.nickname?.toLowerCase())); + return members.map((m: any) => ({ ...m, in_coupon_system: nicknameSet.has(m.nickname?.toLowerCase()) })); + } } diff --git a/front/src/components/AlliancePanel.vue b/front/src/components/AlliancePanel.vue new file mode 100644 index 0000000..0de0ff8 --- /dev/null +++ b/front/src/components/AlliancePanel.vue @@ -0,0 +1,326 @@ + + + + + diff --git a/front/src/views/HomeView.vue b/front/src/views/HomeView.vue index 37dd3f5..fc2c74e 100644 --- a/front/src/views/HomeView.vue +++ b/front/src/views/HomeView.vue @@ -61,6 +61,8 @@
+ + @@ -72,6 +74,7 @@ import { useWosStore } from '../stores/wos.store'; import UserCard from '../components/UserCard.vue'; import CouponInput from '../components/CouponInput.vue'; import CouponManager from '../components/CouponManager.vue'; +import AlliancePanel from '../components/AlliancePanel.vue'; const store = useWosStore(); const fidInput = ref('');