97 lines
2.9 KiB
JavaScript
97 lines
2.9 KiB
JavaScript
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
|
|
import { supabase, STORAGE_BUCKET } from '../../lib/supabase'
|
|
|
|
export function useMedia() {
|
|
return useQuery({
|
|
queryKey: ['media'],
|
|
queryFn: async () => {
|
|
const { data, error } = await supabase
|
|
.from('media')
|
|
.select('*')
|
|
.order('created_at', { ascending: false })
|
|
.limit(100)
|
|
if (error) throw new Error(error.message)
|
|
return data || []
|
|
},
|
|
})
|
|
}
|
|
|
|
export function useUploadMedia() {
|
|
const qc = useQueryClient()
|
|
return useMutation({
|
|
mutationFn: async ({ campaignId, category, type, file, url }) => {
|
|
if (!campaignId) throw new Error('Select a campaign first.')
|
|
if (!file && !url) throw new Error('Please select a file OR paste a URL.')
|
|
if (file && url) throw new Error('Please select EITHER a file OR a URL, not both.')
|
|
|
|
let finalUrl = ''
|
|
|
|
if (url) {
|
|
try {
|
|
new URL(url)
|
|
finalUrl = url
|
|
} catch {
|
|
throw new Error('Please provide a valid URL (include http/https).')
|
|
}
|
|
} else {
|
|
const ext = file.name.split('.').pop()
|
|
const filePath = `${campaignId}/${Date.now()}-${Math.random().toString(36).slice(2)}.${ext}`
|
|
const { error: uploadError } = await supabase.storage
|
|
.from(STORAGE_BUCKET)
|
|
.upload(filePath, file, { cacheControl: '3600', upsert: false })
|
|
if (uploadError) throw new Error('Upload error: ' + uploadError.message)
|
|
const { data: publicUrlData } = supabase.storage
|
|
.from(STORAGE_BUCKET)
|
|
.getPublicUrl(filePath)
|
|
finalUrl = publicUrlData.publicUrl
|
|
}
|
|
|
|
const { error: insertError } = await supabase.from('media').insert([
|
|
{
|
|
campaign_id: campaignId,
|
|
url: finalUrl,
|
|
category,
|
|
type,
|
|
},
|
|
])
|
|
if (insertError) throw new Error('DB insert error: ' + insertError.message)
|
|
|
|
return finalUrl
|
|
},
|
|
onSuccess: () => {
|
|
qc.invalidateQueries({ queryKey: ['media'] })
|
|
qc.invalidateQueries({ queryKey: ['mediaCampaignIds'] })
|
|
},
|
|
})
|
|
}
|
|
|
|
export function useDeleteMedia() {
|
|
const qc = useQueryClient()
|
|
return useMutation({
|
|
mutationFn: async ({ id, url }) => {
|
|
const { error: dbError } = await supabase
|
|
.from('media')
|
|
.delete()
|
|
.eq('id', id)
|
|
if (dbError) throw new Error(dbError.message)
|
|
|
|
if (url.includes(STORAGE_BUCKET)) {
|
|
try {
|
|
const parts = url.split(STORAGE_BUCKET + '/')
|
|
if (parts.length >= 2) {
|
|
const filePath = parts[1]
|
|
await supabase.storage.from(STORAGE_BUCKET).remove([filePath])
|
|
}
|
|
} catch (e) {
|
|
console.error('Failed to delete from storage', e)
|
|
}
|
|
}
|
|
return id
|
|
},
|
|
onSuccess: () => {
|
|
qc.invalidateQueries({ queryKey: ['media'] })
|
|
qc.invalidateQueries({ queryKey: ['mediaCampaignIds'] })
|
|
},
|
|
})
|
|
}
|