feat: change libraly icons

This commit is contained in:
ngthanhvu
2026-07-25 10:39:40 -04:00
parent 856c514c15
commit 6c1dd39935
33 changed files with 827 additions and 459 deletions
+2 -4
View File
@@ -1,6 +1,4 @@
<script setup lang="ts">
import { Save, Settings as SettingsIcon } from 'lucide-vue-next'
definePageMeta({
layout: 'admin',
})
@@ -26,7 +24,7 @@ const allowRegistration = ref(true)
<div class="rounded-xl border border-white/10 bg-slate-900/50 p-5">
<div class="mb-5 flex items-center gap-3">
<div class="grid size-10 place-items-center rounded-lg bg-yellow-400/10">
<SettingsIcon class="size-4 text-yellow-400" />
<AppIcon name="settings" class="size-4 text-yellow-400" />
</div>
<div>
<h2 class="text-lg font-black text-white">Cài đặt chung</h2>
@@ -74,7 +72,7 @@ const allowRegistration = ref(true)
<div class="flex justify-end">
<button type="button"
class="inline-flex h-10 items-center gap-2 rounded-lg bg-yellow-400 px-5 text-sm font-black text-slate-950 transition hover:bg-yellow-300">
<Save class="size-4" />
<AppIcon name="save" class="size-4" />
Lưu thay đổi
</button>
</div>
+7 -9
View File
@@ -1,6 +1,4 @@
<script setup lang="ts">
import { BarChart3, Film, Play, RefreshCw, TrendingUp, Tv, Users, X } from 'lucide-vue-next'
definePageMeta({
layout: 'admin',
})
@@ -77,7 +75,7 @@ function barWidth(views: number) {
<button type="button"
class="inline-flex h-10 items-center gap-2 rounded-lg bg-yellow-400 px-4 text-sm font-black text-slate-950 transition hover:bg-yellow-300"
@click="syncOpen = true">
<RefreshCw class="size-4" />
<AppIcon name="refresh" class="size-4" />
Đồng bộ phim
</button>
</div>
@@ -91,7 +89,7 @@ function barWidth(views: number) {
<p class="mt-2 text-3xl font-black text-white">{{ stats?.total?.toLocaleString() || 0 }}</p>
</div>
<div class="grid size-11 place-items-center rounded-xl bg-yellow-400/10 text-yellow-400">
<Film class="size-5" />
<AppIcon name="film" class="size-5" />
</div>
</div>
</div>
@@ -103,7 +101,7 @@ function barWidth(views: number) {
<p class="mt-2 text-3xl font-black text-green-400">{{ stats?.active?.toLocaleString() || 0 }}</p>
</div>
<div class="grid size-11 place-items-center rounded-xl bg-green-400/10 text-green-400">
<TrendingUp class="size-5" />
<AppIcon name="trending-up" class="size-5" />
</div>
</div>
</div>
@@ -115,7 +113,7 @@ function barWidth(views: number) {
<p class="mt-2 text-3xl font-black text-blue-400">{{ stats?.series?.toLocaleString() || 0 }}</p>
</div>
<div class="grid size-11 place-items-center rounded-xl bg-blue-400/10 text-blue-400">
<Tv class="size-5" />
<AppIcon name="tv" class="size-5" />
</div>
</div>
</div>
@@ -127,7 +125,7 @@ function barWidth(views: number) {
<p class="mt-2 text-3xl font-black text-purple-400">{{ stats?.single?.toLocaleString() || 0 }}</p>
</div>
<div class="grid size-11 place-items-center rounded-xl bg-purple-400/10 text-purple-400">
<Play class="size-5" />
<AppIcon name="play" class="size-5" />
</div>
</div>
</div>
@@ -315,7 +313,7 @@ function barWidth(views: number) {
<button type="button"
class="absolute right-3 top-3 grid size-8 place-items-center rounded-full text-white transition hover:bg-white/10"
@click="syncOpen = false">
<X class="size-5" />
<AppIcon name="x" class="size-5" />
</button>
<h2 class="text-xl font-black text-white">Đồng bộ phim</h2>
@@ -357,7 +355,7 @@ function barWidth(views: number) {
class="inline-flex h-10 items-center gap-2 rounded-lg bg-yellow-400 px-5 text-sm font-black text-slate-950 transition hover:bg-yellow-300 disabled:opacity-50"
:disabled="syncing || !Object.values(syncSources).some(Boolean)"
@click="handleSync">
<RefreshCw class="size-4" :class="syncing ? 'animate-spin' : ''" />
<AppIcon name="refresh" class="size-4" :class="syncing ? 'animate-spin' : ''" />
{{ syncing ? 'Đang đồng bộ...' : 'Đồng bộ' }}
</button>
</div>
+5 -7
View File
@@ -1,6 +1,4 @@
<script setup lang="ts">
import { Eye, EyeOff, LockKeyhole, LogIn, Mail } from 'lucide-vue-next'
definePageMeta({
layout: false,
middleware: [],
@@ -65,7 +63,7 @@ async function handleLogin() {
<div>
<label class="mb-2 block text-sm font-semibold text-white">Email</label>
<div class="relative">
<Mail class="absolute left-3 top-1/2 size-4 -translate-y-1/2 text-slate-400" />
<AppIcon name="mail" class="absolute left-3 top-1/2 size-4 -translate-y-1/2 text-slate-400" />
<input v-model="email" type="email" required placeholder="admin@cinek.vn"
class="h-11 w-full rounded-lg border border-white/10 bg-white/5 pl-10 pr-4 text-sm text-white placeholder:text-slate-500 outline-none focus:border-yellow-400/50">
</div>
@@ -74,15 +72,15 @@ async function handleLogin() {
<div>
<label class="mb-2 block text-sm font-semibold text-white">Mật khẩu</label>
<div class="relative">
<LockKeyhole class="absolute left-3 top-1/2 size-4 -translate-y-1/2 text-slate-400" />
<AppIcon name="lock" class="absolute left-3 top-1/2 size-4 -translate-y-1/2 text-slate-400" />
<input v-model="password" :type="showPassword ? 'text' : 'password'" required minlength="6"
placeholder="Nhập mật khẩu"
class="h-11 w-full rounded-lg border border-white/10 bg-white/5 pl-10 pr-10 text-sm text-white placeholder:text-slate-500 outline-none focus:border-yellow-400/50">
<button type="button"
class="absolute right-3 top-1/2 -translate-y-1/2 text-slate-400 transition hover:text-white"
@click="showPassword = !showPassword">
<EyeOff v-if="showPassword" class="size-4" />
<Eye v-else class="size-4" />
<AppIcon name="eye-off" v-if="showPassword" class="size-4" />
<AppIcon name="eye" v-else class="size-4" />
</button>
</div>
</div>
@@ -91,7 +89,7 @@ async function handleLogin() {
<button type="submit"
class="mt-6 inline-flex h-11 w-full items-center justify-center gap-2 rounded-lg bg-yellow-400 text-sm font-black text-slate-950 transition hover:bg-yellow-300 disabled:opacity-50"
:disabled="loading">
<LogIn class="size-4" />
<AppIcon name="log-in" class="size-4" />
{{ loading ? 'Đang đăng nhập...' : 'Đăng nhập' }}
</button>
+9 -11
View File
@@ -1,6 +1,4 @@
<script setup lang="ts">
import { ArrowLeft, Check, Film, Image, Plus, Save, Trash2, Type } from 'lucide-vue-next'
definePageMeta({
layout: 'admin',
})
@@ -74,7 +72,7 @@ function clearField(field: 'customPoster' | 'customThumb' | 'customContent') {
<div>
<NuxtLink to="/admin/phim"
class="mb-6 inline-flex items-center gap-2 text-sm font-semibold text-slate-400 transition hover:text-white">
<ArrowLeft class="size-4" />
<AppIcon name="arrow-left" class="size-4" />
Quay lại danh sách phim
</NuxtLink>
@@ -93,7 +91,7 @@ function clearField(field: 'customPoster' | 'customThumb' | 'customContent') {
<button type="button"
class="inline-flex h-10 shrink-0 items-center gap-2 rounded-lg bg-yellow-400 px-5 text-sm font-black text-slate-950 transition hover:bg-yellow-300 disabled:opacity-50"
:disabled="saving" @click="handleSave">
<Save class="size-4" />
<AppIcon name="save" class="size-4" />
{{ saving ? 'Đang lưu...' : 'Lưu thay đổi' }}
</button>
</div>
@@ -101,7 +99,7 @@ function clearField(field: 'customPoster' | 'customThumb' | 'customContent') {
<Transition name="fade">
<div v-if="saved"
class="mb-4 flex items-center gap-2 rounded-lg border border-green-400/20 bg-green-400/10 px-4 py-3 text-sm font-semibold text-green-400">
<Check class="size-4" />
<AppIcon name="check" class="size-4" />
Đã lưu thành công
</div>
</Transition>
@@ -111,7 +109,7 @@ function clearField(field: 'customPoster' | 'customThumb' | 'customContent') {
<div class="rounded-xl border border-white/10 bg-slate-900/50 p-5">
<div class="mb-4 flex items-center gap-3">
<div class="grid size-9 place-items-center rounded-lg bg-blue-400/10">
<Type class="size-4 text-blue-400" />
<AppIcon name="type" class="size-4 text-blue-400" />
</div>
<div>
<h2 class="text-base font-black text-white"> tả phim</h2>
@@ -130,7 +128,7 @@ function clearField(field: 'customPoster' | 'customThumb' | 'customContent') {
<div class="rounded-xl border border-white/10 bg-slate-900/50 p-5">
<div class="mb-4 flex items-center gap-3">
<div class="grid size-9 place-items-center rounded-lg bg-amber-400/10">
<Film class="size-4 text-amber-400" />
<AppIcon name="film" class="size-4 text-amber-400" />
</div>
<div class="flex-1">
<h2 class="text-base font-black text-white">Tập phim tuỳ chỉnh</h2>
@@ -139,7 +137,7 @@ function clearField(field: 'customPoster' | 'customThumb' | 'customContent') {
<button type="button"
class="inline-flex h-8 items-center gap-1.5 rounded-lg bg-white/10 px-3 text-xs font-semibold text-white transition hover:bg-white/20"
@click="addEpisode">
<Plus class="size-3.5" />
<AppIcon name="plus" class="size-3.5" />
Thêm tập
</button>
</div>
@@ -152,7 +150,7 @@ function clearField(field: 'customPoster' | 'customThumb' | 'customContent') {
<button type="button"
class="grid size-7 place-items-center rounded-lg text-red-400 transition hover:bg-red-400/10"
@click="removeEpisode(index)">
<Trash2 class="size-3.5" />
<AppIcon name="trash" class="size-3.5" />
</button>
</div>
<div class="space-y-2">
@@ -173,7 +171,7 @@ function clearField(field: 'customPoster' | 'customThumb' | 'customContent') {
<div class="rounded-xl border border-white/10 bg-slate-900/50 p-5">
<div class="mb-4 flex items-center gap-3">
<div class="grid size-9 place-items-center rounded-lg bg-purple-400/10">
<Image class="size-4 text-purple-400" />
<AppIcon name="image" class="size-4 text-purple-400" />
</div>
<div>
<h2 class="text-base font-black text-white">Ảnh poster</h2>
@@ -196,7 +194,7 @@ function clearField(field: 'customPoster' | 'customThumb' | 'customContent') {
<div class="rounded-xl border border-white/10 bg-slate-900/50 p-5">
<div class="mb-4 flex items-center gap-3">
<div class="grid size-9 place-items-center rounded-lg bg-pink-400/10">
<Image class="size-4 text-pink-400" />
<AppIcon name="image" class="size-4 text-pink-400" />
</div>
<div>
<h2 class="text-base font-black text-white">Ảnh thumbnail</h2>
+7 -9
View File
@@ -1,6 +1,4 @@
<script setup lang="ts">
import { Pencil, RefreshCw, Search, Trash2, X } from 'lucide-vue-next'
definePageMeta({
layout: 'admin',
})
@@ -104,13 +102,13 @@ const totalPages = computed(() => data.value?.totalPages || 1)
<button type="button"
class="inline-flex h-10 items-center gap-2 rounded-lg border border-red-400/20 bg-red-400/10 px-4 text-sm font-black text-red-400 transition hover:bg-red-400/20"
@click="deleteConfirmOpen = true">
<Trash2 class="size-4" />
<AppIcon name="trash" class="size-4" />
Xoá tất cả
</button>
<button type="button"
class="inline-flex h-10 items-center gap-2 rounded-lg bg-yellow-400 px-4 text-sm font-black text-slate-950 transition hover:bg-yellow-300 disabled:opacity-50"
@click="syncOpen = true">
<RefreshCw class="size-4" />
<AppIcon name="refresh" class="size-4" />
Đồng bộ từ API
</button>
</div>
@@ -119,7 +117,7 @@ const totalPages = computed(() => data.value?.totalPages || 1)
<div class="rounded-xl border border-white/10 bg-slate-900/50">
<div class="flex flex-col gap-3 border-b border-white/10 p-4 sm:flex-row sm:items-center">
<div class="relative flex-1">
<Search class="absolute left-3 top-1/2 size-4 -translate-y-1/2 text-slate-400" />
<AppIcon name="search" class="absolute left-3 top-1/2 size-4 -translate-y-1/2 text-slate-400" />
<input v-model="searchInput" type="search" placeholder="Tìm kiếm phim..."
class="h-10 w-full rounded-lg border border-white/10 bg-white/5 pl-10 pr-4 text-sm text-white placeholder:text-slate-400 outline-none focus:border-yellow-400/50">
</div>
@@ -208,7 +206,7 @@ const totalPages = computed(() => data.value?.totalPages || 1)
<NuxtLink :to="`/admin/phim/${movie.id}`"
class="grid size-8 place-items-center rounded-lg text-slate-400 transition hover:bg-white/10 hover:text-white"
title="Chỉnh sửa">
<Pencil class="size-4" />
<AppIcon name="pencil" class="size-4" />
</NuxtLink>
<AdminToggle :model-value="movie.active"
@update:model-value="(val: boolean) => { movie.active = val; toggleActive(movie) }" />
@@ -249,7 +247,7 @@ const totalPages = computed(() => data.value?.totalPages || 1)
<button type="button"
class="absolute right-3 top-3 grid size-8 place-items-center rounded-full text-white transition hover:bg-white/10"
@click="syncOpen = false">
<X class="size-5" />
<AppIcon name="x" class="size-5" />
</button>
<h2 class="text-xl font-black text-white">Đồng bộ phim</h2>
@@ -293,7 +291,7 @@ const totalPages = computed(() => data.value?.totalPages || 1)
<button type="button"
class="inline-flex h-10 items-center gap-2 rounded-lg bg-yellow-400 px-5 text-sm font-black text-slate-950 transition hover:bg-yellow-300 disabled:opacity-50"
:disabled="syncing || !Object.values(syncSources).some(Boolean)" @click="handleSync">
<RefreshCw class="size-4" :class="syncing ? 'animate-spin' : ''" />
<AppIcon name="refresh" class="size-4" :class="syncing ? 'animate-spin' : ''" />
{{ syncing ? 'Đang đồng bộ...' : 'Đồng bộ' }}
</button>
</div>
@@ -318,7 +316,7 @@ const totalPages = computed(() => data.value?.totalPages || 1)
<button type="button"
class="inline-flex h-10 items-center gap-2 rounded-lg bg-red-500 px-5 text-sm font-black text-white transition hover:bg-red-400 disabled:opacity-50"
:disabled="deleting" @click="handleDeleteAll">
<Trash2 class="size-4" />
<AppIcon name="trash" class="size-4" />
{{ deleting ? 'Đang xoá...' : 'Xoá tất cả' }}
</button>
</div>
+2 -4
View File
@@ -1,6 +1,4 @@
<script setup lang="ts">
import { Edit, Mail, Search, Trash2, ToggleLeft, ToggleRight, UserRound } from 'lucide-vue-next'
definePageMeta({
layout: 'admin',
})
@@ -68,7 +66,7 @@ const members = computed(() => data.value?.items || [])
<div class="rounded-xl border border-white/10 bg-slate-900/50">
<div class="flex items-center gap-3 border-b border-white/10 p-4">
<div class="relative flex-1">
<Search class="absolute left-3 top-1/2 size-4 -translate-y-1/2 text-slate-400" />
<AppIcon name="search" class="absolute left-3 top-1/2 size-4 -translate-y-1/2 text-slate-400" />
<input v-model="searchInput" type="search" placeholder="Tìm kiếm thành viên..."
class="h-10 w-full rounded-lg border border-white/10 bg-white/5 pl-10 pr-4 text-sm text-white placeholder:text-slate-400 outline-none focus:border-yellow-400/50">
</div>
@@ -123,7 +121,7 @@ const members = computed(() => data.value?.items || [])
:disabled="currentUser?.id === member.id"
:title="currentUser?.id === member.id ? 'Không thể xoá chính mình' : 'Xoá thành viên'"
@click="deleteMember(member)">
<Trash2 class="size-4" />
<AppIcon name="trash" class="size-4" />
</button>
</div>
</td>