JourneyPoint / journeypoint / frontend / src / Components / Blog.js
Blog.js
Raw
import React, { useState, useEffect } from 'react';
import Navbar from "./Navbar";
import Footer from "./footer";

const Blog = () => {
    const [blogs, setBlogs] = useState([]);
    const [newBlog, setNewBlog] = useState('');
    const [newComments, setNewComments] = useState({});
    const [imageFile, setImageFile] = useState(null);

    const userName = localStorage.getItem('username') || 'guest';

    useEffect(() => {
        fetchBlogs();
    }, []);

    const fetchBlogs = async () => {
        try {
            const response = await fetch('https://jp-backend-kc80.onrender.com/api/blogs');
            if (response.ok) {
                const data = await response.json();
                setBlogs(data);
            } else {
                console.error('Failed to fetch blogs');
            }
        } catch (error) {
            console.error('Error fetching blogs:', error);
        }
    };

    const handleImageChange = (e) => {
        setImageFile(e.target.files[0]);
    };

    const uploadImage = async (file) => {
        if (!file) return null;

        const formData = new FormData();
        formData.append('file', file);

        try {
            const response = await fetch('https://jp-backend-kc80.onrender.com/upload/', {
                method: 'POST',
                body: formData,
            });
            const data = await response.json();
            return data.image_url;
        } catch (error) {
            console.error('Error uploading image:', error);
            return null;
        }
    };

    const addBlog = async () => {
        let imageUrl = null;

        if (imageFile) {
            imageUrl = await uploadImage(imageFile);
        }

        console.log('Adding blog with details:');
        console.log('Username:', userName);
        console.log('Blog Content:', newBlog);
        console.log('Image URL:', imageUrl);

        try {
            const response = await fetch('https://jp-backend-kc80.onrender.com/api/blogs', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'Accept': 'application/json',
                },
                body: JSON.stringify({
                    username: userName,
                    text_content: newBlog,
                    image_url: imageUrl || '',
                }),
            });

            if (response.ok) {
                setNewBlog('');
                setImageFile(null);
                fetchBlogs();
            } else {
                console.error('Failed to add blog');
            }
        } catch (error) {
            console.error('Error adding blog:', error);
        }
    };

    const addComment = async (blogId, commentText) => {
        try {
            const response = await fetch(`https://jp-backend-kc80.onrender.com/api/blogs/${blogId}/comment`, {
                method: 'PATCH',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({
                    username: userName,
                    comment: commentText,
                }),
            });

            if (response.ok) {
                fetchBlogs();
                setNewComments({ ...newComments, [blogId]: '' });
            } else {
                console.error('Failed to add comment');
            }
        } catch (error) {
            console.error('Error adding comment:', error);
        }
    };

    const likeBlog = async (blogId) => {
        try {
            const response = await fetch(`https://jp-backend-kc80.onrender.com/api/blogs/${blogId}/like`, {
                method: 'PATCH',
            });

            if (response.ok) {
                fetchBlogs();
            } else {
                console.error('Failed to like blog');
            }
        } catch (error) {
            console.error('Error liking blog:', error);
        }
    };

    const handleCommentChange = (blogId, value) => {
        setNewComments({ ...newComments, [blogId]: value });
    };

    return (
        <div style={{
            display: 'flex',
            flexDirection: 'column',
            minHeight: '100vh',
            background: 'linear-gradient(-45deg, #ee7752, #e73c7e, #23a6d5, #23d5ab)',
            backgroundSize: '400% 400%',
            animation: 'gradient 15s ease infinite',
        }}>
            <style>
                {`
                    @keyframes gradient {
                        0% {
                            background-position: 0% 50%;
                        }
                        50% {
                            background-position: 100% 50%;
                        }
                        100% {
                            background-position: 0% 50%;
                        }
                    }
                `}
            </style>
            <Navbar />
            <div className="container py-5 px-5" style={{ flex: '1' }}>
                <h2 className="text-center mb-5">Blog</h2>
                <div className="mb-4">
                    <textarea
                        className="form-control"
                        value={newBlog}
                        onChange={(e) => setNewBlog(e.target.value)}
                        placeholder="Write your blog here..."
                    />
                    <input type="file" onChange={handleImageChange} accept="image/*" className="form-control mt-2"/>
                    <button className="btn btn-primary mt-2" onClick={addBlog}>Add Blog</button>
                </div>
                {blogs.map((blog) => (
                    <div key={blog.id} className="card mb-4">
                        <div className="card-body">
                            <p><strong>{blog.username}:</strong> {blog.text_content}</p>
                            {blog.image_url && <img src={blog.image_url} alt="Blog" style={{ maxWidth: '100%', maxHeight: '300px', objectFit: 'contain' }} />}
                            <div className="mt-2">
                                <button className="btn btn-success" onClick={() => likeBlog(blog.id)}>Like ({blog.likes})</button>
                            </div>
                            <div className="mt-3">
                                <textarea
                                    className="form-control"
                                    value={newComments[blog.id] || ''}
                                    onChange={(e) => handleCommentChange(blog.id, e.target.value)}
                                    placeholder="Add a comment..."
                                />
                                <button className="btn btn-secondary mt-2" onClick={() => addComment(blog.id, newComments[blog.id])}>Add Comment</button>
                            </div>
                            <div className="mt-3">
                                <h5>Comments:</h5>
                                {Object.entries(blog.comments || {}).map(([user, comment]) => (
                                    <p key={user}><strong>{user}:</strong> {comment}</p>
                                ))}
                            </div>
                        </div>
                    </div>
                ))}
            </div>
            <Footer />
        </div>
    );
};

export default Blog;