## 작업 결과

**색상 통일 (화이트 테마):**
- `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` 하면 자동 배포됩니다.
This commit is contained in:
hyoseung930 2026-05-19 17:47:08 +09:00
parent 765868079d
commit cd6c296fb7
4 changed files with 76 additions and 32 deletions

View File

@ -0,0 +1,41 @@
name: Build and Deploy
on:
push:
branches:
- main
jobs:
deploy-front:
runs-on: self-hosted
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install front dependencies
run: cd front && npm ci
- name: Build front
run: cd front && npm run build
- name: Deploy front
run: rsync -a --delete front/dist/ /home/hyoseung/coupon/dist/
deploy-back:
runs-on: self-hosted
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install back dependencies
run: cd back && npm ci
- name: Build back
run: cd back && npm run build
- name: Deploy back
run: |
rsync -a --delete back/dist/ /home/hyoseung/coupon/back/dist/
cd /home/hyoseung/coupon/back
pm2 restart coupon-back || pm2 start ecosystem.config.js
pm2 save

View File

@ -32,21 +32,22 @@ const successCount = computed(() => store.results.filter((r) => r.status === 'su
<style scoped> <style scoped>
.redeem-results { display: flex; flex-direction: column; gap: 10px; } .redeem-results { display: flex; flex-direction: column; gap: 10px; }
.results-header { display: flex; justify-content: space-between; align-items: center; } .results-header { display: flex; justify-content: space-between; align-items: center; }
.label { color: #94a3b8; font-size: 0.85rem; } .label { color: #64748b; font-size: 0.85rem; }
.summary { color: #60a5fa; font-size: 0.85rem; font-weight: 600; } .summary { color: #3b82f6; font-size: 0.85rem; font-weight: 600; }
.result-list { display: flex; flex-direction: column; gap: 6px; } .result-list { display: flex; flex-direction: column; gap: 6px; }
.result-row { .result-row {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
padding: 8px 12px; padding: 8px 12px;
background: #0f172a; background: #f8fafc;
border: 1px solid #e2e8f0;
border-radius: 8px; border-radius: 8px;
gap: 8px; gap: 8px;
} }
.result-info { display: flex; flex-direction: column; gap: 2px; } .result-info { display: flex; flex-direction: column; gap: 2px; }
.result-name { color: #cbd5e1; font-size: 0.9rem; } .result-name { color: #1e293b; font-size: 0.9rem; }
.result-code { color: #475569; font-family: monospace; font-size: 0.78rem; } .result-code { color: #64748b; font-family: monospace; font-size: 0.78rem; }
.badge { .badge {
padding: 3px 10px; padding: 3px 10px;
border-radius: 20px; border-radius: 20px;
@ -54,8 +55,8 @@ const successCount = computed(() => store.results.filter((r) => r.status === 'su
font-weight: 600; font-weight: 600;
white-space: nowrap; white-space: nowrap;
} }
.badge.success { background: #166534; color: #4ade80; } .badge.success { background: #dcfce7; color: #16a34a; }
.badge.error { background: #7f1d1d; color: #f87171; } .badge.error { background: #fee2e2; color: #dc2626; }
.badge.pending { background: #1e3a5f; color: #93c5fd; } .badge.pending { background: #eff6ff; color: #3b82f6; }
.empty-result p { color: #475569; font-size: 0.9rem; margin: 0; text-align: center; } .empty-result p { color: #94a3b8; font-size: 0.9rem; margin: 0; text-align: center; }
</style> </style>

View File

@ -50,20 +50,20 @@ async function add() {
<style scoped> <style scoped>
.coupon-manager { display: flex; flex-direction: column; gap: 14px; } .coupon-manager { display: flex; flex-direction: column; gap: 14px; }
.manager-header { display: flex; align-items: center; justify-content: space-between; } .manager-header { display: flex; align-items: center; justify-content: space-between; }
.manager-header h3 { margin: 0; color: #f1f5f9; font-size: 1rem; } .manager-header h3 { margin: 0; color: #1e293b; font-size: 1rem; }
.active-count { background: #1e3a5f; color: #60a5fa; padding: 3px 10px; border-radius: 20px; font-size: 0.8rem; font-weight: 600; } .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; } .add-form { display: flex; gap: 8px; flex-wrap: wrap; }
.input { .input {
padding: 8px 12px; padding: 8px 12px;
background: #0f172a; background: #f8fafc;
border: 1px solid #334155; border: 1px solid #e2e8f0;
border-radius: 8px; border-radius: 8px;
color: #f1f5f9; color: #1e293b;
font-size: 0.9rem; font-size: 0.9rem;
flex: 1; flex: 1;
min-width: 120px; min-width: 120px;
} }
.input:focus { outline: none; border-color: #60a5fa; } .input:focus { outline: none; border-color: #3b82f6; box-shadow: 0 0 0 3px rgba(59,130,246,0.1); }
.code-input { font-family: monospace; } .code-input { font-family: monospace; }
.btn-add { .btn-add {
padding: 8px 16px; padding: 8px 16px;
@ -84,14 +84,15 @@ async function add() {
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
padding: 10px 14px; padding: 10px 14px;
background: #0f172a; background: #f8fafc;
border: 1px solid #e2e8f0;
border-radius: 8px; border-radius: 8px;
border-left: 3px solid #22c55e; border-left: 3px solid #22c55e;
gap: 8px; gap: 8px;
} }
.coupon-item.expired { border-left-color: #7c3aed; opacity: 0.5; } .coupon-item.expired { border-left-color: #a855f7; opacity: 0.6; }
.coupon-info { display: flex; flex-direction: column; gap: 2px; flex: 1; } .coupon-info { display: flex; flex-direction: column; gap: 2px; flex: 1; }
.coupon-code { color: #60a5fa; font-family: monospace; font-size: 0.9rem; } .coupon-code { color: #3b82f6; font-family: monospace; font-size: 0.9rem; }
.coupon-actions { display: flex; gap: 6px; align-items: center; } .coupon-actions { display: flex; gap: 6px; align-items: center; }
.btn-toggle { .btn-toggle {
padding: 3px 10px; padding: 3px 10px;
@ -101,10 +102,10 @@ async function add() {
font-size: 0.78rem; font-size: 0.78rem;
font-weight: 600; font-weight: 600;
} }
.btn-toggle.on { background: #166534; color: #4ade80; } .btn-toggle.on { background: #dcfce7; color: #16a34a; }
.btn-toggle.off { background: #374151; color: #9ca3af; } .btn-toggle.off { background: #f1f5f9; color: #64748b; }
.badge { padding: 3px 10px; border-radius: 20px; font-size: 0.78rem; font-weight: 600; } .badge { padding: 3px 10px; border-radius: 20px; font-size: 0.78rem; font-weight: 600; }
.badge-active { background: #166534; color: #4ade80; } .badge-active { background: #dcfce7; color: #16a34a; }
.badge-expired { background: #3b0764; color: #c084fc; } .badge-expired { background: #f3e8ff; color: #9333ea; }
.empty { color: #475569; font-size: 0.9rem; margin: 0; text-align: center; } .empty { color: #94a3b8; font-size: 0.9rem; margin: 0; text-align: center; }
</style> </style>

View File

@ -50,7 +50,7 @@ function formatDate(dt: string) {
} }
.history-header h3 { .history-header h3 {
margin: 0; margin: 0;
color: #f1f5f9; color: #1e293b;
font-size: 1rem; font-size: 1rem;
} }
.count { .count {
@ -66,16 +66,17 @@ function formatDate(dt: string) {
padding-right: 4px; padding-right: 4px;
} }
.list::-webkit-scrollbar { width: 4px; } .list::-webkit-scrollbar { width: 4px; }
.list::-webkit-scrollbar-track { background: #0f172a; } .list::-webkit-scrollbar-track { background: #f1f5f9; }
.list::-webkit-scrollbar-thumb { background: #334155; border-radius: 4px; } .list::-webkit-scrollbar-thumb { background: #cbd5e1; border-radius: 4px; }
.item { .item {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
padding: 8px 12px; padding: 8px 12px;
background: #0f172a; background: #f8fafc;
border: 1px solid #e2e8f0;
border-radius: 8px; border-radius: 8px;
border-left: 3px solid #334155; border-left: 3px solid #e2e8f0;
} }
.item.success { border-left-color: #22c55e; } .item.success { border-left-color: #22c55e; }
.item.error { border-left-color: #ef4444; } .item.error { border-left-color: #ef4444; }
@ -86,11 +87,11 @@ function formatDate(dt: string) {
} }
.code { .code {
font-family: monospace; font-family: monospace;
color: #cbd5e1; color: #334155;
font-size: 0.9rem; font-size: 0.9rem;
} }
.time { .time {
color: #475569; color: #94a3b8;
font-size: 0.75rem; font-size: 0.75rem;
} }
.badge { .badge {
@ -100,6 +101,6 @@ function formatDate(dt: string) {
font-weight: 600; font-weight: 600;
white-space: nowrap; white-space: nowrap;
} }
.badge.success { background: #166534; color: #4ade80; } .badge.success { background: #dcfce7; color: #16a34a; }
.badge.error { background: #7f1d1d; color: #f87171; } .badge.error { background: #fee2e2; color: #dc2626; }
</style> </style>