feat: not working download zip file
This commit is contained in:
@@ -41,7 +41,7 @@ class ApiClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ==================== Auth ====================
|
// ==================== Auth ====================
|
||||||
|
|
||||||
async register(email, password, displayName = null) {
|
async register(email, password, displayName = null) {
|
||||||
return this.request('/auth/register', {
|
return this.request('/auth/register', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
@@ -58,12 +58,12 @@ class ApiClient {
|
|||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify({ email, password }),
|
body: JSON.stringify({ email, password }),
|
||||||
});
|
});
|
||||||
|
|
||||||
// Store user ID for subsequent requests
|
// Store user ID for subsequent requests
|
||||||
if (response.user?.user_id) {
|
if (response.user?.user_id) {
|
||||||
this.setUserId(response.user.user_id);
|
this.setUserId(response.user.user_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,7 +81,7 @@ class ApiClient {
|
|||||||
|
|
||||||
async uploadPost(formData) {
|
async uploadPost(formData) {
|
||||||
const url = `${this.baseUrl}/posts/upload`;
|
const url = `${this.baseUrl}/posts/upload`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch(url, {
|
const response = await fetch(url, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
@@ -103,7 +103,7 @@ class ApiClient {
|
|||||||
|
|
||||||
async getPosts(params = {}) {
|
async getPosts(params = {}) {
|
||||||
const queryParams = new URLSearchParams();
|
const queryParams = new URLSearchParams();
|
||||||
|
|
||||||
if (params.page) queryParams.append('page', params.page);
|
if (params.page) queryParams.append('page', params.page);
|
||||||
if (params.limit) queryParams.append('limit', params.limit);
|
if (params.limit) queryParams.append('limit', params.limit);
|
||||||
if (params.visibility) queryParams.append('visibility', params.visibility);
|
if (params.visibility) queryParams.append('visibility', params.visibility);
|
||||||
@@ -153,6 +153,12 @@ class ApiClient {
|
|||||||
return this.request(`/posts/${postId}/metadata`);
|
return this.request(`/posts/${postId}/metadata`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async exportPost(postId) {
|
||||||
|
const response = await fetch(`/api/posts/${postId}/download`, { method: "GET" });
|
||||||
|
if (!response.ok) throw new Error(`Failed to download post: ${response.statusText}`);
|
||||||
|
return await response.blob(); // returns proper Blob ready for download
|
||||||
|
}
|
||||||
|
|
||||||
// ==================== RAG Search ====================
|
// ==================== RAG Search ====================
|
||||||
|
|
||||||
async searchRAG(query, userId, page = 1, limit = 30) {
|
async searchRAG(query, userId, page = 1, limit = 30) {
|
||||||
@@ -174,7 +180,7 @@ class ApiClient {
|
|||||||
|
|
||||||
async getAuditLogs(params = {}) {
|
async getAuditLogs(params = {}) {
|
||||||
const queryParams = new URLSearchParams();
|
const queryParams = new URLSearchParams();
|
||||||
|
|
||||||
if (params.post_id) queryParams.append('post_id', params.post_id);
|
if (params.post_id) queryParams.append('post_id', params.post_id);
|
||||||
if (params.user_id) queryParams.append('user_id', params.user_id);
|
if (params.user_id) queryParams.append('user_id', params.user_id);
|
||||||
if (params.page) queryParams.append('page', params.page);
|
if (params.page) queryParams.append('page', params.page);
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ export default function AudioPostCard({ post }) {
|
|||||||
const now = new Date()
|
const now = new Date()
|
||||||
const diffMs = now - date
|
const diffMs = now - date
|
||||||
const diffMins = Math.floor(diffMs / 60000)
|
const diffMins = Math.floor(diffMs / 60000)
|
||||||
|
|
||||||
if (diffMins < 60) return `${diffMins}m ago`
|
if (diffMins < 60) return `${diffMins}m ago`
|
||||||
if (diffMins < 1440) return `${Math.floor(diffMins / 60)}h ago`
|
if (diffMins < 1440) return `${Math.floor(diffMins / 60)}h ago`
|
||||||
return `${Math.floor(diffMins / 1440)}d ago`
|
return `${Math.floor(diffMins / 1440)}d ago`
|
||||||
@@ -42,7 +42,7 @@ export default function AudioPostCard({ post }) {
|
|||||||
if (post.status === 'ready' && !transcript && !loadingTranscript) {
|
if (post.status === 'ready' && !transcript && !loadingTranscript) {
|
||||||
loadTranscript()
|
loadTranscript()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set audio source if available
|
// Set audio source if available
|
||||||
if (post.audio_url && audioRef.current) {
|
if (post.audio_url && audioRef.current) {
|
||||||
console.log('Setting audio src to:', post.audio_url)
|
console.log('Setting audio src to:', post.audio_url)
|
||||||
@@ -75,7 +75,7 @@ export default function AudioPostCard({ post }) {
|
|||||||
|
|
||||||
const togglePlay = () => {
|
const togglePlay = () => {
|
||||||
if (!audioRef.current) return
|
if (!audioRef.current) return
|
||||||
|
|
||||||
if (isPlaying) {
|
if (isPlaying) {
|
||||||
audioRef.current.pause()
|
audioRef.current.pause()
|
||||||
} else {
|
} else {
|
||||||
@@ -107,7 +107,7 @@ export default function AudioPostCard({ post }) {
|
|||||||
const x = e.clientX - rect.left
|
const x = e.clientX - rect.left
|
||||||
const percentage = x / rect.width
|
const percentage = x / rect.width
|
||||||
const newTime = percentage * duration
|
const newTime = percentage * duration
|
||||||
|
|
||||||
if (audioRef.current) {
|
if (audioRef.current) {
|
||||||
audioRef.current.currentTime = newTime
|
audioRef.current.currentTime = newTime
|
||||||
setCurrentTime(newTime)
|
setCurrentTime(newTime)
|
||||||
@@ -122,6 +122,24 @@ export default function AudioPostCard({ post }) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleDownload = async () => {
|
||||||
|
try {
|
||||||
|
const zipBlob = await api.exportPost(post.post_id);
|
||||||
|
|
||||||
|
const url = window.URL.createObjectURL(zipBlob);
|
||||||
|
const a = document.createElement("a");
|
||||||
|
a.href = url;
|
||||||
|
a.download = `${post.title.replace(/\s+/g, "_")}.zip`;
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
a.remove();
|
||||||
|
window.URL.revokeObjectURL(url);
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Failed to download post:", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const handleEnded = () => {
|
const handleEnded = () => {
|
||||||
setIsPlaying(false)
|
setIsPlaying(false)
|
||||||
setCurrentTime(0)
|
setCurrentTime(0)
|
||||||
@@ -156,6 +174,15 @@ export default function AudioPostCard({ post }) {
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{post.status === "ready" && (
|
||||||
|
<button
|
||||||
|
onClick={handleDownload}
|
||||||
|
className="mt-2 px-3 py-1 bg-[#f4b840] text-black rounded hover:bg-[#e5a930] transition-colors"
|
||||||
|
>
|
||||||
|
Download Post
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
|
||||||
<button className="text-gray-500 hover:text-gray-700">
|
<button className="text-gray-500 hover:text-gray-700">
|
||||||
<MoreVertical size={18} />
|
<MoreVertical size={18} />
|
||||||
</button>
|
</button>
|
||||||
@@ -185,7 +212,7 @@ export default function AudioPostCard({ post }) {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
<button
|
<button
|
||||||
onClick={togglePlay}
|
onClick={togglePlay}
|
||||||
className="w-10 h-10 bg-[#f4b840] hover:bg-[#e5a930] rounded-full flex items-center justify-center text-[#1a1a1a] transition-colors"
|
className="w-10 h-10 bg-[#f4b840] hover:bg-[#e5a930] rounded-full flex items-center justify-center text-[#1a1a1a] transition-colors"
|
||||||
>
|
>
|
||||||
@@ -196,11 +223,11 @@ export default function AudioPostCard({ post }) {
|
|||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<div
|
<div
|
||||||
className="h-1.5 bg-gray-300 rounded-full overflow-hidden mb-2 cursor-pointer"
|
className="h-1.5 bg-gray-300 rounded-full overflow-hidden mb-2 cursor-pointer"
|
||||||
onClick={handleSeek}
|
onClick={handleSeek}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="h-full bg-[#f4b840] rounded-full transition-all"
|
className="h-full bg-[#f4b840] rounded-full transition-all"
|
||||||
style={{ width: `${progress}%` }}
|
style={{ width: `${progress}%` }}
|
||||||
></div>
|
></div>
|
||||||
@@ -241,7 +268,7 @@ export default function AudioPostCard({ post }) {
|
|||||||
transcriptExpanded ? <ChevronUp size={18} /> : <ChevronDown size={18} />
|
transcriptExpanded ? <ChevronUp size={18} /> : <ChevronDown size={18} />
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
{transcript && (
|
{transcript && (
|
||||||
<div className={`bg-white transition-all ${transcriptExpanded ? 'max-h-96' : 'max-h-24'} overflow-y-auto`}>
|
<div className={`bg-white transition-all ${transcriptExpanded ? 'max-h-96' : 'max-h-24'} overflow-y-auto`}>
|
||||||
<div className="p-4">
|
<div className="p-4">
|
||||||
|
|||||||
Reference in New Issue
Block a user