Initial commit

This commit is contained in:
2026-05-26 12:11:14 +07:00
commit 9fdd78e737
117 changed files with 10579 additions and 0 deletions
+30
View File
@@ -0,0 +1,30 @@
import axios from 'axios'
const api = axios.create({
baseURL: import.meta.env.VITE_API_BASE_URL || 'http://localhost:3001/api',
withCredentials: true,
headers: { 'Content-Type': 'application/json' },
})
api.interceptors.response.use(
(res) => res,
async (err) => {
const original = err.config
if (err.response?.status === 401 && !original._retry) {
original._retry = true
try {
await axios.post(
`${api.defaults.baseURL}/auth/refresh`,
{},
{ withCredentials: true }
)
return api(original)
} catch {
return Promise.reject(err)
}
}
return Promise.reject(err)
}
)
export default api
+56
View File
@@ -0,0 +1,56 @@
import { Howl } from 'howler'
let howl = null
let listeners = {}
function formatTime(secs) {
if (!secs || isNaN(secs)) return '0:00'
const m = Math.floor(secs / 60)
const s = Math.floor(secs % 60)
return `${m}:${s.toString().padStart(2, '0')}`
}
function load(url) {
destroy()
howl = new Howl({
src: [url],
html5: true,
onplay: () => listeners.onPlay?.(),
onpause: () => listeners.onPause?.(),
onend: () => listeners.onEnd?.(),
onloaderror: () => listeners.onError?.(),
onplayerror: () => listeners.onError?.(),
})
}
function play() { howl?.play() }
function pause() { howl?.pause() }
function togglePlay() { howl?.playing() ? howl.pause() : howl.play() }
function seek(time) { if (howl) howl.seek(time) }
function getSeek() { return howl ? howl.seek() : 0 }
function volume(val) {
if (val !== undefined) Howler.volume(val / 100)
return Howler.volume() * 100
}
function duration() { return howl ? howl.duration() : 0 }
function playing() { return howl ? howl.playing() : false }
function on(event, fn) { listeners[event] = fn }
function off(event) { delete listeners[event] }
function destroy() {
if (howl) {
howl.unload()
howl = null
}
listeners = {}
}
export default {
load, play, pause, togglePlay,
seek, getSeek, volume, duration, playing,
on, off, destroy, formatTime,
}