Horje
Document Management System using NextJS

The Document Management System is a web application developed using Next.js, that allows users to efficiently manage their documents. The system provides features for uploading, organizing, and retrieving documents. Users can upload documents through the web interface, which are then stored in local storage.

Output Preview: Let us have a look at how the final output will look like.

gfgd

Prerequisites:

Approach to Create Document Management System:

  • Setup the Project by Creating a new NextJS project Install the necessary libraries.
  • Design the layout of Document Management System, including components like Navbar, Documents, AddDocument, SearchBar, etc.
  • Create Documents component which will display the list of documents added with functionality to view, delete and search specific document. Create a modal to view a document in detail.
  • Create AddDocument component which contains the form to add the document details such as name, description and image.
  • Use useState hook to manage the form state.
  • Use localStorage to store document metadata
  • We will use Bootstrap to style the components.

Steps to Create Document Management System:

Step 1: Create a application of NextJS using the following command.

npx create-next-app doc-management

Step 2: Navigate to project directory

cd doc-management

Step 3: Install the necessary package in your project using the following command.

npm install bootstrap
npm install react-toastify

Step 4: Create the folder structure as shown below and create the files in respective folders.

Project Structure:

Screenshot-(59)

The updated dependencies in package.json file will look like:

"dependencies": {
"bootstrap": "^5.3.3",
"next": "14.1.3",
"react": "^18",
"react-dom": "^18",
"react-toastify": "^10.0.5"
}

Example: Below are the components which describes the implementation Document Management System.

JavaScript
// page.js

import React from 'react'
import Documents from './components/Documents'

const page = () => {
    return (
        <div>
            <Documents />
        </div>
    )
}

export default page;
JavaScript
// Navbar.js
import React from 'react';
import 'bootstrap/dist/css/bootstrap.min.css';
import Link from 'next/link';
function Navbar() {
    return (
        <nav className="navbar navbar-expand-lg navbar-light 
                        bg-light shadow top-0">
            <div className="container">
                <a className="navbar-brand" href="#">
                    GFG DocManager
                </a>
                <button className="navbar-toggler"
                    type="button" data-toggle="collapse"
                    data-target="#navbarNav" aria-controls="navbarNav"
                    aria-expanded="false" aria-label="Toggle navigation">
                    <span className="navbar-toggler-icon"></span>
                </button>
                <div className="collapse navbar-collapse" id="navbarNav">
                    <ul className="navbar-nav">
                        <li className="nav-item">
                            <Link className="nav-link"
                                href="/">Documents
                            </Link>
                        </li>
                        <li className="nav-item">
                            <Link className="nav-link"
                                href="AddDocument">Add New Document
                            </Link>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
    );
}

export default Navbar;
JavaScript
// Documents.js

'use client'
import React, { useState, useEffect } from 'react';
import 'bootstrap/dist/css/bootstrap.min.css';
import Navbar from './Navbar';

const Documents = () => {
    const [documents, setDocuments] = useState([]);
    const [selectedDocument, setSelectedDocument] = useState(null);
    const [showModal, setShowModal] = useState(false);
    const [searchQuery, setSearchQuery] = useState('');

    useEffect(() => {
        const storedDocuments = JSON.parse(localStorage.getItem('documents')) || [];
        setDocuments(storedDocuments);
    }, []);

    const handleViewDocument = (id) => {
        const document = documents.find(doc => doc.id === id);
        setSelectedDocument(document);
        setShowModal(true);
    };

    const handleDeleteDocument = (id) => {
        const updatedDocuments = documents.filter((document) => document.id !== id);
        setDocuments(updatedDocuments);
        localStorage.setItem('documents', JSON.stringify(updatedDocuments));
    };

    const filteredDocuments = documents.filter(document =>
        document.name.toLowerCase().includes(searchQuery.toLowerCase())
    );

    return (
        <>
            <Navbar />
            <div className="container mt-5">
                <div className="row">
                    <div className="col-md-1 border-end"></div>
                    <div className="mb-3">
                        <input
                            type="text"
                            className="form-control"
                            placeholder="Search documents..."
                            value={searchQuery}
                            onChange={(e) => setSearchQuery(e.target.value)}
                        />
                    </div>
                    <div className="col">
                        <h2>Document List</h2>

                        <table className="table">
                            <thead>
                                <tr>
                                    <th>ID</th>
                                    <th>Name</th>
                                    <th>Created Date</th>
                                    <th>Action</th>
                                </tr>
                            </thead>
                            <tbody>
                                {filteredDocuments.map((document) => (
                                    <tr key={document.id}>
                                        <td>{document.id}</td>
                                        <td>{document.name}</td>
                                        <td>{document.date}</td>
                                        <td>
                                            <button className="btn btn-primary"
                                                onClick={() =>
                                                    handleViewDocument(document.id)}>
                                                View
                                            </button>
                                            <button className="btn btn-danger ms-2"
                                                onClick={() =>
                                                    handleDeleteDocument(document.id)}>
                                                Delete
                                            </button>
                                        </td>
                                    </tr>
                                ))}
                            </tbody>
                        </table>
                    </div>
                </div>
            </div>

            {showModal && (
                <div className="modal" tabIndex="-1" role="dialog" style={{
                    display: 'block', backgroundColor: 'rgba(0, 0, 0, 0.5)'
                }}>
                    <div className="modal-dialog modal-dialog-centered"
                        role="document">
                        <div className="modal-content">
                            <div className="modal-header">
                                <h5 className="modal-title">
                                    {selectedDocument?.name}
                                </h5>
                                <button type="button" className="close"
                                    onClick={() => setShowModal(false)}>
                                    <span aria-hidden="true">&times;</span>
                                </button>
                            </div>
                            <div className="modal-body">
                                {
                                    selectedDocument && selectedDocument.image &&
                                    <img src={selectedDocument.image} alt="Document"
                                        className="img-fluid" />
                                }
                            </div>
                        </div>
                    </div>
                </div>
            )}
        </>
    );
};

export default Documents;
JavaScript
// AddDocument.js

import React, { useState } from 'react';
import 'bootstrap/dist/css/bootstrap.min.css';
import Navbar from '@/app/components/Navbar';
import { toast, ToastContainer } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';

const AddDocument = () => {
    const [documentName, setDocumentName] = useState('');
    const [description, setDescription] = useState('');
    const [image, setImage] = useState('');

    const handleDocumentNameChange = (e) => {
        setDocumentName(e.target.value);
    };

    const handleDescriptionChange = (e) => {
        setDescription(e.target.value);
    };

    const handleImageChange = (e) => {
        const file = e.target.files[0];
        const reader = new FileReader();
        reader.onloadend = () => {
            setImage(reader.result);
        };
        if (file) {
            reader.readAsDataURL(file);
        }
    };

    const handleAddDocument = () => {
        if (!documentName.trim() || !description.trim() || !image) {
            toast.error('Please fill in all fields.');
            return;
        }

        const currentDate = new Date().toLocaleDateString();
        const existingDocuments = JSON.parse(
            localStorage.getItem('documents')) || [];
        const newDocument = {
            id: existingDocuments.length + 1,
            // Use the length of existingDocuments array as the ID
            name: documentName,
            description: description,
            image: image,
            date: currentDate,
        };
        const updatedDocuments = [...existingDocuments, newDocument];
        localStorage.setItem('documents', JSON.stringify(updatedDocuments));
        setDocumentName('');
        setDescription('');
        setImage('');
        toast.success('Document added successfully.');
    };

    return (
        <>
            <Navbar />
            <div className="mb-3 container" style={{ width: '70%' }}>
                <label htmlFor="documentName" className="form-label">
                    Document Name
                </label>
                <input
                    type="text"
                    className="form-control"
                    id="documentName"
                    value={documentName}
                    onChange={handleDocumentNameChange}
                />
                <label htmlFor="description" className="form-label mt-3">
                    Description
                </label>
                <textarea
                    className="form-control"
                    id="description"
                    value={description}
                    onChange={handleDescriptionChange}
                />
                <label htmlFor="image" className="form-label mt-3">
                    Select Image
                </label>
                <input
                    type="file"
                    className="form-control"
                    id="image"
                    onChange={handleImageChange}
                />
                <button className="btn btn-primary mt-3"
                    onClick={handleAddDocument}>
                    Add Document
                </button>
            </div>
            <ToastContainer />
        </>
    );
};

export default AddDocument;

Start your application using the following command:

npm run dev

Output: Naviage to the URL http://localhost:3000:

gfgdoc




Reffered: https://www.geeksforgeeks.org


Project

Related
Simple Chatbot application using Python, GoogleAPIKey Simple Chatbot application using Python, GoogleAPIKey
Environment Protection Website using React Environment Protection Website using React
Can acceptance criteria change during sprint? Can acceptance criteria change during sprint?
Simulating electrostatic fields in 2-dimensions using Python3 Simulating electrostatic fields in 2-dimensions using Python3
Sketchpy in Python Sketchpy in Python

Type:
Geek
Category:
Coding
Sub Category:
Tutorial
Uploaded by:
Admin
Views:
12