Refactor: Remove Supabase authentication and related code

- Removed Supabase authentication logic from xem/[slug].vue and yeu-thich.vue.
- Updated favorite and watch later messages to be device-specific.
- Removed unused user state and authentication initialization.
- Deleted supabase.ts plugin file and related configurations.
- Updated nuxt.config.ts to remove Supabase runtime configuration.
- Removed Supabase dependencies from package.json and package-lock.json.
- Adjusted Dockerfile for development environment.
- Added admin layout and pages for managing settings, movies, and users.
- Implemented admin dashboard with statistics and recent activities.
- Created movie and user management interfaces with search functionality.
This commit is contained in:
ngthanhvu
2026-07-21 23:43:04 -04:00
parent 2782ffb75e
commit f09e3275eb
22 changed files with 697 additions and 760 deletions
+10 -64
View File
@@ -56,31 +56,15 @@ function legacyKeyFor(key: string) {
}
export function useMovieLibrary() {
const { $supabase } = useNuxtApp()
const { user } = useSupabaseAuth()
async function loadItems(key: string, table: string, limit = 30) {
async function loadItems(key: string, limit = 30) {
const localItems = readLocalItems(key, legacyKeyFor(key))
if (user.value) {
const { data, error } = await $supabase
.from(table)
.select('source, slug, name, origin_name, thumb, poster, updated_at')
.eq('user_id', user.value.id)
.order('updated_at', { ascending: false })
.limit(limit)
if (!error && data) {
return data.map(normalizeLibraryItem).filter(Boolean) as LibraryMovieItem[]
}
}
return localItems
.sort((a, b) => (b.updatedAt || 0) - (a.updatedAt || 0))
.slice(0, limit)
}
async function saveItem(key: string, table: string, item: LibraryMovieItem) {
async function saveItem(key: string, item: LibraryMovieItem) {
const normalizedItem = normalizeLibraryItem({
...item,
updatedAt: Date.now(),
@@ -95,63 +79,25 @@ export function useMovieLibrary() {
writeLocalItems(key, nextItems)
if (user.value) {
await $supabase
.from(table)
.upsert({
user_id: user.value.id,
source: normalizedItem.source,
slug: normalizedItem.slug,
name: normalizedItem.name,
origin_name: normalizedItem.originName || null,
thumb: normalizedItem.thumb || null,
poster: normalizedItem.poster || null,
updated_at: new Date(normalizedItem.updatedAt || Date.now()).toISOString(),
}, {
onConflict: 'user_id,source,slug',
})
}
return true
}
async function removeItem(key: string, table: string, item: LibraryMovieItem) {
async function removeItem(key: string, item: LibraryMovieItem) {
const nextItems = readLocalItems(key, legacyKeyFor(key))
.filter((savedItem) => !(savedItem.slug === item.slug && savedItem.source === item.source))
writeLocalItems(key, nextItems)
if (user.value) {
await $supabase
.from(table)
.delete()
.eq('user_id', user.value.id)
.eq('source', item.source)
.eq('slug', item.slug)
}
}
async function isSaved(key: string, table: string, item: LibraryMovieItem) {
const localSaved = readLocalItems(key, legacyKeyFor(key))
async function isSaved(key: string, item: LibraryMovieItem) {
return readLocalItems(key, legacyKeyFor(key))
.some((savedItem) => savedItem.slug === item.slug && savedItem.source === item.source)
if (!user.value) return localSaved
const { data, error } = await $supabase
.from(table)
.select('slug')
.eq('user_id', user.value.id)
.eq('source', item.source)
.eq('slug', item.slug)
.maybeSingle()
return error ? localSaved : Boolean(data)
}
return {
loadFavorites: (limit?: number) => loadItems(favoriteKey, 'favorite_movies', limit),
saveFavorite: (item: LibraryMovieItem) => saveItem(favoriteKey, 'favorite_movies', item),
removeFavorite: (item: LibraryMovieItem) => removeItem(favoriteKey, 'favorite_movies', item),
isFavorite: (item: LibraryMovieItem) => isSaved(favoriteKey, 'favorite_movies', item),
saveWatchLater: (item: LibraryMovieItem) => saveItem(watchLaterKey, 'watch_later_movies', item),
loadFavorites: (limit?: number) => loadItems(favoriteKey, limit),
saveFavorite: (item: LibraryMovieItem) => saveItem(favoriteKey, item),
removeFavorite: (item: LibraryMovieItem) => removeItem(favoriteKey, item),
isFavorite: (item: LibraryMovieItem) => isSaved(favoriteKey, item),
saveWatchLater: (item: LibraryMovieItem) => saveItem(watchLaterKey, item),
}
}
-86
View File
@@ -1,86 +0,0 @@
import type { User } from '@supabase/supabase-js'
let authListenerStarted = false
export function useSupabaseAuth() {
const { $supabase } = useNuxtApp()
const user = useState<User | null>('supabase-user', () => null)
const loading = useState('supabase-auth-loading', () => false)
async function initAuth() {
if (!import.meta.client || authListenerStarted) return
authListenerStarted = true
loading.value = true
const { data } = await $supabase.auth.getSession()
user.value = data.session?.user ?? null
loading.value = false
$supabase.auth.onAuthStateChange((_event, session) => {
user.value = session?.user ?? null
})
}
function authRedirectUrl() {
const redirectTo = import.meta.client ? window.location.origin : undefined
return redirectTo
}
async function signInWithEmail(email: string) {
return $supabase.auth.signInWithOtp({
email,
options: {
emailRedirectTo: authRedirectUrl(),
},
})
}
async function signInWithPassword(email: string, password: string) {
return $supabase.auth.signInWithPassword({
email,
password,
})
}
async function signUpWithPassword(email: string, password: string) {
return $supabase.auth.signUp({
email,
password,
options: {
emailRedirectTo: authRedirectUrl(),
},
})
}
async function signInWithGoogle() {
return $supabase.auth.signInWithOAuth({
provider: 'google',
options: {
redirectTo: authRedirectUrl(),
},
})
}
async function resetPassword(email: string) {
return $supabase.auth.resetPasswordForEmail(email, {
redirectTo: authRedirectUrl(),
})
}
async function signOut() {
return $supabase.auth.signOut()
}
return {
user,
loading,
initAuth,
signInWithEmail,
signInWithPassword,
signUpWithPassword,
signInWithGoogle,
resetPassword,
signOut,
}
}
-69
View File
@@ -63,49 +63,9 @@ function writeLocalHistory(items: WatchHistoryItem[]) {
}
export function useWatchHistory() {
const { $supabase } = useNuxtApp()
const { user } = useSupabaseAuth()
async function loadWatchHistory(limit = 12) {
const localItems = readLocalHistory()
if (user.value) {
if (localItems.length) {
await $supabase
.from('watch_history')
.upsert(localItems.slice(0, 20).map((item) => ({
user_id: user.value?.id,
source: item.source,
slug: item.slug,
name: item.name,
origin_name: item.originName || null,
thumb: item.thumb || null,
poster: item.poster || null,
episode_name: item.episodeName || null,
episode_index: item.episodeIndex || 0,
server_index: item.serverIndex || 0,
progress_seconds: Math.floor(item.progressSeconds || 0),
duration_seconds: Math.floor(item.durationSeconds || 0),
updated_at: new Date(item.updatedAt || Date.now()).toISOString(),
})), {
onConflict: 'user_id,source,slug',
})
}
const { data, error } = await $supabase
.from('watch_history')
.select('source, slug, name, origin_name, thumb, poster, episode_name, episode_index, server_index, progress_seconds, duration_seconds, updated_at')
.eq('user_id', user.value.id)
.order('updated_at', { ascending: false })
.limit(limit)
if (!error && data) {
return data
.map(normalizeHistoryItem)
.filter(Boolean) as WatchHistoryItem[]
}
}
return localItems
.sort((a, b) => (b.updatedAt || 0) - (a.updatedAt || 0))
.slice(0, limit)
@@ -125,28 +85,6 @@ export function useWatchHistory() {
].slice(0, 20)
writeLocalHistory(localItems)
if (!user.value) return
await $supabase
.from('watch_history')
.upsert({
user_id: user.value.id,
source: normalizedItem.source,
slug: normalizedItem.slug,
name: normalizedItem.name,
origin_name: normalizedItem.originName || null,
thumb: normalizedItem.thumb || null,
poster: normalizedItem.poster || null,
episode_name: normalizedItem.episodeName || null,
episode_index: normalizedItem.episodeIndex || 0,
server_index: normalizedItem.serverIndex || 0,
progress_seconds: Math.floor(normalizedItem.progressSeconds || 0),
duration_seconds: Math.floor(normalizedItem.durationSeconds || 0),
updated_at: new Date(normalizedItem.updatedAt || Date.now()).toISOString(),
}, {
onConflict: 'user_id,source,slug',
})
}
async function clearWatchHistory() {
@@ -154,13 +92,6 @@ export function useWatchHistory() {
window.localStorage.removeItem(watchHistoryKey)
window.localStorage.removeItem(legacyWatchHistoryKey)
}
if (user.value) {
await $supabase
.from('watch_history')
.delete()
.eq('user_id', user.value.id)
}
}
return {