쿠폰 자동 입력 사이트 작성
완료. 비활성 토글이 제거됐습니다. 이제 쿠폰은 **활성** (기본) 또는 **만료** 두 가지 상태만 있습니다.
This commit is contained in:
parent
82d245e012
commit
68c71cb0c4
@ -2,7 +2,7 @@
|
|||||||
<div class="coupon-manager">
|
<div class="coupon-manager">
|
||||||
<div class="manager-header">
|
<div class="manager-header">
|
||||||
<h3>🎟️ 쿠폰 관리</h3>
|
<h3>🎟️ 쿠폰 관리</h3>
|
||||||
<span class="active-count">활성 {{ activeCoupons }}개</span>
|
<span class="active-count">{{ activeCoupons }}개</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="add-form">
|
<div class="add-form">
|
||||||
@ -15,21 +15,13 @@
|
|||||||
v-for="c in store.coupons"
|
v-for="c in store.coupons"
|
||||||
:key="c.id"
|
:key="c.id"
|
||||||
class="coupon-item"
|
class="coupon-item"
|
||||||
:class="{ inactive: !c.is_active, expired: c.is_expired }"
|
:class="{ expired: c.is_expired }"
|
||||||
>
|
>
|
||||||
<div class="coupon-info">
|
<div class="coupon-info">
|
||||||
<span class="coupon-code">{{ c.code }}</span>
|
<span class="coupon-code">{{ c.code }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="coupon-actions">
|
<div class="coupon-actions">
|
||||||
<span v-if="c.is_expired" class="badge badge-expired">만료</span>
|
<span v-if="c.is_expired" class="badge badge-expired">만료</span>
|
||||||
<button
|
|
||||||
v-else
|
|
||||||
class="btn-toggle"
|
|
||||||
:class="c.is_active ? 'on' : 'off'"
|
|
||||||
@click="store.toggleCoupon(c.id, !c.is_active)"
|
|
||||||
>
|
|
||||||
{{ c.is_active ? '활성' : '비활성' }}
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -44,7 +36,7 @@ import { useWosStore } from '../stores/wos.store';
|
|||||||
const store = useWosStore();
|
const store = useWosStore();
|
||||||
const newCode = ref('');
|
const newCode = ref('');
|
||||||
|
|
||||||
const activeCoupons = computed(() => store.coupons.filter((c) => c.is_active && !c.is_expired).length);
|
const activeCoupons = computed(() => store.coupons.filter((c) => !c.is_expired).length);
|
||||||
|
|
||||||
async function add() {
|
async function add() {
|
||||||
if (!newCode.value.trim()) return;
|
if (!newCode.value.trim()) return;
|
||||||
@ -96,7 +88,6 @@ async function add() {
|
|||||||
border-left: 3px solid #22c55e;
|
border-left: 3px solid #22c55e;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
}
|
}
|
||||||
.coupon-item.inactive { border-left-color: #334155; opacity: 0.6; }
|
|
||||||
.coupon-item.expired { border-left-color: #7c3aed; opacity: 0.5; }
|
.coupon-item.expired { border-left-color: #7c3aed; opacity: 0.5; }
|
||||||
.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: #60a5fa; font-family: monospace; font-size: 0.9rem; }
|
||||||
|
|||||||
@ -29,13 +29,6 @@
|
|||||||
<span class="coupon-code">{{ c.code }}</span>
|
<span class="coupon-code">{{ c.code }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="coupon-actions">
|
<div class="coupon-actions">
|
||||||
<label class="toggle">
|
|
||||||
<input type="checkbox" :checked="c.is_active" @change="store.toggleCoupon(c.id, !c.is_active)" />
|
|
||||||
<span class="slider"></span>
|
|
||||||
</label>
|
|
||||||
<span class="status-label" :class="c.is_active ? 'active' : 'inactive'">
|
|
||||||
{{ c.is_active ? '활성' : '비활성' }}
|
|
||||||
</span>
|
|
||||||
<button class="btn btn-danger" @click="confirmDelete(c.id, c.name || c.code)">삭제</button>
|
<button class="btn btn-danger" @click="confirmDelete(c.id, c.name || c.code)">삭제</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -52,7 +45,7 @@ const newCode = ref('');
|
|||||||
const newName = ref('');
|
const newName = ref('');
|
||||||
const errorMsg = ref('');
|
const errorMsg = ref('');
|
||||||
|
|
||||||
const activeCoupons = computed(() => store.coupons.filter((c) => c.is_active).length);
|
const activeCoupons = computed(() => store.coupons.filter((c) => !c.is_expired).length);
|
||||||
|
|
||||||
onMounted(() => store.loadCoupons());
|
onMounted(() => store.loadCoupons());
|
||||||
|
|
||||||
@ -148,20 +141,5 @@ header h1 { margin: 0; color: #f1f5f9; font-size: 1.6rem; }
|
|||||||
.coupon-name { color: #f1f5f9; font-size: 0.95rem; font-weight: 500; }
|
.coupon-name { color: #f1f5f9; font-size: 0.95rem; font-weight: 500; }
|
||||||
.coupon-code { color: #60a5fa; font-family: monospace; font-size: 0.85rem; }
|
.coupon-code { color: #60a5fa; font-family: monospace; font-size: 0.85rem; }
|
||||||
.coupon-actions { display: flex; align-items: center; gap: 12px; }
|
.coupon-actions { display: flex; align-items: center; gap: 12px; }
|
||||||
.status-label { font-size: 0.8rem; font-weight: 600; min-width: 36px; }
|
|
||||||
.status-label.active { color: #4ade80; }
|
|
||||||
.status-label.inactive { color: #64748b; }
|
|
||||||
.toggle { position: relative; display: inline-block; width: 40px; height: 22px; }
|
|
||||||
.toggle input { opacity: 0; width: 0; height: 0; }
|
|
||||||
.slider {
|
|
||||||
position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0;
|
|
||||||
background: #334155; border-radius: 22px; transition: 0.2s;
|
|
||||||
}
|
|
||||||
.slider:before {
|
|
||||||
position: absolute; content: "";
|
|
||||||
height: 16px; width: 16px; left: 3px; bottom: 3px;
|
|
||||||
background: white; border-radius: 50%; transition: 0.2s;
|
|
||||||
}
|
|
||||||
input:checked + .slider { background: #3b82f6; }
|
|
||||||
input:checked + .slider:before { transform: translateX(18px); }
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user