feat(front) react version start
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
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'] })
|
||||
},
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user