<repo_name>racob/react-blog<file_sep>/src/NotFound.js
import { Alert, Container } from "react-bootstrap";
import { useHistory } from 'react-router-dom';

const NotFound = () => {
    const navStack = useHistory();
    const goBack = () => {
        navStack.push('/');
    };
    return (
        <Container className='my-5'>
            <Alert variant='danger'>
                Sorry, the page you're looking for doesn't exist.
                <Alert.Link onClick={goBack}> Click here to go back to the homepage.</Alert.Link>
            </Alert>
        </Container>
    );
};

export default NotFound;<file_sep>/src/Create.js
import { useState } from 'react';
import { useHistory } from 'react-router-dom';
import { Alert, Card, Container, Form, Button } from 'react-bootstrap';

const Create = () => {
    const [title, setTitle] = useState('');
    const [body, setBody] = useState('');
    const [author, setAuthor] = useState('Mario');
    const [isPending, setIsPending] = useState(false);
    const [submitted, setSubmit] = useState(false);
    const navStack = useHistory();

    const handleSubmit = (e) => {
        e.preventDefault();
        console.log('handling submit');
        setIsPending(true);
        const newBlog = {title, body, author};
        fetch('http://localhost:8000/blogs', {
            method: 'POST',
            headers: {"Content-Type": "application/json"},
            body: JSON.stringify(newBlog)
        }).then(() => {
            setSubmit(true);
            setTimeout(() => {navStack.push('/')}, 2000);
        })
    };

    return (
        <Container className='my-3'>
            { submitted && <Alert variant='success' className='mt-5'>The new blog is successfuly posted! Returning to home page...</Alert> }
            <h1>Create a new blog</h1>
            <Card>
                <Card.Body>
                    <Form onSubmit={!isPending ? handleSubmit : null}>
                        <Form.Group>
                            <Form.Label>New blog title</Form.Label>
                            <Form.Control
                                type="text"
                                placeholder="Enter a new title for your blog..." 
                                value={title}
                                onChange={(e) => setTitle(e.target.value)}
                                disabled={isPending}
                                required
                            />
                        </Form.Group>
                        <Form.Group>
                            <Form.Label>Choose author</Form.Label>
                            <Form.Control 
                                as="select"
                                value={author}
                                onChange={(e) => setAuthor(e.target.value)}
                                required
                                disabled={isPending}
                            >
                                <option>Mario</option>
                                <option>Luigi</option>
                            </Form.Control>
                        </Form.Group>
                        <Form.Group>
                            <Form.Label>Blog body</Form.Label>
                            <Form.Control
                                as="textarea"
                                rows={12}
                                placeholder="Write your blog here..."
                                value={body}
                                onChange={(e) => setBody(e.target.value)}
                                disabled={isPending}
                                required
                            />
                        </Form.Group>
                        <Button 
                            variant="primary"
                            type="submit"
                            className='float-right'
                            disabled={isPending}
                        >
                            {isPending ? 'Posting...' : 'Post blog'}
                        </Button>
                    </Form>
                </Card.Body>
            </Card>
        </Container>
    );
};

export default Create;<file_sep>/src/BlogDetails.js
import { useState } from "react";
import { Container, Alert, Row, Col, Button, Modal} from "react-bootstrap";
import { useHistory, useParams } from "react-router-dom";
import useFetch from './useFetch';

const BlogDetails = () => {
    const [showModal, setShowModal] = useState(false);
    const [deleted, setDeleted] = useState(false);
    const { id } = useParams();
    const { data: blog, isPending, error} = useFetch('http://localhost:8000/blogs/' + id);
    const navStack = useHistory();
    
    
    const toggleModal = () => {
        setShowModal(!showModal);
        console.log(showModal);
    };

    const deletePost = () => {
        fetch('http://localhost:8000/blogs/' + blog.id, {
            method: 'DELETE'
        }).then(() => {
            setDeleted(true);
            toggleModal();
            setTimeout(() => {
                navStack.push('/');
            },2000);
            
        })
    };

    return(
        <Container className='my-5'>
            { deleted && <Alert variant='success' className='mt-5'>The blog has been deleted successfuly!</Alert> }
            { error && <Alert variant='danger' className='mt-5'>{error}</Alert> }
            { isPending && <h3 className='text-muted' >Loading...</h3> }
            {blog && (
                <Container>
                    <Row>
                        <Col>
                            <h1>{blog.title}</h1>
                            <h5 className="text-muted mb-4">Written by {blog.author}</h5>
                        </Col>
                        <Col>
                            <Button
                                className='float-right'
                                variant='outline-danger'
                                onClick={toggleModal}
                            >Delete post</Button>
                        </Col>
                    </Row>
                    <p>{blog.body}</p>
                </Container>
            )}
            <Modal show={showModal}>
                <Modal.Header>
                    <Modal.Title>Delete post</Modal.Title>
                </Modal.Header>
                <Modal.Body>
                    <p>Are you sure? The post cannot be recovered once it is deleted.</p>
                </Modal.Body>
                <Modal.Footer>
                    <Button variant="warning" onClick={toggleModal}>Cancel</Button>
                    <Button variant="outline-danger" onClick={deletePost}>Delete</Button>
                </Modal.Footer>
            </Modal>
        </Container>
    );
};

export default BlogDetails;<file_sep>/README.md
# React-blog

This is an exercise project to learn the basics of React. React-bootstrap is also used as CSS framework.

## Features

- Display all blogs
- Create a new blog
- Delete a blog
- Provides 404 error page

## Available Scripts

In the project directory, you can run:

### `npm install`

This is to install all the required dependencies for the project to run.

### `npm start`

Runs the app in the development mode.\
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.

The page will reload if you make edits.\
You will also see any lint errors in the console.

### `npx json-server --watch data/db.json --port [PORT NUMBER]`

Runs the JSON server as a REST API on a specific port number.
<file_sep>/src/Header.js
import Navbar from 'react-bootstrap/Navbar';
import Nav from 'react-bootstrap/Nav';
import { Link } from 'react-router-dom';

const Header = () => {
    return (
        <Navbar bg="primary" variant="dark" expand="lg">
            <Navbar.Brand href="/">The React Blog</Navbar.Brand>
            <Navbar.Toggle aria-controls="basic-navbar-nav" />
            <Navbar.Collapse id="basic-navbar-nav">
                <Nav className="ml-auto">
                    <Link className="nav-link" to="/">Home</Link>
                    <Link className="nav-link" to="new_blog">New Blog</Link>
                </Nav>
            </Navbar.Collapse>
        </Navbar>
    );
};

export default Header;