Buatlah sequence diagram untuk login. buat dia sequence nya berbeda untuk role mahasiswa, penguji, pembimbing, koordinator, baak. buatlah sequence diagram dengan kondisi alternative, sesuaikan dengan code. buat dengan konsep mvc sesuai code, buat dia cotohnya apa nama controllernya. untuk sequence diagram nya jangan terlalu kompleks agar tidak terlalu panjang, buat dia inti yang penting. buat sequence diagramnya mudah dimengerti, jika ada menggunakan parameter sesuai buat dengan code. lalu untuk sequence buat dia pure dari code jangan ada tambahan di luar code, contohnya mengklik menu ini itu. jadi untuk login misalnya aksinya langsung aja aksi aktor ke view gitu input username dan password gitu. langsung ke aksi yang di code. lalu buat dia konsep nya mvc. jadi yang masuk sebagai object nya itu hanya view, model dan controller. jadi kek storage itu gak termasuk. setelah itu buat lah penjelasan untuk sequence diagramnya dalam bentuk paragraf. bbuat penjelasannya rinci, singkat, dan padat. khusus login ini, dia validasi dilakukan ke api bukan ke database atau model. controller
view @extends('layouts.auth')
@section('content')
@if ($errors->has('login'))
<div class="alert alert-danger">
{{ $errors->first('login') }}
</div>
@endif
<form action="{{route('login')}}" method="POST">
@csrf
<div class="form-group text-left">
<label for="username">Username</label>
<input id="username" type="username" class="form-control @error('username') is-invalid @enderror" name="username" value="{{ old('username') }}" autofocus>
@error('username')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
<div class="form-group text-left">
<label for="password" class="control-label">Password</label>
<input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" autocomplete="current-password">
@error('password')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
<div class="form-group">
<button type="submit" class="btn btn-lg btn-block text-white" style="background-color: #6C46A1; border-radius: 8px;">
Login
</button>
</div>
</form>
@endsection
Berdasarkan kode yang Anda berikan, saya akan membuat sequence diagram untuk sistem login dengan berbagai role menggunakan konsep MVC. Berikut adalah sequence diagram yang menggambarkan alur login untuk setiap role:
Sequence diagram di atas menggambarkan alur login sistem dengan arsitektur MVC yang melibatkan validasi melalui API eksternal. Proses dimulai ketika aktor memasukkan username dan password melalui Login View, kemudian data dikirim ke AuthController melalui POST request ke route /login
.
AuthController melakukan validasi input terlebih dahulu, jika gagal maka akan dikembalikan ke view dengan pesan error. Jika validasi berhasil, controller mengirim request autentikasi ke API eksternal melalui endpoint jwt-api/do-auth
. Apabila autentikasi API gagal, sistem akan menampilkan pesan "Username dan password tidak sesuai".
Ketika autentikasi API berhasil, controller mengambil detail user melalui endpoint library-api/mahasiswa
atau library-api/pegawai
tergantung role user. Setelah mendapat detail user yang valid, sistem menyimpan data user ke dalam session dan melakukan pengecekan role untuk menentukan dashboard tujuan.
Untuk role Mahasiswa, sistem mengecek keberadaan kelompok aktif melalui model KelompokMahasiswa dengan join ke tabel kelompok. Jika mahasiswa belum tergabung dalam kelompok aktif, login akan ditolak. Jika sudah tergabung, data kelompok disimpan ke session dan diarahkan ke dashboard mahasiswa.
Untuk role Dosen, sistem mengecek DosenRole aktif melalui model DosenRole. Jika ditemukan, sistem mengambil semua role_id yang dimiliki dosen tersebut. Berdasarkan role_id, dosen akan diarahkan ke dashboard yang sesuai: koordinator (role_id '1'), penguji (role_id '2' atau '4'), atau pembimbing (role_id '3' atau '5'). Untuk role Staff, sistem langsung mengarahkan ke dashboard BAAK. Jika role tidak valid atau tidak dikenali, sistem akan menampilkan pesan error dan mengembalikan user ke halaman login.
Berdasarkan gambar yang Anda berikan, saya akan membuat sequence diagram dengan format yang serupa menggunakan Mermaid:
Sequence diagram ini menggambarkan alur login sistem berbasis MVC dengan validasi melalui API eksternal. Proses dimulai ketika User memasukkan username dan password melalui view login.blade.php
, kemudian form mengirim request ke method login()
di AuthController
.
Controller melakukan validasi input menggunakan $request->validate()
dengan aturan bahwa username dan password wajib diisi. Jika validasi berhasil, controller membuat HTTP client dan mengirim POST request ke endpoint jwt-api/do-auth
dengan parameter username dan password.
Ketika API mengembalikan $body['result'] == true
, controller memanggil method getUserDetail()
untuk mengambil detail user berdasarkan user_id
, role
, dan token
yang diterima. Setelah mendapat detail user, controller menyimpan data user ke session menggunakan session::put()
dengan key user_id
, role
, token
, name
, dan email
.
Berdasarkan role user, sistem melakukan redirect ke dashboard yang sesuai: role 'Dosen' diarahkan ke dashboard.koordinator
, role 'Mahasiswa' ke dashboard.mahasiswa
, dan role 'Staff' ke dashboard.BAAK
. Jika API mengembalikan $body['result'] == false
, controller akan redirect kembali ke halaman login dengan pesan error "Username dan password tidak sesuai".
Apabila validasi input gagal, controller langsung melakukan redirect dengan error validation tanpa memanggil API. Semua hasil akhir ditampilkan kembali kepada User melalui view, baik berupa redirect ke dashboard maupun pesan error di halaman login.
1. Buatlah sequence diagram untuk mengumpulkan artefak oleh mahasiswa. buatlah sequence diagram dengan kondisi alternative, sesuaikan dengan code. untuk sequence mengelola, pisahkan dia untuk yang menambah, edit, hapus. buat sequence dengan konsep mvc sesuai code, buat dia contohnya apa nama controllernya. jadi di konsep mvc ini, dia cuma boleh controller, model, sama view aja, kalau ada kaitannya ke api boleh api ditambah. tapi selain object2 itu gk usah dibuat. kalau udah menggunakan model jangan lagi digunakan database dan begitu sebaliknya. lalu aktornya harus dicantumkan. lalu jika pake parameter buat parameternya sesuai dengan isi code. jad nanti sequence ini full pure dari code. tidak ada kek aksi mengklik tombol ini dan sebagainya, jadi isi sequence pure code. dia langsung buat aksinya apa contohnya kalau untuk login kan, dia langsung input username dan password, jadi gak ada lagi kek mengakses halaman ini dan sebagainya. buat sequence nya mudah dipahami dan gak usah terlalu kompleks tapi dapat inti alurnya. setelah itu buat lah penjelasan untuk sequence diagramnya dalam bentuk paragraf. buat penjelasannya rinci, singkat, dan padat. humanize agar tidak seperti bahasa mesin tapi tetap cocok untuk ke laporan. controller model <?php namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; class pengumpulan_tugas extends Model { use HasFactory; protected $table = 'pengumpulan_tugas'; protected $fillable = [ 'kelompok_id', 'tugas_id', 'waktu_submit', 'file_path', 'status', 'feedback', 'feedback_pembimbing', 'feedback_penguji' ]; public function Kelompok() { return $this->belongsTo(Kelompok::class,'kelompok_id'); } public function tugas() { return $this->belongsTo(Tugas::class,'tugas_id'); } public function pembimbing(){ return $this->belongsTo(pembimbing::class); } public function penguji(){ return $this->belongsTo(penguji::class); } } view @extends('layouts.main') @section('title', 'Edit File Tugas') @section('content') <section class="section"> <div class="section-body"> <div class="row"> <div class="col-12"> @include('partials.alert') <div class="card"> <div class="card-header d-flex justify-content-between"> <h4>Edit File</h4> <a href="{{ route('artefak.index') }}" class="btn btn-primary">Kembali</a> </div> <div class="card-body"> <form method="POST" action="{{ route('artefak.update', ['id' => Crypt::encrypt($artefak->id)]) }}" enctype="multipart/form-data"> @csrf @method('PUT') <div class="form-group mt-4"> <label for="file_path"><strong>Upload Dokumen</strong></label> <div id="drop-area" class="border p-4 text-center" style="border: 2px dashed #ccc; position: relative; transition: background-color 0.3s ease;" ondragover="handleDragOver(event)" ondragleave="handleDragLeave(event)" ondrop="handleFileDrop(event)"> <!-- Instruksi dan tombol --> <div id="upload-instructions"> <i class="fas fa-upload fa-2x mb-2"></i> <p>Drag Your File Here</p> <p>Or</p> <label class="btn btn-primary"> Select File <input type="file" name="file_path" id="file_path" class="d-none @error('file') is-invalid @enderror" onchange="updateFileName(event)"> </label> </div> <!-- Nama file --> <div id="file-name" class="mt-2 text-muted"> <span>No file selected</span> </div> <!-- Preview --> <div id="file-preview" class="mt-3" style="display: none;"> <div class="dock-preview border rounded p-3 d-inline-block text-center" style="background-color: #f8f9fa;"> <div id="file-type-icon" class="mb-2" style="font-size: 24px;"></div> <img id="file-image-preview" src="" alt="File Preview" style="max-width: 100px; max-height: 100px; display: none; border-radius: 10px;" /> <div id="file-name-preview" class="mt-2 font-weight-bold"></div> </div> </div> </div> @error('file') <div class="invalid-feedback d-block">{{ $message }}</div> @enderror </div> <div class="text-right mt-3"> <button type="submit" class="btn btn-primary">Submit</button> </div> </form> </div> </div> </div> </div> </div> </section> @endsection @push('script') <script> function handleDragOver(event) { event.preventDefault(); document.getElementById('drop-area').style.backgroundColor = '#f8f9fa'; } function handleDragLeave(event) { event.preventDefault(); document.getElementById('drop-area').style.backgroundColor = ''; } function handleFileDrop(event) { event.preventDefault(); document.getElementById('drop-area').style.backgroundColor = ''; const file = event.dataTransfer.files[0]; if (file) { const fileInput = document.getElementById('file'); const dataTransfer = new DataTransfer(); dataTransfer.items.add(file); fileInput.files = dataTransfer.files; showFilePreview(file); } } function updateFileName(event) { const file = event.target.files[0]; if (file) { showFilePreview(file); } } function showFilePreview(file) { // Sembunyikan instruksi awal document.getElementById('upload-instructions').style.display = 'none'; const preview = document.getElementById('file-preview'); const icon = document.getElementById('file-type-icon'); const imgPreview = document.getElementById('file-image-preview'); const fileName = document.getElementById('file-name-preview'); // Tampilkan icon atau preview gambar if (file.type.startsWith('image/')) { const reader = new FileReader(); reader.onload = function (e) { imgPreview.src = e.target.result; imgPreview.style.display = 'block'; }; reader.readAsDataURL(file); icon.textContent = '🖼️'; } else { imgPreview.style.display = 'none'; icon.textContent = '📄'; } fileName.textContent = file.name; preview.style.display = 'block'; } </script> 2. Buatlah sequence diagram untuk mengelola template artefak oleh koordinator pa. buatlah sequence diagram dengan kondisi alternative, sesuaikan dengan code. untuk sequence mengelola, pisahkan dia untuk yang menambah, edit, hapus. buat sequence dengan konsep mvc sesuai code, buat dia contohnya apa nama controllernya. jadi di konsep mvc ini, dia cuma boleh controller, model, sama view aja, kalau ada kaitannya ke api boleh api ditambah. tapi selain object2 itu gk usah dibuat misalnya kek storage sistem dan lainnya gak usah. kalau udah menggunakan model jangan lagi digunakan database dan begitu sebaliknya. lalu aktornya harus dicantumkan. lalu jika pake parameter buat parameternya sesuai dengan isi code. jad nanti sequence ini full pure dari code. tidak ada kek aksi mengklik tombol ini dan sebagainya, jadi isi sequence pure code. dia langsung buat aksinya apa contohnya kalau untuk login kan, dia langsung input username dan password, jadi gak ada lagi kek mengakses halaman ini dan sebagainya. buat sequence nya mudah dipahami dan gak usah terlalu kompleks tapi dapat inti alurnya. setelah itu buat lah penjelasan untuk sequence diagramnya dalam bentuk paragraf. buat penjelasannya rinci, singkat, dan padat. humanize agar tidak seperti bahasa mesin tapi tetap cocok untuk ke laporan. controller model <?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class Tugas extends Model { protected $table = 'tugas'; protected $fillable = [ 'user_id', 'Judul_Tugas', 'Deskripsi_Tugas', 'KPA_id', 'prodi_id', 'TM_id', 'tanggal_pengumpulan', 'file', 'kategori_tugas', 'status', ]; protected $casts = [ 'tanggal_pengumpulan' => 'datetime', ]; public function prodi() { return $this->belongsTo(Prodi::class, 'prodi_id'); } public function tahunMasuk() { return $this->belongsTo(TahunMasuk::class, 'TM_id'); } public function kategoriPA() { return $this->belongsTo(kategoriPA::class, 'KPA_id'); } public function pengumpulan(){ return $this->hasMany(pengumpulan_tugas::class); } public function dosenRoles() { return $this->hasOne(DosenRole::class, 'user_id', 'user_id'); } } view @extends('layouts.main') @section('title', 'List Kelompok') @section('content') <section class="section custom-section"> <div class="section-body"> <div class="row"> <div class="col-12"> <div class="card"> <div class="card-header d-flex justify-content-between"> <h4>List Tugas</h4> <a href="{{ route('tugas.create') }}" class="btn btn-primary"> <i class="nav-icon fas fa-folder-plus"></i> Tambah Tugas </a> </div> <div class="card-body"> @include('partials.alert') <div class="table-responsive"> <table class="table table-striped" id="table-2"> <thead> <tr> <th>No</th> <th>Judul Tugas</th> <th>kategori</th> <th>Status</th> <th>Aksi</th> </tr> </thead> <tbody> @foreach($tugas as $item) <tr> <td>{{ $loop->iteration }}</td> <td>{{ $item->Judul_Tugas }}</td> <td>{{ $item->kategori_tugas }}</td> <td>{{ $item->status }}</td> <td> <div class="d-flex"> <a href="{{route('tugas.show', $item->id)}}" class="btn btn-primary btn-sm"><i class="nav-icon fas fa-eye"></i> Show</a> <a href="{{route('artefak.index.koordinator', $item->id)}}" class="btn btn-primary btn-sm"><i class="nav-icon fas fa-eye"></i> Show Submision</a> <a href="{{ route('tugas.edit', ['id' => Crypt::encrypt($item->id)]) }}" class="btn btn-success btn-sm"><i class="nav-icon fas fa-edit"></i> Edit</a> <form method="POST" action="{{route('tugas.destroy', $item->id)}}"> @csrf @method('delete') <button class="btn btn-danger btn-sm show_confirm" data-toggle="tooltip" title='Delete' style="margin-left: 8px"><i class="nav-icon fas fa-trash-alt"></i> Hapus</button> </form> {{-- <a href="{{route('artefak.index.koordinator')}}" class="btn btn-primary btn-sm"><i class="nav-icon fas fa-eye"></i> Show Tugas</a> --}} </div> </td> </tr> @endforeach </tbody> </table> </div> </div> </div> </div> </div> </div> </div> </section> @endsection @push('script') <script type="text/javascript"> $('.show_confirm').click(function(event) { var form = $(this).closest("form"); var name = $(this).data("name"); event.preventDefault(); swal({ title: `Yakin ingin menghapus data ini?` , text: "Data akan terhapus secara permanen!" , icon: "warning" , buttons: true , dangerMode: true , }) .then((willDelete) => { if (willDelete) { form.submit(); } }); }); </script> @endpush @extends('layouts.main') @section('title', 'Tambah Tugas') @section('content') <section class="section custom-section"> <div class="section-body"> <div class="row"> <div class="col-12"> <div class="card"> <div class="card-header d-flex justify-content-between"> <h4>Tambah Tugas</h4> <a class="btn btn-primary btn-sm" href="{{ route('koordinator.tugas.index') }}">Kembali</a> </div> <div class="card-body"> {{-- Tampilkan Error jika ada --}} @if ($errors->any()) <div class="alert alert-danger alert-dismissible show fade"> <div class="alert-body"> <button class="close" data-dismiss="alert"><span>×</span></button> <ul> @foreach ($errors->all() as $error) <li>{{ $error }}</li> @endforeach </ul> </div> </div> @endif <form method="POST" action="{{ route('tugas.store') }}" enctype="multipart/form-data"> @csrf {{-- input user_id hide --}} <input type="hidden" name="user_id" value="{{ $user_id }}"> {{-- input TA_id hide --}} <input type="hidden" name="TM_id" value="{{ $tahun_masuk->id }}"> {{-- input prodi_id hide --}} <input type="hidden" name="prodi_id" value="{{ $prodi->id }}"> {{-- KPA_id hide --}} <input type="hidden" name="KPA_id" value="{{ $kategoripa->id }}"> <div class="form-group"> <label for="Judul_Tugas">Judul Tugas</label> <input type="text" name="Judul_Tugas" id="Judul_Tugas" class="form-control @error('Judul_Tugas') is-invalid @enderror" placeholder="Masukkan Judul Tugas" value="{{ old('Judul_Tugas') }}"> @error('Judul_Tugas') <div class="invalid-feedback">{{ $message }}</div> @enderror </div> <div class="form-group"> <label for="Deskripsi_Tugas">Deskripsi Tugas</label> <textarea name="Deskripsi_Tugas" id="Deskripsi_Tugas" class="form-control @error('Deskripsi_Tugas') is-invalid @enderror" placeholder="Masukkan Deskripsi Tugas" rows="5">{{ old('Deskripsi_Tugas') }}</textarea> </div> <div class="form-group"> <label for="kategori_tugas">Kategori </label> <select name="kategori_tugas" id="kategori_tugas" class="form-control"> <option value="">--Pilih Kategori Tugas --</option> <option value="Tugas" >Tugas(submitan Progres)</option> <option value="Artefak">Artefak(Submitan Final)</option> <option value="Revisi">Revisi(Submitan Perbaikan)</option> </select> </div> <div class="form-group"> <label for="tanggal_pengumpulan">Batas Pengumpulan</label> <input type="datetime-local" name="tanggal_pengumpulan" id="tanggal_pengumpulan" class="form-control @error('tanggal_pengumpulan') is-invalid @enderror" value="{{ old('tanggal_pengumpulan') ? old('tanggal_pengumpulan') : '' }}"> @error('tanggal_pengumpulan') <div class="invalid-feedback">{{ $message }}</div> @enderror </div> <div class="form-group"> <label for="file">Dokumen (Opsional)</label> <div id="drop-area" class="border p-4 text-center" style="border: 2px dashed #ccc; position: relative; transition: background-color 0.3s ease;" ondragover="handleDragOver(event)" ondragleave="handleDragLeave(event)" ondrop="handleFileDrop(event)"> <!-- Bagian instruksi dan tombol --> <div id="upload-instructions"> <i class="fas fa-upload fa-2x mb-2"></i> <p>Drag Your File Here</p> <p>Or</p> <label class="btn btn-primary"> Select File <input type="file" name="file" id="file" class="d-none @error('file') is-invalid @enderror" onchange="updateFileName(event)"> </label> </div> <!-- Nama file sebelum preview --> <div id="file-name" class="mt-2 text-muted"> <span>No file selected</span> </div> <!-- File Preview (dock style) --> <div id="file-preview" class="mt-3" style="display: none;"> <div class="dock-preview border rounded p-3 d-inline-block text-center" style="background-color: #f8f9fa;"> <div id="file-type-icon" class="mb-2" style="font-size: 24px;"></div> <img id="file-image-preview" src="" alt="File Preview" style="max-width: 100px; max-height: 100px; display: none; border-radius: 10px;" /> <div id="file-name-preview" class="mt-2 font-weight-bold"></div> </div> </div> </div> @error('file') <div class="invalid-feedback d-block">{{ $message }}</div> @enderror </div> {{-- status --}} <div class="form-group"> <select name="status" id="status" class="form-control" hidden> <option value="berlangsung" {{ old('status', 'berlangsung') == 'berlangsung' ? 'selected' : '' }}>Berlangsung</option> </select> </div> <button type="submit" class="btn btn-primary">Tambah</button> </form> </div> </div> </div> </div> </div> </section> @endsection @push('script') <script> function updateFileName(event) { const file = event.target.files[0]; if (file) { showFileDetails(file); } } function handleDragOver(event) { event.preventDefault(); document.getElementById('drop-area').style.backgroundColor = '#f0f8ff'; } function handleDragLeave(event) { event.preventDefault(); document.getElementById('drop-area').style.backgroundColor = ''; } function handleFileDrop(event) { event.preventDefault(); document.getElementById('drop-area').style.backgroundColor = ''; const file = event.dataTransfer.files[0]; if (file) { const fileInput = document.getElementById('file'); const dataTransfer = new DataTransfer(); dataTransfer.items.add(file); fileInput.files = dataTransfer.files; showFileDetails(file); } } function showFileDetails(file) { const uploadInstructions = document.getElementById('upload-instructions'); const fileName = document.getElementById('file-name'); const previewContainer = document.getElementById('file-preview'); const imgPreview = document.getElementById('file-image-preview'); const fileTypeIcon = document.getElementById('file-type-icon'); const fileNamePreview = document.getElementById('file-name-preview'); // Sembunyikan instruksi awal uploadInstructions.style.display = 'none'; fileName.style.display = 'none'; const isImage = file.type.startsWith('image/'); if (isImage) { const reader = new FileReader(); reader.onload = function(e) { imgPreview.src = e.target.result; imgPreview.style.display = 'block'; }; reader.readAsDataURL(file); fileTypeIcon.textContent = '🖼️'; } else { imgPreview.style.display = 'none'; fileTypeIcon.textContent = '📄'; } fileNamePreview.textContent = file.name; previewContainer.style.display = 'block'; } </script> @extends('layouts.main') @section('title', 'Edit Tugas') @section('content') <section class="section"> <div class="section-body"> <div class="row"> <div class="col-12"> @include('partials.alert') <div class="card"> <div class="card-header d-flex justify-content-between"> <h4>Edit Tugas</h4> <a href="{{ route('koordinator.tugas.index') }}" class="btn btn-primary">Kembali</a> </div> <div class="card-body"> <form method="POST" action="{{ route('tugas.update', ['id' => Crypt::encrypt($tugas->id)]) }}" enctype="multipart/form-data"> @csrf @method('PUT') {{-- input user_id hide --}} <input type="hidden" name="user_id" value="{{ $user_id }}"> {{-- input TA_id hide --}} <input type="hidden" name="TM_id" value="{{ $tahun_masuk->id }}"> {{-- input prodi_id hide --}} <input type="hidden" name="prodi_id" value="{{ $prodi->id }}"> {{-- KPA_id hide --}} <input type="hidden" name="KPA_id" value="{{ $kategoripa->id }}"> <div class="form-group"> <label for="Judul_Tugas">Judul Tugas</label> <input type="text" name="Judul_Tugas" id="Judul_Tugas" class="form-control @error('Judul_Tugas') is-invalid @enderror" placeholder="Masukkan Judul Tugas" value="{{ old('Judul_Tugas', $tugas->Judul_Tugas) }}"> @error('Judul_Tugas') <div class="invalid-feedback">{{ $message }}</div> @enderror </div> <div class="mb-3"> <label for="Deskripsi_Tugas" class="form-label">Deskripsi Tugas</label> <textarea name="Deskripsi_Tugas" id="Deskripsi_Tugas" rows="5" class="form-control fs-5 @error('Deskripsi_Tugas') is-invalid @enderror" style="height: 200px;" placeholder="Masukkan Deskripsi">{{ old('Deskripsi_Tugas', $tugas->Deskripsi_Tugas) }}</textarea> @error('Deskripsi_Tugas') <div class="invalid-feedback">{{ $message }}</div> @enderror </div> <div class="form-group"> <label for="tanggal_pengumpulan">Batas Pengumpulan</label> <input type="datetime-local" name="tanggal_pengumpulan" id="tanggal_pengumpulan" class="form-control @error('tanggal_pengumpulan') is-invalid @enderror" value="{{ old('Judul_Tugas', $tugas->tanggal_pengumpulan) }}"> @error('tanggal_pengumpulan') <div class="invalid-feedback">{{ $message }}</div> @enderror </div> @if(old('file', $tugas->file)) <div class="mt-3"> <label>Dokumen Saat Ini:</label> <div class="border rounded p-1 bg-light d-inline-block"> @php $filePath = asset('storage/' . $tugas->file); // atau sesuaikan path file sesuai lokasi penyimpananmu $fileExt = pathinfo($tugas->file, PATHINFO_EXTENSION); @endphp @if(in_array(strtolower($fileExt), ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'])) <img src="{{ $filePath }}" alt="Dokumen Lama" style="max-width: 100px; max-height: 100px; border-radius: 10px;"> @else <a href="{{ $filePath }}" target="_blank">📄{{ basename($tugas->file) }}</a> @endif </div> </div> @endif <div class="form-group"> <label for="file">Ganti Dokumen</label> <div id="drop-area" class="border p-4 text-center" style="border: 2px dashed #ccc; transition: background-color 0.3s ease;" ondragover="handleDragOver(event)" ondragleave="handleDragLeave(event)" ondrop="handleFileDrop(event)" > <!-- Instruksi Awal --> <div id="upload-instructions"> <i class="fas fa-upload fa-2x mb-2"></i> <p>Drag Your File Here</p> <p>Or</p> <label class="btn btn-primary"> Select File <input type="file" name="file" id="file" class="d-none @error('file') is-invalid @enderror" onchange="updateFileName(event)" > </label> </div> <!-- Dock Preview --> <div id="file-preview" class="mt-3" style="display: none;"> <div class="border rounded p-3 bg-light d-inline-block"> <div id="file-type-icon" class="mb-2" style="font-size: 24px;"></div> <img id="file-image-preview" src="" alt="File Preview" style="max-width: 100px; max-height: 100px; display: none; border-radius: 10px;" /> <div id="file-name-preview" class="mt-2 font-weight-bold"></div> </div> </div> </div> @error('file') <div class="invalid-feedback d-block">{{ $message }}</div> @enderror </div> <!-- Status --> <div class="form-group"> <label for="status">Status</label> <select name="status" id="status" class="form-control"> <option value="berlangsung" {{ old('status', $tugas->status) == 'berlangsung' ? 'selected' : '' }}>Berlangsung</option> <option value="selesai" {{ old('status', $tugas->status) == 'selesai' ? 'selected' : '' }}>Selesai</option> </select> </div> <button type="submit" class="btn btn-primary"> <i class="nav-icon fas fa-save"></i> Simpan Perubahan </button> </form> </div> </div> </div> </div> </div> </section> @endsection @push('script') <script> function handleDragOver(event) { event.preventDefault(); document.getElementById('drop-area').style.backgroundColor = '#f8f9fa'; } function handleDragLeave(event) { event.preventDefault(); document.getElementById('drop-area').style.backgroundColor = ''; } function handleFileDrop(event) { event.preventDefault(); document.getElementById('drop-area').style.backgroundColor = ''; const file = event.dataTransfer.files[0]; if (file) { const fileInput = document.getElementById('file'); const dataTransfer = new DataTransfer(); dataTransfer.items.add(file); fileInput.files = dataTransfer.files; showFilePreview(file); } } function updateFileName(event) { const file = event.target.files[0]; if (file) { showFilePreview(file); } } function showFilePreview(file) { // Sembunyikan instruksi awal document.getElementById('upload-instructions').style.display = 'none'; const preview = document.getElementById('file-preview'); const icon = document.getElementById('file-type-icon'); const imgPreview = document.getElementById('file-image-preview'); const fileName = document.getElementById('file-name-preview'); // Tampilkan icon atau preview gambar if (file.type.startsWith('image/')) { const reader = new FileReader(); reader.onload = function (e) { imgPreview.src = e.target.result; imgPreview.style.display = 'block'; }; reader.readAsDataURL(file); icon.textContent = '🖼️'; } else { imgPreview.style.display = 'none'; icon.textContent = '📄'; } fileName.textContent = file.name; preview.style.display = 'block'; } </script> 2. Buatlah sequence diagram untuk mengajukan permintaan bimbingan oleh mahasiswa. buatlah sequence diagram dengan kondisi alternative, sesuaikan dengan code. untuk sequence mengelola, pisahkan dia untuk yang menambah, edit, hapus. buat sequence dengan konsep mvc sesuai code, buat dia contohnya apa nama controllernya. jadi di konsep mvc ini, dia cuma boleh controller, model, sama view aja, kalau ada kaitannya ke api boleh api ditambah. tapi selain object2 itu gk usah dibuat misalnya kek storage sistem dan lainnya gak usah. kalau udah menggunakan model jangan lagi digunakan database dan begitu sebaliknya. lalu aktornya harus dicantumkan. lalu jika pake parameter buat parameternya sesuai dengan isi code. jad nanti sequence ini full pure dari code. tidak ada kek aksi mengklik tombol ini dan sebagainya, jadi isi sequence pure code. dia langsung buat aksinya apa contohnya kalau untuk login kan, dia langsung input username dan password, jadi gak ada lagi kek mengakses halaman ini dan sebagainya. buat sequence nya mudah dipahami dan gak usah terlalu kompleks tapi dapat inti alurnya. setelah itu buat lah penjelasan untuk sequence diagramnya dalam bentuk paragraf. buat penjelasannya rinci, singkat, dan padat. humanize agar tidak seperti bahasa mesin tapi tetap cocok untuk ke laporan. controller model <?php namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; class Bimbingan extends Model { use HasFactory; protected $table = 'request_bimbingan'; // Sesuai nama tabel di database protected $fillable = [ 'kelompok_id', 'user_id', 'keperluan', 'rencana_mulai', 'rencana_selesai', 'ruangan_id', 'status', 'hasil_bimbingan', // Tambahkan field ini ]; // Relasi ke Kelompok public function kelompok() { return $this->belongsTo(Kelompok::class, 'kelompok_id'); } // Relasi ke KartuBimbingan public function kartuBimbingan() { return $this->hasOne(KartuBimbingan::class, 'request_bimbingan_id'); } public function ruangan(){ return $this->belongsTo(Ruangan::class,'ruangan_id'); } public function prodi() { return $this->belongsTo(Prodi::class); } public function kategoriPA() { return $this->belongsTo(kategoriPA::class); } } view @extends('layouts.main') @section('title', 'List Bimbingan') @section('content') <section class="section custom-section"> <div class="section-body"> <div class="row"> <div class="col-12"> <div class="card"> <div class="card-header d-flex justify-content-between"> <h4>List Bimbingan</h4> <a href="{{ route('bimbingan.create') }}" class="btn btn-primary"> <i class="nav-icon fas fa-folder-plus"></i> Request Bimbingan </a> </div> <div class="card-body"> @include('partials.alert') <div class="table-responsive"> <table class="table table-striped" id="table-2"> <thead> <tr> <th>No</th> <th>Nomor Kelompok</th> <th>Keperluan</th> <th>Tanggal Mulai</th> <th>Tanggal Selesai</th> <th>Ruangan</th> <th>Status</th> <th>Aksi</th> </tr> </thead> <tbody> @foreach($bimbingan as $item) <tr> <td>{{ $loop->iteration }}</td> <td>{{ $item->kelompok->nomor_kelompok }}</td> <td>{{ $item->keperluan }}</td> <td>{{ $item->rencana_mulai }}</td> <td>{{ $item->rencana_selesai}}</td> <td>{{ $item->ruangan->ruangan }}</td> <td> <span class="badge @if($item->status == 'disetujui') badge-success @elseif($item->status == 'ditolak') badge-danger @elseif($item->status == 'selesai') badge-info @else badge-warning @endif"> {{ ucfirst($item->status) }} </span> </td> <td> <div class="d-flex"> @if($item->status == 'menunggu') <a href="{{ route('bimbingan.edit', Crypt::encrypt($item->id)) }}" class="btn btn-sm btn-primary mr-2"> <i class="fas fa-edit"></i> Edit </a> <form method="POST" action="{{ route('bimbingan.destroy', $item->id) }}" style="display: inline;"> @csrf @method('DELETE') <button type="submit" class="btn btn-sm btn-danger show_confirm"> <i class="fas fa-trash"></i> Hapus </button> </form> @elseif($item->status == 'selesai') <a href="{{ route('bimbingan.kartu', Crypt::encrypt($item->id)) }}" class="btn btn-success btn-sm mr-2"> <i class="nav-icon fas fa-eye"></i> Kartu bimbingan </a> @endif </div> </td> </tr> @endforeach </tbody> </table> </div> </div> </div> </div> </div> </div> </section> @endsection @push('script') <script type="text/javascript"> $('.show_confirm').click(function(event) { var form = $(this).closest("form"); var name = $(this).data("name"); event.preventDefault(); swal({ title: `Yakin ingin menghapus data ini?` , text: "Data akan terhapus secara permanen!" , icon: "warning" , buttons: true , dangerMode: true , }) .then((willDelete) => { if (willDelete) { form.submit(); } }); }); </script> @endpush @extends('layouts.main') @section('title', 'Tambah Bimbingan') @section('content') <section class="section custom-section"> <div class="section-body"> <div class="row"> <div class="col-12"> <div class="card"> <div class="card-header d-flex justify-content-between"> <h4>Tambah Request Bimbingan</h4> <a class="btn btn-primary btn-sm" href="{{ route('bimbingan.index') }}">Kembali</a> </div> <div class="card-body"> {{-- Tampilkan Error jika ada --}} @if ($errors->any()) <div class="alert alert-danger alert-dismissible show fade"> <div class="alert-body"> <button class="close" data-dismiss="alert"><span>×</span></button> <ul> @foreach ($errors->all() as $error) <li>{{ $error }}</li> @endforeach </ul> </div> </div> @endif <form method="POST" action="{{ route('bimbingan.store')}}" enctype="multipart/form-data"> @csrf {{-- Kelompok_id--}} <div class="form-group"> <input type="hidden" name="kelompok_id" value="{{ $kelompokId }}"> </div> {{-- keperluan --}} <div class="form-group"> <label for="keperluan">Keperluan</label> <input type="text" name="keperluan" id="keperluan" class="form-control" required> </div> {{-- Rencana Bimbingan --}} <div class="form-group"> <label for="rencana_mulai">Rencana Mulai Bimbingan</label> <input type="datetime-local" name="rencana_mulai" id="rencana_mulai" class="form-control @error('rencana_mulai') is-invalid @enderror" value="{{ old('rencana_mulai') ? old('rencana_mulai') : '' }}"> @error('rencana_mulai') <div class="invalid-feedback">{{ $message }}</div> @enderror </div> {{-- Rencana Bimbingan --}} <div class="form-group"> <label for="rencana_selesai">Rencana Selesai Bimbingan</label> <input type="datetime-local" name="rencana_selesai" id="rencana_selesai" class="form-control @error('rencana_selesai') is-invalid @enderror" value="{{ old('rencana_selesai') ? old('rencana_selesai') : '' }}"> @error('rencana_selesai') <div class="invalid-feedback">{{ $message }}</div> @enderror </div> <!-- {{-- Rencana Bimbingan --}} <div class="form-group"> <label for="rencana_mulai">Rencana Mulai Bimbingan</label> <input type="datetime-local" name="rencana_mulai" id="rencana_mulai" class="form-control @error('rencana_mulai') is-invalid @enderror" value="{{ old('rencana_mulai') ? old('rencana_mulai') : '' }}"> @error('rencana_mulai') <div class="invalid-feedback">{{ $message }}</div> @enderror </div> --> {{-- keperluan --}} <div class="form-group"> <label for="ruangan">Ruangan</label> <select name="ruangan_id" id="ruangan_id" class="form-control" required> <option value="">-- Pilih Ruangan --</option> @foreach($ruangan as $item) <option value="{{ $item->id}}" {{ old('ruangan_id') == $item->id ? 'selected' : '' }}> {{ $item->ruangan}} </option> @endforeach </select> </div> {{-- status --}} <div class="form-group"> <input type="hidden" name="status" value="menunggu"> </div> <button type="submit" class="btn btn-primary">Tambah</button> </form> </div> </div> </div> </div> </div> </section> @endsection @extends('layouts.main') @section('title', 'Edit Bimbingan') @section('content') <section class="section custom-section"> <div class="section-body"> <div class="row"> <div class="col-12"> <div class="card"> <div class="card-header"> <h4>Edit Request Bimbingan</h4> </div> <div class="card-body"> @include('partials.alert') <form action="{{ route('bimbingan.update', Crypt::encrypt($bimbingan->id)) }}" method="POST"> @csrf @method('PUT') <div class="form-group"> <label for="keperluan">Keperluan</label> <textarea class="form-control" id="keperluan" name="keperluan" rows="3" required>{{ $bimbingan->keperluan }}</textarea> </div> <div class="form-group"> <label for="ruangan_id">Ruangan</label> <select class="form-control" id="ruangan_id" name="ruangan_id" required> <option value="">Pilih Ruangan</option> @foreach($ruangan as $r) <option value="{{ $r->id }}" {{ $bimbingan->ruangan_id == $r->id ? 'selected' : '' }}> {{ $r->ruangan }} </option> @endforeach </select> </div> <div class="form-group"> <label for="rencana_mulai">Tanggal Mulai</label> <input type="datetime-local" class="form-control" id="rencana_mulai" name="rencana_mulai" value="{{ date('Y-m-d\TH:i', strtotime($bimbingan->rencana_mulai)) }}" required> </div> <div class="form-group"> <label for="rencana_selesai">Tanggal Selesai</label> <input type="datetime-local" class="form-control" id="rencana_selesai" name="rencana_selesai" value="{{ date('Y-m-d\TH:i', strtotime($bimbingan->rencana_selesai)) }}" required> </div> <div class="form-group text-right"> <a href="{{ route('bimbingan.index') }}" class="btn btn-secondary">Batal</a> <button type="submit" class="btn btn-primary">Simpan Perubahan</button> </div> </form> </div> </div> </div> </div> </div> </section> @endsection