coupon/front/src/components/CouponManager.vue
hyoseung930 cd6c296fb7 New task
## 작업 결과

**색상 통일 (화이트 테마):**
- `CouponInput.vue` — 결과 행 배경 `#0f172a` → `#f8fafc`, 텍스트/배지 라이트로
- `CouponManager.vue` — 입력창/쿠폰 리스트 배경/텍스트 전체 라이트로
- `HistoryList.vue` — 이력 아이템 배경/텍스트 라이트로, 스크롤바도 라이트

**CI/CD 설정:**
- Gitea `git.wageulwageul.com/hyoseung/coupon` 레포 생성
- `.gitea/workflows/deploy.yml` — front/back 각각 빌드 후 rsync 배포
- 백엔드 `ubuntu` PM2 → `hyoseung` PM2로 마이그레이션 (CI/CD 권한 문제 해결)
- 첫 푸시에 CI/CD 자동 실행 완료 

이제부터는 `autoCoupon/` 폴더에서 코드 수정 후 `git push origin main` 하면 자동 배포됩니다.
2026-05-19 17:47:08 +09:00

112 lines
3.6 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="coupon-manager">
<div class="manager-header">
<h3>🎟 쿠폰 관리</h3>
<span class="active-count">{{ activeCoupons }}</span>
</div>
<div class="add-form">
<input v-model="newCode" type="text" placeholder="쿠폰 코드" class="input code-input" />
<button class="btn btn-add" @click="add" :disabled="!newCode">추가</button>
</div>
<div class="coupon-list" v-if="store.coupons.length > 0">
<div
v-for="c in store.coupons"
:key="c.id"
class="coupon-item"
:class="{ expired: c.is_expired }"
>
<div class="coupon-info">
<span class="coupon-code">{{ c.code }}</span>
</div>
<div class="coupon-actions">
<span v-if="c.is_expired" class="badge badge-expired">만료</span>
<span v-else class="badge badge-active">활성</span>
</div>
</div>
</div>
<p class="empty" v-else>등록된 쿠폰이 없습니다.</p>
</div>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue';
import { useWosStore } from '../stores/wos.store';
const store = useWosStore();
const newCode = ref('');
const activeCoupons = computed(() => store.coupons.filter((c) => !c.is_expired).length);
async function add() {
if (!newCode.value.trim()) return;
const code = newCode.value.trim();
await store.addCoupon(code, code);
newCode.value = '';
}
</script>
<style scoped>
.coupon-manager { display: flex; flex-direction: column; gap: 14px; }
.manager-header { display: flex; align-items: center; justify-content: space-between; }
.manager-header h3 { margin: 0; color: #1e293b; font-size: 1rem; }
.active-count { background: #eff6ff; color: #3b82f6; padding: 3px 10px; border-radius: 20px; font-size: 0.8rem; font-weight: 600; }
.add-form { display: flex; gap: 8px; flex-wrap: wrap; }
.input {
padding: 8px 12px;
background: #f8fafc;
border: 1px solid #e2e8f0;
border-radius: 8px;
color: #1e293b;
font-size: 0.9rem;
flex: 1;
min-width: 120px;
}
.input:focus { outline: none; border-color: #3b82f6; box-shadow: 0 0 0 3px rgba(59,130,246,0.1); }
.code-input { font-family: monospace; }
.btn-add {
padding: 8px 16px;
background: #22c55e;
color: #fff;
border: none;
border-radius: 8px;
cursor: pointer;
font-weight: 600;
font-size: 0.9rem;
white-space: nowrap;
}
.btn-add:disabled { opacity: 0.4; cursor: not-allowed; }
.btn-add:hover:not(:disabled) { background: #16a34a; }
.coupon-list { display: flex; flex-direction: column; gap: 6px; max-height: 260px; overflow-y: auto; }
.coupon-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px 14px;
background: #f8fafc;
border: 1px solid #e2e8f0;
border-radius: 8px;
border-left: 3px solid #22c55e;
gap: 8px;
}
.coupon-item.expired { border-left-color: #a855f7; opacity: 0.6; }
.coupon-info { display: flex; flex-direction: column; gap: 2px; flex: 1; }
.coupon-code { color: #3b82f6; font-family: monospace; font-size: 0.9rem; }
.coupon-actions { display: flex; gap: 6px; align-items: center; }
.btn-toggle {
padding: 3px 10px;
border: none;
border-radius: 20px;
cursor: pointer;
font-size: 0.78rem;
font-weight: 600;
}
.btn-toggle.on { background: #dcfce7; color: #16a34a; }
.btn-toggle.off { background: #f1f5f9; color: #64748b; }
.badge { padding: 3px 10px; border-radius: 20px; font-size: 0.78rem; font-weight: 600; }
.badge-active { background: #dcfce7; color: #16a34a; }
.badge-expired { background: #f3e8ff; color: #9333ea; }
.empty { color: #94a3b8; font-size: 0.9rem; margin: 0; text-align: center; }
</style>