Tugas CRUD Tabel Mahasiswa dengan Modal (React + React-Bootstrap)

Persiapan Proyek

1. Buat project baru

npx create-react-app react-crud-modal
cd react-crud-modal
npm install react-bootstrap bootstrap axios

2. Tambahkan Bootstrap ke project

Edit src/index.js:

import 'bootstrap/dist/css/bootstrap.min.css';

3. Struktur folder

src/
├── api.js
├── components/
│   ├── StudentTable.js
│   ├── StudentModal.js
│   └── DeleteModal.js
└── App.js

4. Konfigurasi API (src/api.js)

import axios from 'axios';

const api = axios.create({
  baseURL: 'http://localhost:5000/api/students' // sesuaikan dengan backend kamu
});

export default api;

5. Komponen: StudentTable.js

Menampilkan daftar mahasiswa dan tombol aksi.

import React, { useEffect, useState } from 'react';
import { Table, Button } from 'react-bootstrap';
import api from '../api';

function StudentTable({ onEdit, onDelete, onCreate }) {
  const [students, setStudents] = useState([]);

  const fetchStudents = async () => {
    try {
      const res = await api.get('/');
      setStudents(res.data);
    } catch (err) {
      console.error('Gagal memuat data:', err);
    }
  };

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

  return (
    <div>
      <div className="d-flex justify-content-between align-items-center mb-3">
        <h4>Daftar Mahasiswa</h4>
        <Button variant="primary" onClick={onCreate}>Tambah</Button>
      </div>

      <Table striped bordered hover>
        <thead>
          <tr>
            <th>#</th>
            <th>Nama</th>
            <th>Jurusan</th>
            <th>Usia</th>
            <th>Aksi</th>
          </tr>
        </thead>
        <tbody>
          {students.map((s, idx) => (
            <tr key={s.id}>
              <td>{idx + 1}</td>
              <td>{s.name}</td>
              <td>{s.major}</td>
              <td>{s.age}</td>
              <td>
                <Button
                  variant="warning"
                  size="sm"
                  className="me-2"
                  onClick={() => onEdit(s)}
                >
                  Edit
                </Button>
                <Button
                  variant="danger"
                  size="sm"
                  onClick={() => onDelete(s)}
                >
                  Hapus
                </Button>
              </td>
            </tr>
          ))}
        </tbody>
      </Table>
    </div>
  );
}

export default StudentTable;

6. Komponen: StudentModal.js

Modal untuk tambah & edit data mahasiswa.

import React, { useState, useEffect } from 'react';
import { Modal, Button, Form } from 'react-bootstrap';
import api from '../api';

function StudentModal({ show, handleClose, refresh, selected }) {
  const [form, setForm] = useState({ name: '', major: '', age: '' });

  useEffect(() => {
    if (selected) setForm(selected);
    else setForm({ name: '', major: '', age: '' });
  }, [selected]);

  const handleChange = (e) => {
    setForm({ ...form, [e.target.name]: e.target.value });
  };

  const handleSubmit = async (e) => {
    e.preventDefault();
    try {
      if (form.id) {
        await api.put(`/${form.id}`, form);
      } else {
        await api.post('/', form);
      }
      refresh();
      handleClose();
    } catch (err) {
      console.error('Gagal menyimpan data:', err);
    }
  };

  return (
    <Modal show={show} onHide={handleClose} centered>
      <Modal.Header closeButton>
        <Modal.Title>{form.id ? 'Edit Mahasiswa' : 'Tambah Mahasiswa'}</Modal.Title>
      </Modal.Header>
      <Modal.Body>
        <Form onSubmit={handleSubmit}>
          <Form.Group className="mb-3">
            <Form.Label>Nama</Form.Label>
            <Form.Control
              name="name"
              value={form.name}
              onChange={handleChange}
              required
            />
          </Form.Group>
          <Form.Group className="mb-3">
            <Form.Label>Jurusan</Form.Label>
            <Form.Control
              name="major"
              value={form.major}
              onChange={handleChange}
              required
            />
          </Form.Group>
          <Form.Group className="mb-3">
            <Form.Label>Usia</Form.Label>
            <Form.Control
              type="number"
              name="age"
              value={form.age}
              onChange={handleChange}
              required
            />
          </Form.Group>
          <div className="text-end">
            <Button variant="secondary" onClick={handleClose} className="me-2">
              Batal
            </Button>
            <Button variant="primary" type="submit">
              Simpan
            </Button>
          </div>
        </Form>
      </Modal.Body>
    </Modal>
  );
}

export default StudentModal;

7. Komponen: DeleteModal.js

Modal konfirmasi untuk menghapus data.

import React from 'react';
import { Modal, Button } from 'react-bootstrap';
import api from '../api';

function DeleteModal({ show, handleClose, refresh, selected }) {
  const handleDelete = async () => {
    try {
      await api.delete(`/${selected.id}`);
      refresh();
      handleClose();
    } catch (err) {
      console.error('Gagal menghapus data:', err);
    }
  };

  return (
    <Modal show={show} onHide={handleClose} centered>
      <Modal.Header closeButton>
        <Modal.Title>Konfirmasi Hapus</Modal.Title>
      </Modal.Header>
      <Modal.Body>
        <p>
          Apakah kamu yakin ingin menghapus mahasiswa <strong>{selected?.name}</strong>?
        </p>
      </Modal.Body>
      <Modal.Footer>
        <Button variant="secondary" onClick={handleClose}>
          Batal
        </Button>
        <Button variant="danger" onClick={handleDelete}>
          Hapus
        </Button>
      </Modal.Footer>
    </Modal>
  );
}

export default DeleteModal;

8. File Utama: App.js

import React, { useState } from 'react';
import { Container } from 'react-bootstrap';
import StudentTable from './components/StudentTable';
import StudentModal from './components/StudentModal';
import DeleteModal from './components/DeleteModal';

function App() {
  const [showForm, setShowForm] = useState(false);
  const [showDelete, setShowDelete] = useState(false);
  const [selected, setSelected] = useState(null);
  const [refreshFlag, setRefreshFlag] = useState(false);

  const refresh = () => setRefreshFlag(!refreshFlag);

  const handleCreate = () => {
    setSelected(null);
    setShowForm(true);
  };

  const handleEdit = (student) => {
    setSelected(student);
    setShowForm(true);
  };

  const handleDelete = (student) => {
    setSelected(student);
    setShowDelete(true);
  };

  return (
    <Container className="py-4">
      <h1 className="mb-4 text-center">CRUD Mahasiswa (Modal Version)</h1>

      <StudentTable
        key={refreshFlag}
        onCreate={handleCreate}
        onEdit={handleEdit}
        onDelete={handleDelete}
      />

      <StudentModal
        show={showForm}
        handleClose={() => setShowForm(false)}
        refresh={refresh}
        selected={selected}
      />

      <DeleteModal
        show={showDelete}
        handleClose={() => setShowDelete(false)}
        refresh={refresh}
        selected={selected}
      />
    </Container>
  );
}

export default App;

9. Kriteria Penilaian

Aspek
Deskripsi

CRUD Berfungsi

Tambah, Edit, dan Hapus berjalan normal

Modal Interaktif

Semua aksi menggunakan modal, tidak halaman baru

Integrasi API

Data tersinkron dengan backend

React-Bootstrap

Menggunakan komponen Table, Modal, Form, Button

Desain Rapi

Layout bersih dan mudah digunakan

Kerapian Kode

Struktur file dan naming convention sesuai standar

Last updated