import React, { useState, useEffect, useRef } from "react";
import MDEditor, { commands } from '@uiw/react-md-editor';
import { Input } from './ui/input';
import { Label } from './ui/label';
import { Select, SelectTrigger, SelectValue, SelectContent, SelectItem } from './ui/select';
import { Button } from './ui/button';
import { Separator } from './ui/separator';
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from './ui/dialog';
import { CustomTabs } from './ui/tabs';
import Cookies from 'js-cookie';
const PUBLIC_MINIO_UPLOAD_URL = 'https://file-vault-prod-pdgctwgsnkiy.siliconpin.com/upload';
const IMAGE_URL_PREFIX = 'https://file-delivery.ndgctwgsnkiy.siliconpin.com/';
// const PUBLIC_MINIO_UPLOAD_URL = import.meta.env.PUBLIC_MINIO_UPLOAD_URL;
const PUBLIC_TOPIC_API_URL = import.meta.env.PUBLIC_TOPIC_API_URL;
const NewTopic = () => {
// Form state
const [formData, setFormData] = useState({ status: 'draft', category: '', title: '', content: '', imageUrl: '' });
// UI state
const [isSubmitting, setIsSubmitting] = useState(false);
const [error, setError] = useState(null);
const [success, setSuccess] = useState(false);
const [imageFile, setImageFile] = useState(null);
const [uploadProgress, setUploadProgress] = useState(0);
const [imageDialogOpen, setImageDialogOpen] = useState(false);
const [imageUrlInput, setImageUrlInput] = useState('');
const [imageUploadFile, setImageUploadFile] = useState(null);
const [imageUploadPreview, setImageUploadPreview] = useState('');
const [editorMode, setEditorMode] = useState('edit');
const uploadToMinIO = async (file, onProgress) => {
const siliconId = Cookies.get('siliconId'); // Get from cookie or anywhere
const token = Cookies.get('token'); // Get from cookie or storage
const formData = new FormData();
formData.append('file', file);
try {
const response = await fetch(PUBLIC_MINIO_UPLOAD_URL, {
method: 'POST',
headers: {
'x-user-data': siliconId,
'Authorization': token,
},
body: formData
});
if (!response.ok) {
throw new Error(`Upload failed: ${response.statusText}`);
}
const data = await response.json();
// console.log('Upload successful:', data);
return data;
} catch (error) {
console.error('Upload error:', error);
throw error;
}
};
// // Generate slug from title
// useEffect(() => {
// if (formData.title) {
// const slug = formData.title
// .toLowerCase()
// .replace(/[^\w\s]/g, '')
// .replace(/\s+/g, '-');
// setFormData(prev => ({ ...prev, slug }));
// }
// }, [formData.title]);
const customImageCommand = {
name: 'image',
keyCommand: 'image',
buttonProps: { 'aria-label': 'Insert image' },
icon: (
),
execute: () => {
setImageDialogOpen(true);
},
};
// Custom
insert command
const lineBreakCommand = {
name: 'linebreak',
keyCommand: 'linebreak',
buttonProps: { 'aria-label': 'Insert line break' },
icon: (
),
execute: () => {
const textarea = document.querySelector('.w-md-editor-text-input');
if (!textarea) return;
const start = textarea.selectionStart;
const end = textarea.selectionEnd;
const value = formData.content || "";
const breakTag = '
';
const newValue = value.slice(0, start) + breakTag + value.slice(end);
setFormData(prev => ({
...prev,
content: newValue
}));
setTimeout(() => {
textarea.selectionStart = textarea.selectionEnd = start + breakTag.length;
textarea.focus();
}, 0);
}
};
// Get all commands (same as NewTopic)
const allCommands = [
...commands.getCommands().map(cmd => {
if (cmd.name === 'image') {
return customImageCommand;
}
return cmd;
}),
lineBreakCommand,
];
// Handle image URL insertion
const handleInsertImageUrl = () => {
if (imageUrlInput) {
const imgMarkdown = ``;
const textarea = document.querySelector('.w-md-editor-text-input');
if (textarea) {
const startPos = textarea.selectionStart;
const endPos = textarea.selectionEnd;
const currentValue = formData.content;
const newValue =
currentValue.substring(0, startPos) +
imgMarkdown +
currentValue.substring(endPos);
setFormData(prev => ({ ...prev, content: newValue }));
}
setImageDialogOpen(false);
setImageUrlInput('');
}
};
// Handle image file selection
const handleImageFileSelect = (e) => {
const file = e.target.files[0];
if (file) {
setImageUploadFile(file);
// Create preview
const reader = new FileReader();
reader.onload = () => {
setImageUploadPreview(reader.result);
};
reader.readAsDataURL(file);
}
};
// Upload image file to MinIO and insert into editor
const handleImageUpload = async () => {
if (!imageUploadFile) return;
console.log(imageUploadFile)
try {
setIsSubmitting(true);
setUploadProgress(0);
const uploadedUrl = await uploadToMinIO(imageUploadFile, (progress) => {
setUploadProgress(progress);
});
// Insert markdown for the uploaded image
const imgMarkdown = ``;
const textarea = document.querySelector('.w-md-editor-text-input');
if (textarea) {
const startPos = textarea.selectionStart;
const endPos = textarea.selectionEnd;
const currentValue = formData.content;
const newValue =
currentValue.substring(0, startPos) +
imgMarkdown +
currentValue.substring(endPos);
setFormData(prev => ({ ...prev, content: newValue }));
}
setImageDialogOpen(false);
setImageUploadFile(null);
setImageUploadPreview('');
} catch (error) {
setError('Failed to upload image: ' + error.message);
} finally {
setIsSubmitting(false);
}
};
// Form submission
const handleSubmit = async (e) => {
e.preventDefault();
setIsSubmitting(true);
setError(null);
setUploadProgress(0);
try {
// Upload featured image if selected
let imageUrl = formData.imageUrl.url;
if (imageFile) {
imageUrl = await uploadToMinIO(imageFile, (progress) => {
console.log('imageUrl', imageUrl)
setUploadProgress(progress);
});
}
imageUrl = imageUrl.url;
// Prepare payload
const payload = {
...formData,
imageUrl
};
// Submit to API
const response = await fetch(`${PUBLIC_TOPIC_API_URL}?query=create-new-topic`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
credentials: 'include',
body: JSON.stringify(payload)
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.message || 'Failed to create topic');
}
setSuccess(true);
} catch (err) {
setError(err.message);
} finally {
setIsSubmitting(false);
setUploadProgress(0);
}
};
// Handle form field changes
const handleChange = (e) => {
const { name, value } = e.target;
setFormData(prev => ({ ...prev, [name]: value }));
};
// Handle featured image file selection
const handleFileChange = (e) => {
const file = e.target.files[0];
if (file) {
setImageFile(file);
// Preview image
const reader = new FileReader();
reader.onload = () => {
setFormData(prev => ({ ...prev, imageUrl: reader.result }));
};
reader.readAsDataURL(file);
}
};
// Reset form
const resetForm = () => {
setFormData({
status: 'draft',
category: '',
title: '',
slug: '',
content: '',
imageUrl: ''
});
setImageFile(null);
setSuccess(false);
setError(null);
};
// Success state
if (success) {
return (
Start a new discussion in the SiliconPin community