update revisi

This commit is contained in:
ghozahimma65 2026-05-09 13:44:30 +07:00
parent 6e5f120cbd
commit fe34628f50
43 changed files with 2670 additions and 761 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

BIN
app/Http/Controllers.zip Normal file

Binary file not shown.

View File

@ -73,20 +73,39 @@ public function update(Request $request, $id)
// 1. Validasi
$request->validate([
'nama_guru' => 'required|string|max:255', // Harus nama_guru
'email' => 'required|email',
'nama_guru' => 'required|string|max:255',
'email' => 'required|email|unique:users,email,' . $guru->user_id,
'password' => 'nullable|min:6',
'no_hp' => 'nullable|string',
'jenis_guru' => 'required|string',
'nip' => 'nullable|string',
'alamat' => 'nullable|string',
]);
// 2. Update Tabel Guru LANGSUNG
// Kita abaikan tabel user dulu karena user_id kamu masih NULL
$guru->update([
'nama_guru' => $request->nama_guru, // Masukkan ke kolom nama_guru
DB::transaction(function () use ($request, $guru) {
// Update User Login (jika ada)
if ($guru->user) {
$userData = [
'name' => $request->nama_guru,
'email' => $request->email,
];
if ($request->filled('password')) {
$userData['password'] = Hash::make($request->password);
}
$guru->user->update($userData);
}
// Update Tabel Guru LANGSUNG
$guru->update([
'nama_guru' => $request->nama_guru,
'no_hp' => $request->no_hp,
'jenis_guru' => $request->jenis_guru,
'nip' => $request->nip,
'alamat' => $request->alamat,
]);
});
return redirect()->route('guru.index')->with('success', 'Data Guru berhasil diperbarui!');
}

View File

@ -3,6 +3,7 @@
use App\Http\Controllers\Controller;
use App\Models\Pengumuman;
use App\Models\User;
use Illuminate\Http\Request;
class PengumumanController extends Controller
@ -20,6 +21,7 @@ public function create()
public function store(Request $request)
{
// 1. Validasi Input
$request->validate([
'judul' => 'required|string|max:255',
'isi' => 'required|string',
@ -28,9 +30,24 @@ public function store(Request $request)
'status' => 'boolean',
]);
Pengumuman::create($request->all());
// 2. Simpan Pengumuman ke Database
$pengumuman = Pengumuman::create($request->all());
return redirect()->route('pengumuman.index')->with('success', 'Pengumuman berhasil ditambahkan.');
// 3. Ambil semua FCM token user yang tidak null (guru & wali murid)
$tokens = User::whereNotNull('fcm_token')->pluck('fcm_token')->toArray();
// 4. Trigger Broadcast Notifikasi FCM
if (count($tokens) > 0) {
$notifTitle = "Pengumuman Baru: " . $pengumuman->judul;
$notifBody = "Ada pengumuman baru dari sekolah, yuk cek sekarang!";
// Panggil method dari Controller dasar
$this->sendFCMNotification($notifTitle, $notifBody, $tokens);
}
// 5. Redirect dengan pesan sukses
return redirect()->route('pengumuman.index')
->with('success', 'Pengumuman berhasil ditambahkan dan notifikasi telah dikirim.');
}
public function edit(Pengumuman $pengumuman)

View File

@ -67,7 +67,7 @@ public function update(Request $request, $id)
$siswa = Siswa::findOrFail($id);
$request->validate([
'nis' => 'required|unique:siswas,nis,'.$id,
'nis' => 'required|unique:siswas,nis,' . $id,
'nisn' => 'nullable|string',
'nama_siswa' => 'required|string|max:255',
'tempat_lahir' => 'required|string',

View File

@ -21,8 +21,8 @@ public function index()
public function create()
{
// PERBAIKAN DI SINI JUGA
return view('admin.wali.create');
$zonas = \App\Models\MasterZona::orderBy('kategori', 'desc')->get()->groupBy('kategori');
return view('admin.wali.create', compact('zonas'));
}
public function store(Request $request)
@ -51,6 +51,7 @@ public function store(Request $request)
'no_hp' => $request->no_hp,
'alamat' => $request->alamat,
'pekerjaan' => $request->pekerjaan,
'master_zona_id' => $request->master_zona_id,
]);
});
@ -60,7 +61,8 @@ public function store(Request $request)
public function edit($id)
{
$data = WaliMurid::with('user')->findOrFail($id);
return view('admin.wali.edit', compact('data'));
$zonas = \App\Models\MasterZona::orderBy('kategori', 'desc')->get()->groupBy('kategori');
return view('admin.wali.edit', compact('data', 'zonas'));
}
public function update(Request $request, $id)
@ -70,6 +72,7 @@ public function update(Request $request, $id)
$request->validate([
'nama_wali' => 'required',
'email' => 'required|email|unique:users,email,' . $wali->user_id,
'password' => 'nullable|min:6',
'no_hp' => 'required',
]);
@ -77,10 +80,16 @@ public function update(Request $request, $id)
// 1. Update User Login
if ($wali->user) {
$wali->user->update([
$userData = [
'name' => $request->nama_wali,
'email' => $request->email,
]);
];
if ($request->filled('password')) {
$userData['password'] = Hash::make($request->password);
}
$wali->user->update($userData);
}
// 2. Update Profil Wali
@ -88,6 +97,7 @@ public function update(Request $request, $id)
'nama_wali' => $request->nama_wali,
'no_hp' => $request->no_hp,
'alamat' => $request->alamat,
'master_zona_id' => $request->master_zona_id,
// 'pekerjaan' => $request->pekerjaan, // Form belum ada input pekerjaan
]);
});
@ -99,7 +109,7 @@ public function destroy($id)
{
$wali = WaliMurid::findOrFail($id);
if($wali->user) {
if ($wali->user) {
$wali->user->delete();
} else {
$wali->delete();

View File

@ -42,4 +42,25 @@ public function logout()
Auth::logout();
return response()->json(['message' => 'Berhasil Logout']);
}
public function updateFcmToken(Request $request)
{
$request->validate([
'fcm_token' => 'required|string'
]);
$user = Auth::user();
if ($user) {
$user->update(['fcm_token' => $request->fcm_token]);
return response()->json([
'success' => true,
'message' => 'FCM Token updated successfully'
], 200);
}
return response()->json([
'success' => false,
'message' => 'Unauthenticated'
], 401);
}
}

View File

@ -212,9 +212,28 @@ public function scanJemput(Request $request)
'qr_code' => 'required',
]);
$qrCodeData = $request->qr_code;
$parts = explode('_', $qrCodeData);
$idSiswa = $parts[0];
if (count($parts) > 1) {
$qrDate = $parts[1];
if ($qrDate !== date('Y-m-d')) {
return response()->json([
'success' => false,
'message' => 'QR Code Kadaluarsa! Harap gunakan QR hari ini.'
], 400);
}
} else {
return response()->json([
'success' => false,
'message' => 'Format QR Code tidak valid atau Kadaluarsa!'
], 400);
}
// Cari siswa berdasarkan qr_code (Biasanya NIS atau ID Siswa)
$siswa = Siswa::where('nis', $request->qr_code)
->orWhere('id', $request->qr_code)
$siswa = Siswa::where('nis', $idSiswa)
->orWhere('id', $idSiswa)
->first();
if (!$siswa) {
@ -224,18 +243,30 @@ public function scanJemput(Request $request)
], 404);
}
// Catat Penjemputan
// Kita bisa atur default nama penjemput "Orang Tua/Wali"
// Cek request untuk nama penjemput dan status
$statusPenjemput = $request->status_penjemput ?? 'Orang Tua / Wali';
Penjemputan::create([
'siswa_id' => $siswa->id,
'nama_penjemput' => 'Orang Tua / Wali',
'status_hubungan' => 'Orang Tua',
'nama_penjemput' => $statusPenjemput,
'status_hubungan' => $statusPenjemput == 'Orang Tua' ? 'Orang Tua' : 'Diwakilkan',
'waktu_jemput' => now(),
]);
// --- TRIGGER FCM NOTIFICATION KE WALI MURID ---
if ($siswa->waliMurid && $siswa->waliMurid->user && $siswa->waliMurid->user->fcm_token) {
$token = $siswa->waliMurid->user->fcm_token;
$namaAnak = $siswa->nama_siswa ?? $siswa->nama_lengkap ?? 'Ananda';
$this->sendFCMNotification(
"Penjemputan Berhasil",
"Ananda {$namaAnak} telah berhasil dijemput dan diverifikasi oleh Guru.",
[$token]
);
}
return response()->json([
'success' => true,
'message' => 'Berhasil mencatat penjemputan untuk ' . $siswa->nama_lengkap
'message' => 'Berhasil mencatat penjemputan untuk ' . ($siswa->nama_siswa ?? $siswa->nama_lengkap)
]);
}
}

View File

@ -0,0 +1,45 @@
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\MasterZona;
use App\Models\Siswa;
class HomeVisitController extends Controller
{
/**
* Endpoint 1: Mendapatkan daftar zona, dikelompokkan berdasarkan kategori
*/
public function getZonasi()
{
// Mengambil semua data zona dan mengelompokkan berdasarkan field 'kategori'
$zonas = MasterZona::orderBy('kategori', 'desc')->get()->groupBy('kategori');
return response()->json([
'success' => true,
'message' => 'Berhasil mengambil data zonasi',
'data' => $zonas
]);
}
/**
* Endpoint 2: Mendapatkan daftar siswa berdasarkan zona_id
*/
public function getSiswaByZona($zona_id)
{
// Query Siswa yang berelasi dengan wali_murid, dimana wali_murid.master_zona_id = $zona_id
$siswas = Siswa::with('wali_murid')
->whereHas('wali_murid', function ($query) use ($zona_id) {
$query->where('master_zona_id', $zona_id);
})
->get();
return response()->json([
'success' => true,
'message' => 'Berhasil mengambil data siswa di zona tersebut',
'data' => $siswas
]);
}
}

View File

@ -40,8 +40,14 @@ public function getDashboard(Request $request)
// 3. Pengumuman Aktif Terbaru
$pengumuman = Pengumuman::where('status', true)
->where('tanggal_mulai', '<=', now())
->where('tanggal_selesai', '>=', now())
->where(function ($query) {
$query->whereNull('tanggal_mulai')
->orWhereDate('tanggal_mulai', '<=', now());
})
->where(function ($query) {
$query->whereNull('tanggal_selesai')
->orWhereDate('tanggal_selesai', '>=', now());
})
->latest()
->first();
@ -76,9 +82,21 @@ public function getDashboard(Request $request)
// Murni kalkulasi berdasarkan data riil, 0 jika kosong
$percentage = $count > 0 ? round($totalScore / $count) : 0;
$predikat = "Perlu Bimbingan";
if ($percentage >= 76) $predikat = "Sangat Baik";
elseif ($percentage >= 51) $predikat = "Baik";
elseif ($percentage >= 26) $predikat = "Cukup";
$narasi = null;
if ($count > 0) {
$namaAnak = $siswa->nama_siswa ?? $siswa->nama_lengkap ?? 'Ananda';
$narasi = "Ananda {$namaAnak} telah menunjukkan perkembangan yang {$predikat} pada aspek {$aspek} dengan capaian {$percentage}%.";
}
$progressPerkembangan[] = [
'aspek' => $aspek,
'nilai' => $percentage
'nilai' => $percentage,
'narasi' => $narasi
];
}

View File

@ -2,7 +2,62 @@
namespace App\Http\Controllers;
use Kreait\Firebase\Factory;
use Kreait\Firebase\Messaging\CloudMessage;
use Kreait\Firebase\Messaging\Notification;
use Kreait\Firebase\Messaging\AndroidConfig;
abstract class Controller
{
//
public function sendFCMNotification($title, $body, $tokens)
{
$credentialsFilePath = storage_path('firebase-auth.json');
if (!file_exists($credentialsFilePath)) {
\Log::error("FCM Service Account file not found at: " . $credentialsFilePath);
return false;
}
try {
$factory = (new Factory)->withServiceAccount($credentialsFilePath);
$messaging = $factory->createMessaging();
$responses = [];
foreach ($tokens as $fcmToken) {
$message = CloudMessage::withTarget('token', $fcmToken)
->withNotification(Notification::create($title, $body))
->withAndroidConfig(AndroidConfig::fromArray([
'priority' => 'high',
'notification' => [
'channel_id' => 'paud_notif_channel',
'sound' => 'default'
]
]));
try {
$result = $messaging->send($message);
$responses[] = $result;
\Log::info("FCM Response for token {$fcmToken}: Sukses via Kreait. Result: " . json_encode($result));
} catch (\Kreait\Firebase\Exception\MessagingException $e) {
\Log::error("Kreait FCM Error for token {$fcmToken}: " . $e->getMessage());
// ERROR HANDLING TEGAS SEPERTI SEBELUMNYA
dd([
'STATUS' => 'ERROR_DITOLAK_GOOGLE',
'FCM_ERROR' => $e->getMessage(),
'FCM_ERROR_DETAILS' => $e->errors()
]);
}
}
return $responses;
} catch (\Exception $e) {
\Log::error("FCM System Error: " . $e->getMessage());
dd([
'STATUS' => 'FATAL_SYSTEM_ERROR',
'ERROR' => $e->getMessage()
]);
return false;
}
}
}

11
app/Models/MasterZona.php Normal file
View File

@ -0,0 +1,11 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class MasterZona extends Model
{
protected $table = 'master_zonas';
protected $fillable = ['nama_zona', 'kategori'];
}

View File

@ -24,4 +24,9 @@ public function siswas()
{
return $this->hasMany(Siswa::class, 'wali_id');
}
public function zona()
{
return $this->belongsTo(MasterZona::class, 'master_zona_id');
}
}

View File

@ -8,6 +8,8 @@
"require": {
"php": "^8.2",
"doctrine/dbal": "^4.4",
"google/apiclient": "^2.19",
"kreait/firebase-php": "^7.24",
"laravel/framework": "^12.0",
"laravel/sanctum": "^4.0",
"laravel/tinker": "^2.10.1",

1374
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('users', function (Blueprint $table) {
$table->text('fcm_token')->nullable()->after('remember_token');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('fcm_token');
});
}
};

View File

@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('master_zonas', function (Blueprint $table) {
$table->id();
$table->string('nama_zona');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('master_zonas');
}
};

View File

@ -0,0 +1,29 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('wali_murids', function (Blueprint $table) {
$table->foreignId('master_zona_id')->nullable()->constrained('master_zonas')->nullOnDelete();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('wali_murids', function (Blueprint $table) {
$table->dropForeign(['master_zona_id']);
$table->dropColumn('master_zona_id');
});
}
};

View File

@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('master_zonas', function (Blueprint $table) {
$table->string('kategori')->nullable();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('master_zonas', function (Blueprint $table) {
$table->dropColumn('kategori');
});
}
};

View File

@ -0,0 +1,35 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
class MasterZonaSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
\Illuminate\Support\Facades\Schema::disableForeignKeyConstraints();
\App\Models\MasterZona::truncate();
\Illuminate\Support\Facades\Schema::enableForeignKeyConstraints();
$kotaMadiun = [
'Kartoharjo', 'Manguharjo', 'Taman'
];
$kabupatenMadiun = [
'Balerejo', 'Dagangan', 'Dolopo', 'Geger', 'Gemarang', 'Jiwan', 'Kare', 'Kebonsari', 'Madiun', 'Mejayan', 'Pilangkenceng', 'Saradan', 'Sawahan', 'Wonoasri', 'Wungu'
];
foreach ($kotaMadiun as $zona) {
\App\Models\MasterZona::create(['nama_zona' => $zona, 'kategori' => 'Kota Madiun']);
}
foreach ($kabupatenMadiun as $zona) {
\App\Models\MasterZona::create(['nama_zona' => $zona, 'kategori' => 'Kabupaten Madiun']);
}
}
}

BIN
resources/views.zip Normal file

Binary file not shown.

View File

@ -1,10 +1,11 @@
@extends('layouts.app')
@section('content')
<div class="bg-white p-6 rounded-lg shadow-md">
<div class="bg-white p-6 rounded-lg shadow-md">
<div class="flex justify-between items-center mb-4">
<h1 class="text-xl font-semibold text-gray-700">🔐 Daftar Akun</h1>
<a href="{{ route('akun.create') }}" class="bg-green-600 text-white px-4 py-2 rounded hover:bg-green-700">+ Tambah Akun</a>
<a href="{{ route('akun.create') }}" class="bg-green-600 text-white px-4 py-2 rounded hover:bg-green-700">+
Tambah Akun</a>
</div>
@if(session('success'))
@ -44,13 +45,10 @@
{{-- Kolom password (disembunyikan tapi bisa dilihat) --}}
<td class="p-3 border text-center">
<div class="relative inline-block">
<input
type="password"
value="123456"
readonly
class="border rounded-lg px-2 py-1 text-center bg-gray-100 text-sm w-24 password-field"
>
<button type="button" class="absolute right-2 top-1/2 transform -translate-y-1/2 text-gray-500 toggle-password">
<input type="password" value="123456" readonly
class="border rounded-lg px-2 py-1 text-center bg-gray-100 text-sm w-24 password-field">
<button type="button"
class="absolute right-2 top-1/2 transform -translate-y-1/2 text-gray-500 toggle-password">
<i class="fas fa-eye"></i>
</button>
</div>
@ -58,14 +56,17 @@ class="border rounded-lg px-2 py-1 text-center bg-gray-100 text-sm w-24 password
{{-- Tombol Aksi --}}
<td class="p-3 border text-center space-x-2">
<a href="{{ route('akun.edit', $user->id) }}" class="bg-blue-500 text-white px-3 py-1 rounded hover:bg-blue-600">Edit</a>
<a href="{{ route('akun.edit', $user->id) }}"
class="bg-blue-500 text-white px-3 py-1 rounded hover:bg-blue-600">Edit</a>
<form action="{{ route('akun.reset', $user->id) }}" method="POST" class="inline">
@csrf
<button type="submit" class="bg-yellow-500 text-white px-3 py-1 rounded hover:bg-yellow-600">Reset</button>
<button type="submit"
class="bg-yellow-500 text-white px-3 py-1 rounded hover:bg-yellow-600">Reset</button>
</form>
<form action="{{ route('akun.destroy', $user->id) }}" method="POST" onsubmit="return confirm('Yakin mau hapus akun ini?')" class="inline">
<form action="{{ route('akun.destroy', $user->id) }}" method="POST"
onsubmit="return confirm('Yakin mau hapus akun ini?')" class="inline">
@csrf
@method('DELETE')
<button class="bg-red-500 text-white px-3 py-1 rounded hover:bg-red-600">Hapus</button>
@ -79,12 +80,12 @@ class="border rounded-lg px-2 py-1 text-center bg-gray-100 text-sm w-24 password
@endforelse
</tbody>
</table>
</div>
</div>
{{-- Script show/hide password --}}
<script>
document.querySelectorAll('.toggle-password').forEach(btn => {
btn.addEventListener('click', function() {
{{-- Script show/hide password --}}
<script>
document.querySelectorAll('.toggle-password').forEach(btn => {
btn.addEventListener('click', function () {
const input = this.closest('div').querySelector('.password-field');
const icon = this.querySelector('i');
if (input.type === 'password') {
@ -97,6 +98,6 @@ class="border rounded-lg px-2 py-1 text-center bg-gray-100 text-sm w-24 password
icon.classList.add('fa-eye');
}
});
});
</script>
});
</script>
@endsection

View File

@ -1,19 +1,24 @@
@extends('layouts.app')
@section('content')
<div class="bg-white shadow-md rounded-2xl border border-[#e1f0e8] overflow-hidden">
<div class="bg-white shadow-md rounded-2xl border border-[#e1f0e8] overflow-hidden">
<!-- Header Section -->
<div class="flex flex-col md:flex-row justify-between items-start md:items-center bg-gradient-to-br from-green-600 to-teal-700 p-8 shadow-inner relative overflow-hidden">
<div
class="flex flex-col md:flex-row justify-between items-start md:items-center bg-gradient-to-br from-green-600 to-teal-700 p-8 shadow-inner relative overflow-hidden">
<!-- Decorative inner pattern -->
<div class="absolute inset-0 bg-[url('https://www.transparenttextures.com/patterns/cubes.png')] opacity-10 mix-blend-overlay"></div>
<div
class="absolute inset-0 bg-[url('https://www.transparenttextures.com/patterns/cubes.png')] opacity-10 mix-blend-overlay">
</div>
<div class="relative z-10">
<h1 class="text-2xl font-extrabold text-white flex items-center drop-shadow">
<span class="bg-white/20 text-white p-2.5 rounded-xl mr-4 backdrop-blur-md"><i class="fas fa-chalkboard-teacher"></i></span> Data Guru
<span class="bg-white/20 text-white p-2.5 rounded-xl mr-4 backdrop-blur-md"><i
class="fas fa-chalkboard-teacher"></i></span> Data Guru
</h1>
<p class="text-green-50 mt-2 ml-14 font-medium drop-shadow-sm">Kelola informasi tenaga pengajar PAUD.</p>
</div>
<div class="mt-6 md:mt-0 relative z-10">
<a href="{{ route('guru.create') }}" class="inline-flex items-center gap-2 bg-white text-green-700 px-6 py-3 rounded-xl hover:bg-green-50 font-bold text-sm shadow-lg transition-all hover:-translate-y-1">
<a href="{{ route('guru.create') }}"
class="inline-flex items-center gap-2 bg-white text-green-700 px-6 py-3 rounded-xl hover:bg-green-50 font-bold text-sm shadow-lg transition-all hover:-translate-y-1">
<i class="fas fa-plus"></i> Tambah Guru
</a>
</div>
@ -42,16 +47,21 @@
<td class="p-2">
{{-- Logic tampilan badge --}}
@if($guru->jenis_guru == 'guru_kelas')
<span class="bg-blue-100 text-blue-800 text-xs font-semibold mr-2 px-2.5 py-0.5 rounded">Guru Kelas</span>
<span
class="bg-blue-100 text-blue-800 text-xs font-semibold mr-2 px-2.5 py-0.5 rounded">Guru
Kelas</span>
@elseif($guru->jenis_guru == 'shadow_abk')
<span class="bg-yellow-100 text-yellow-800 text-xs font-semibold mr-2 px-2.5 py-0.5 rounded">Shadow ABK</span>
<span
class="bg-yellow-100 text-yellow-800 text-xs font-semibold mr-2 px-2.5 py-0.5 rounded">Shadow
ABK</span>
@else
-
@endif
</td>
<td class="p-2 space-x-2">
<a href="{{ route('guru.edit', $guru->id) }}" class="text-blue-500 hover:underline">Edit</a>
<form action="{{ route('guru.destroy', $guru->id) }}" method="POST" class="inline" onsubmit="return confirm('Yakin hapus data ini?');">
<form action="{{ route('guru.destroy', $guru->id) }}" method="POST" class="inline"
onsubmit="return confirm('Yakin hapus data ini?');">
@csrf
@method('DELETE')
<button type="submit" class="text-red-500 hover:underline">Hapus</button>
@ -67,5 +77,5 @@
</table>
</div>
</div>
</div>
</div>
@endsection

View File

@ -1,19 +1,25 @@
@extends('layouts.app')
@section('content')
<div class="bg-white shadow-md rounded-2xl border border-[#e1f0e8] overflow-hidden">
<div class="bg-white shadow-md rounded-2xl border border-[#e1f0e8] overflow-hidden">
<!-- Header Section -->
<div class="flex flex-col md:flex-row justify-between items-start md:items-center bg-gradient-to-br from-green-600 to-teal-700 p-8 shadow-inner relative overflow-hidden">
<div
class="flex flex-col md:flex-row justify-between items-start md:items-center bg-gradient-to-br from-green-600 to-teal-700 p-8 shadow-inner relative overflow-hidden">
<!-- Decorative inner pattern -->
<div class="absolute inset-0 bg-[url('https://www.transparenttextures.com/patterns/cubes.png')] opacity-10 mix-blend-overlay"></div>
<div
class="absolute inset-0 bg-[url('https://www.transparenttextures.com/patterns/cubes.png')] opacity-10 mix-blend-overlay">
</div>
<div class="relative z-10">
<h1 class="text-2xl font-extrabold text-white flex items-center drop-shadow">
<span class="bg-white/20 text-white p-2.5 rounded-xl mr-4 backdrop-blur-md"><i class="fas fa-bullhorn"></i></span> Menu Pengumuman
<span class="bg-white/20 text-white p-2.5 rounded-xl mr-4 backdrop-blur-md"><i
class="fas fa-bullhorn"></i></span> Menu Pengumuman
</h1>
<p class="text-green-50 mt-2 ml-14 font-medium drop-shadow-sm">Kelola informasi dan pengumuman untuk seluruh pihak.</p>
<p class="text-green-50 mt-2 ml-14 font-medium drop-shadow-sm">Kelola informasi dan pengumuman untuk seluruh
pihak.</p>
</div>
<div class="mt-6 md:mt-0 relative z-10">
<a href="{{ route('pengumuman.create') }}" class="inline-flex items-center gap-2 bg-white text-green-700 px-6 py-3 rounded-xl hover:bg-green-50 font-bold text-sm shadow-lg transition-all hover:-translate-y-1">
<a href="{{ route('pengumuman.create') }}"
class="inline-flex items-center gap-2 bg-white text-green-700 px-6 py-3 rounded-xl hover:bg-green-50 font-bold text-sm shadow-lg transition-all hover:-translate-y-1">
<i class="fas fa-plus"></i> Tambah Pengumuman
</a>
</div>
@ -34,19 +40,22 @@
<tbody>
@foreach ($pengumuman as $i => $p)
<tr class="border-b hover:bg-gray-50">
<td class="p-2">{{ $i+1 }}</td>
<td class="p-2">{{ $i + 1 }}</td>
<td class="p-2 font-semibold">{{ $p->judul }}</td>
<td class="p-2">
{{ $p->tanggal_mulai }} - {{ $p->tanggal_selesai }}
</td>
<td class="p-2">
<span class="px-2 py-1 rounded text-white {{ $p->status ? 'bg-green-500' : 'bg-gray-400' }}">
<span
class="px-2 py-1 rounded text-white {{ $p->status ? 'bg-green-500' : 'bg-gray-400' }}">
{{ $p->status ? 'Aktif' : 'Nonaktif' }}
</span>
</td>
<td class="p-2 flex gap-2">
<a href="{{ route('pengumuman.edit', $p->id) }}" class="bg-blue-500 text-white px-3 py-1 rounded hover:bg-blue-600">Edit</a>
<form action="{{ route('pengumuman.destroy', $p->id) }}" method="POST" onsubmit="return confirm('Yakin hapus?')">
<a href="{{ route('pengumuman.edit', $p->id) }}"
class="bg-blue-500 text-white px-3 py-1 rounded hover:bg-blue-600">Edit</a>
<form action="{{ route('pengumuman.destroy', $p->id) }}" method="POST"
onsubmit="return confirm('Yakin hapus?')">
@csrf
@method('DELETE')
<button class="bg-red-500 text-white px-3 py-1 rounded hover:bg-red-600">Hapus</button>
@ -58,5 +67,5 @@
</table>
</div>
</div>
</div>
</div>
@endsection

View File

@ -1,17 +1,21 @@
@extends('layouts.app')
@section('content')
<div class="bg-white shadow-md rounded-2xl p-6 border border-[#e1f0e8]">
<div class="flex flex-col md:flex-row justify-between items-start md:items-center mb-6 border-b border-[#e1f0e8] pb-4">
<div class="bg-white shadow-md rounded-2xl p-6 border border-[#e1f0e8]">
<div
class="flex flex-col md:flex-row justify-between items-start md:items-center mb-6 border-b border-[#e1f0e8] pb-4">
<div>
<h1 class="text-2xl font-extrabold text-gray-800 flex items-center">
<span class="bg-green-100 text-green-700 p-2 rounded-xl mr-3"><i class="fas fa-bus"></i></span> Log Penjemputan
<span class="bg-green-100 text-green-700 p-2 rounded-xl mr-3"><i class="fas fa-bus"></i></span> Log
Penjemputan
</h1>
<p class="text-sm text-gray-500 mt-1 ml-12">Daftar riwayat penjemputan siswa (Real-time).</p>
</div>
<div class="mt-4 md:mt-0 flex items-center bg-green-50 text-green-800 px-4 py-2.5 rounded-xl font-bold text-sm border border-green-100 shadow-sm">
<i class="fas fa-calendar-day mr-2 text-green-500"></i> Hari Ini: {{ $logs->where('waktu_jemput', '>=', now()->today())->count() }}
<div
class="mt-4 md:mt-0 flex items-center bg-green-50 text-green-800 px-4 py-2.5 rounded-xl font-bold text-sm border border-green-100 shadow-sm">
<i class="fas fa-calendar-day mr-2 text-green-500"></i> Hari Ini:
{{ $logs->where('waktu_jemput', '>=', now()->today())->count() }}
</div>
</div>
@ -48,18 +52,24 @@
</td>
<td class="p-4 text-center">
<span class="inline-block px-3 py-1 rounded-full text-xs font-bold bg-green-100 text-green-700 border border-green-200 shadow-sm">
<span
class="inline-block px-3 py-1 rounded-full text-xs font-bold bg-green-100 text-green-700 border border-green-200 shadow-sm">
{{ $log->status_hubungan }}
</span>
</td>
<td class="p-4 text-center">
<form action="{{ route('penjemputan.destroy', $log->id) }}" method="POST" onsubmit="return confirm('Hapus data log ini?');">
<form action="{{ route('penjemputan.destroy', $log->id) }}" method="POST"
onsubmit="return confirm('Hapus data log ini?');">
@csrf
@method('DELETE')
<button type="submit" class="text-gray-400 hover:text-red-500 transition-colors p-2 rounded-full hover:bg-red-50" title="Hapus Riwayat">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
<button type="submit"
class="text-gray-400 hover:text-red-500 transition-colors p-2 rounded-full hover:bg-red-50"
title="Hapus Riwayat">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
</svg>
</button>
</form>
@ -69,7 +79,11 @@
<tr>
<td colspan="5" class="p-10 text-center text-gray-400">
<div class="flex flex-col items-center justify-center">
<svg class="w-12 h-12 mb-3 text-gray-300" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg>
<svg class="w-12 h-12 mb-3 text-gray-300" fill="none" stroke="currentColor"
viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
<p class="text-sm">Belum ada data penjemputan hari ini.</p>
</div>
</td>
@ -78,5 +92,5 @@
</tbody>
</table>
</div>
</div>
</div>
@endsection

View File

@ -1,18 +1,24 @@
@extends('layouts.app')
@section('content')
<div class="bg-white shadow-md rounded-2xl border border-[#e1f0e8] overflow-hidden">
<div class="bg-white shadow-md rounded-2xl border border-[#e1f0e8] overflow-hidden">
<!-- Header Section -->
<div class="flex flex-col md:flex-row justify-between items-start md:items-center bg-gradient-to-br from-green-600 to-teal-700 p-8 shadow-inner relative overflow-hidden">
<div
class="flex flex-col md:flex-row justify-between items-start md:items-center bg-gradient-to-br from-green-600 to-teal-700 p-8 shadow-inner relative overflow-hidden">
<!-- Decorative inner pattern -->
<div class="absolute inset-0 bg-[url('https://www.transparenttextures.com/patterns/cubes.png')] opacity-10 mix-blend-overlay"></div>
<div
class="absolute inset-0 bg-[url('https://www.transparenttextures.com/patterns/cubes.png')] opacity-10 mix-blend-overlay">
</div>
<div class="relative z-10">
<h1 class="text-2xl font-extrabold text-white flex items-center drop-shadow">
<span class="bg-white/20 text-white p-2.5 rounded-xl mr-4 backdrop-blur-md"><i class="fas fa-chart-line"></i></span> Laporan Perkembangan
<span class="bg-white/20 text-white p-2.5 rounded-xl mr-4 backdrop-blur-md"><i
class="fas fa-chart-line"></i></span> Laporan Perkembangan
</h1>
<p class="text-green-50 mt-2 ml-14 font-medium drop-shadow-sm">Pilih siswa untuk melihat Catatan Anekdot, Hasil Karya, dan Ceklis.</p>
<p class="text-green-50 mt-2 ml-14 font-medium drop-shadow-sm">Pilih siswa untuk melihat Catatan Anekdot,
Hasil Karya, dan Ceklis.</p>
</div>
<div class="mt-6 md:mt-0 relative z-10 flex items-center bg-white text-green-800 px-5 py-3 rounded-xl font-bold text-sm shadow-lg">
<div
class="mt-6 md:mt-0 relative z-10 flex items-center bg-white text-green-800 px-5 py-3 rounded-xl font-bold text-sm shadow-lg">
<i class="fas fa-users mr-2 text-green-500"></i> Total Siswa: {{ $siswas->count() }}
</div>
</div>
@ -45,7 +51,8 @@
<td class="py-3 px-4 text-center">
{{-- PERBAIKAN: Hapus 'admin.' jadi 'perkembangan.show' --}}
<a href="{{ route('perkembangan.show', $siswa->id) }}" class="inline-flex items-center gap-1 border border-green-600 text-green-600 bg-white hover:bg-green-50 px-4 py-1.5 rounded-md text-sm font-medium transition duration-200 shadow-sm">
<a href="{{ route('perkembangan.show', $siswa->id) }}"
class="inline-flex items-center gap-1 border border-green-600 text-green-600 bg-white hover:bg-green-50 px-4 py-1.5 rounded-md text-sm font-medium transition duration-200 shadow-sm">
📂 Buka Rapot
</a>
</td>
@ -68,5 +75,5 @@
<div class="mt-4 pb-6 text-center text-xs text-gray-400">
&copy; {{ date('Y') }} PAUD Aisyiyah Monitoring System
</div>
</div>
</div>
@endsection

View File

@ -1,19 +1,24 @@
@extends('layouts.app')
@section('content')
<div class="bg-white shadow-md rounded-2xl border border-[#e1f0e8] overflow-hidden">
<div class="bg-white shadow-md rounded-2xl border border-[#e1f0e8] overflow-hidden">
<!-- Header Section -->
<div class="flex flex-col md:flex-row justify-between items-start md:items-center bg-gradient-to-br from-green-600 to-teal-700 p-8 shadow-inner relative overflow-hidden">
<div
class="flex flex-col md:flex-row justify-between items-start md:items-center bg-gradient-to-br from-green-600 to-teal-700 p-8 shadow-inner relative overflow-hidden">
<!-- Decorative inner pattern -->
<div class="absolute inset-0 bg-[url('https://www.transparenttextures.com/patterns/cubes.png')] opacity-10 mix-blend-overlay"></div>
<div
class="absolute inset-0 bg-[url('https://www.transparenttextures.com/patterns/cubes.png')] opacity-10 mix-blend-overlay">
</div>
<div class="relative z-10">
<h1 class="text-2xl font-extrabold text-white flex items-center drop-shadow">
<span class="bg-white/20 text-white p-2.5 rounded-xl mr-4 backdrop-blur-md"><i class="fas fa-child"></i></span> Data Peserta Didik
<span class="bg-white/20 text-white p-2.5 rounded-xl mr-4 backdrop-blur-md"><i
class="fas fa-child"></i></span> Data Peserta Didik
</h1>
<p class="text-green-50 mt-2 ml-14 font-medium drop-shadow-sm">Manajemen data peserta didik PAUD.</p>
</div>
<div class="mt-6 md:mt-0 relative z-10">
<a href="{{ route('siswa.create') }}" class="inline-flex items-center gap-2 bg-white text-green-700 px-6 py-3 rounded-xl hover:bg-green-50 font-bold text-sm shadow-lg transition-all hover:-translate-y-1">
<a href="{{ route('siswa.create') }}"
class="inline-flex items-center gap-2 bg-white text-green-700 px-6 py-3 rounded-xl hover:bg-green-50 font-bold text-sm shadow-lg transition-all hover:-translate-y-1">
<i class="fas fa-plus"></i> Tambah Siswa
</a>
</div>
@ -22,7 +27,8 @@
<div class="p-6">
@if(session('success'))
<div class="bg-green-50/50 border border-green-200 text-green-700 p-4 mb-6 rounded-xl flex items-center shadow-sm" role="alert">
<div class="bg-green-50/50 border border-green-200 text-green-700 p-4 mb-6 rounded-xl flex items-center shadow-sm"
role="alert">
<i class="fas fa-check-circle mr-3 text-xl text-green-500"></i>
<p class="font-medium">{{ session('success') }}</p>
</div>
@ -54,7 +60,8 @@
<td class="py-3 px-4 font-medium">{{ $siswa->nama_siswa }}</td>
<td class="py-3 px-4 text-center">
<span class="px-2 py-1 rounded text-xs font-bold {{ $siswa->jenis_kelamin == 'L' ? 'bg-blue-100 text-blue-800' : 'bg-pink-100 text-pink-800' }}">
<span
class="px-2 py-1 rounded text-xs font-bold {{ $siswa->jenis_kelamin == 'L' ? 'bg-blue-100 text-blue-800' : 'bg-pink-100 text-pink-800' }}">
{{ $siswa->jenis_kelamin }}
</span>
</td>
@ -67,7 +74,8 @@
@if($siswa->wali_murid)
<div class="text-sm font-semibold text-gray-800">{{ $siswa->wali_murid->nama_wali }}</div>
{{-- Tampilkan Alamat dari Wali Murid --}}
<div class="text-xs text-gray-500 mt-1">🏠 {{ Str::limit($siswa->wali_murid->alamat, 30) }}</div>
<div class="text-xs text-gray-500 mt-1">🏠 {{ Str::limit($siswa->wali_murid->alamat, 30) }}
</div>
@if(!empty($siswa->wali_murid->no_hp) && $siswa->wali_murid->no_hp != '-')
<div class="text-xs text-gray-500">📞 {{ $siswa->wali_murid->no_hp }}</div>
@endif
@ -78,13 +86,16 @@
<td class="py-3 px-4 text-center">
<div class="flex items-center justify-center gap-4">
<a href="{{ route('siswa.edit', $siswa->id) }}" class="text-blue-500 hover:text-blue-700 hover:underline transition duration-150">
<a href="{{ route('siswa.edit', $siswa->id) }}"
class="text-blue-500 hover:text-blue-700 hover:underline transition duration-150">
Edit
</a>
<form action="{{ route('siswa.destroy', $siswa->id) }}" method="POST" onsubmit="return confirm('Yakin ingin menghapus data siswa ini?');" class="m-0">
<form action="{{ route('siswa.destroy', $siswa->id) }}" method="POST"
onsubmit="return confirm('Yakin ingin menghapus data siswa ini?');" class="m-0">
@csrf
@method('DELETE')
<button type="submit" class="text-red-500 hover:text-red-700 hover:underline transition duration-150">
<button type="submit"
class="text-red-500 hover:text-red-700 hover:underline transition duration-150">
Hapus
</button>
</form>
@ -102,5 +113,5 @@
</table>
</div>
</div>
</div>
</div>
@endsection

View File

@ -39,6 +39,22 @@
<label class="block text-gray-700 font-medium mb-1">Alamat Lengkap</label>
<textarea name="alamat" rows="2" class="w-full border border-gray-300 rounded-lg p-2 focus:ring-2 focus:ring-green-500 focus:outline-none">{{ old('alamat') }}</textarea>
</div>
<div class="mb-2 md:col-span-2">
<label class="block text-gray-700 font-medium mb-1">Zona Wilayah</label>
<select name="master_zona_id" class="w-full border border-gray-300 rounded-lg p-2 focus:ring-2 focus:ring-green-500 focus:outline-none" required>
<option value="">-- Pilih Zona Wilayah --</option>
@foreach ($zonas as $kategori => $zonaGroup)
<optgroup label="{{ $kategori }}">
@foreach ($zonaGroup as $zona)
<option value="{{ $zona->id }}" {{ old('master_zona_id') == $zona->id ? 'selected' : '' }}>
{{ $zona->nama_zona }}
</option>
@endforeach
</optgroup>
@endforeach
</select>
</div>
</div>
</div>

View File

@ -1,7 +1,7 @@
@extends('layouts.app')
@section('content')
<div class="bg-white shadow-md rounded-lg p-6 max-w-xl mx-auto mt-10">
<div class="bg-white shadow-md rounded-lg p-6 max-w-xl mx-auto mt-10">
<div class="flex justify-between items-center mb-6">
<h1 class="text-xl font-bold text-gray-700">✏️ Edit Wali Murid</h1>
<a href="{{ route('wali-murid.index') }}" class="text-gray-500 hover:text-gray-700">&larr; Kembali</a>
@ -26,24 +26,14 @@
<div class="mb-4">
<label class="block text-gray-700 font-medium mb-1">Nama Wali</label>
{{-- PERHATIKAN: value="{{ old('nama_wali', $data->nama_wali) }}" --}}
<input type="text" name="nama_wali"
value="{{ old('nama_wali', $data->nama_wali) }}"
<input type="text" name="nama_wali" value="{{ old('nama_wali', $data->nama_wali) }}"
class="w-full border border-gray-300 rounded-lg p-2 focus:ring-2 focus:ring-green-500 focus:outline-none"
required>
</div>
<div class="mb-4">
<label class="block text-gray-700 font-medium mb-1">Email (Login)</label>
<input type="email" name="email"
value="{{ old('email', $data->user?->email ?? '') }}"
class="w-full border border-gray-300 rounded-lg p-2 focus:ring-2 focus:ring-green-500 focus:outline-none"
placeholder="Email belum didaftarkan">
</div>
<div class="mb-4">
<label class="block text-gray-700 font-medium mb-1">No HP</label>
<input type="text" name="no_hp"
value="{{ old('no_hp', $data->no_hp) }}"
<input type="text" name="no_hp" value="{{ old('no_hp', $data->no_hp) }}"
class="w-full border border-gray-300 rounded-lg p-2 focus:ring-2 focus:ring-green-500 focus:outline-none">
</div>
@ -53,6 +43,42 @@ class="w-full border border-gray-300 rounded-lg p-2 focus:ring-2 focus:ring-gree
class="w-full border border-gray-300 rounded-lg p-2 focus:ring-2 focus:ring-green-500 focus:outline-none">{{ old('alamat', $data->alamat) }}</textarea>
</div>
<div class="mb-4">
<label class="block text-gray-700 font-medium mb-1">Zona Wilayah</label>
<select name="master_zona_id" class="w-full border border-gray-300 rounded-lg p-2 focus:ring-2 focus:ring-green-500 focus:outline-none" required>
<option value="">-- Pilih Zona Wilayah --</option>
@foreach ($zonas as $kategori => $zonaGroup)
<optgroup label="{{ $kategori }}">
@foreach ($zonaGroup as $zona)
<option value="{{ $zona->id }}" {{ old('master_zona_id', $data->master_zona_id) == $zona->id ? 'selected' : '' }}>
{{ $zona->nama_zona }}
</option>
@endforeach
</optgroup>
@endforeach
</select>
</div>
<div class="bg-yellow-50 p-4 rounded-lg border border-yellow-200 mb-6 mt-4">
<h2 class="text-lg font-bold text-yellow-800 mb-2 flex items-center gap-2">🔐 Pengaturan Akun Login</h2>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label class="block text-gray-700 font-medium mb-1">Email Login</label>
<input type="email" name="email" value="{{ old('email', $data->user?->email ?? '') }}"
class="w-full border border-gray-300 rounded-lg p-2 focus:ring-2 focus:ring-yellow-500 focus:outline-none"
placeholder="Email belum didaftarkan">
</div>
<div>
<label class="block text-gray-700 font-medium mb-1">Password Baru</label>
<input type="password" name="password"
class="w-full border border-gray-300 rounded-lg p-2 focus:ring-2 focus:ring-yellow-500 focus:outline-none"
placeholder="Kosongkan jika tidak ganti">
<p class="text-xs text-gray-500 mt-1">*Isi hanya jika ingin mengganti password login.</p>
</div>
</div>
</div>
<div class="flex justify-end mt-6 gap-3">
<button type="submit"
class="bg-green-600 text-white font-semibold px-6 py-2 rounded-lg hover:bg-green-700 transition duration-200 shadow-md">
@ -60,5 +86,5 @@ class="bg-green-600 text-white font-semibold px-6 py-2 rounded-lg hover:bg-green
</button>
</div>
</form>
</div>
</div>
@endsection

View File

@ -1,19 +1,25 @@
@extends('layouts.app')
@section('content')
<div class="bg-white shadow-md rounded-2xl border border-[#e1f0e8] overflow-hidden">
<div class="bg-white shadow-md rounded-2xl border border-[#e1f0e8] overflow-hidden">
<!-- Header Section -->
<div class="flex flex-col md:flex-row justify-between items-start md:items-center bg-gradient-to-br from-green-600 to-teal-700 p-8 shadow-inner relative overflow-hidden">
<div
class="flex flex-col md:flex-row justify-between items-start md:items-center bg-gradient-to-br from-green-600 to-teal-700 p-8 shadow-inner relative overflow-hidden">
<!-- Decorative inner pattern -->
<div class="absolute inset-0 bg-[url('https://www.transparenttextures.com/patterns/cubes.png')] opacity-10 mix-blend-overlay"></div>
<div
class="absolute inset-0 bg-[url('https://www.transparenttextures.com/patterns/cubes.png')] opacity-10 mix-blend-overlay">
</div>
<div class="relative z-10">
<h1 class="text-2xl font-extrabold text-white flex items-center drop-shadow">
<span class="bg-white/20 text-white p-2.5 rounded-xl mr-4 backdrop-blur-md"><i class="fas fa-users"></i></span> Data Wali Murid
<span class="bg-white/20 text-white p-2.5 rounded-xl mr-4 backdrop-blur-md"><i
class="fas fa-users"></i></span> Data Wali Murid
</h1>
<p class="text-green-50 mt-2 ml-14 font-medium drop-shadow-sm">Kelola informasi orang tua / wali peserta didik.</p>
<p class="text-green-50 mt-2 ml-14 font-medium drop-shadow-sm">Kelola informasi orang tua / wali peserta
didik.</p>
</div>
<div class="mt-6 md:mt-0 relative z-10">
<a href="{{ route('wali-murid.create') }}" class="inline-flex items-center gap-2 bg-white text-green-700 px-6 py-3 rounded-xl hover:bg-green-50 font-bold text-sm shadow-lg transition-all hover:-translate-y-1">
<a href="{{ route('wali-murid.create') }}"
class="inline-flex items-center gap-2 bg-white text-green-700 px-6 py-3 rounded-xl hover:bg-green-50 font-bold text-sm shadow-lg transition-all hover:-translate-y-1">
<i class="fas fa-plus"></i> Tambah Wali
</a>
</div>
@ -22,7 +28,8 @@
<div class="p-6">
{{-- Alert Merah untuk Error --}}
@if(session('error'))
<div class="bg-red-50/50 border border-red-200 text-red-700 p-4 mb-6 rounded-xl flex items-center shadow-sm" role="alert">
<div class="bg-red-50/50 border border-red-200 text-red-700 p-4 mb-6 rounded-xl flex items-center shadow-sm"
role="alert">
<i class="fas fa-exclamation-circle mr-3 text-xl text-red-500"></i>
<div>
<strong class="font-bold block">Error!</strong>
@ -33,7 +40,8 @@
{{-- Alert Hijau untuk Sukses --}}
@if(session('success'))
<div class="bg-green-50/50 border border-green-200 text-green-700 p-4 mb-6 rounded-xl flex items-center shadow-sm" role="alert">
<div class="bg-green-50/50 border border-green-200 text-green-700 p-4 mb-6 rounded-xl flex items-center shadow-sm"
role="alert">
<i class="fas fa-check-circle mr-3 text-xl text-green-500"></i>
<p class="font-medium">{{ session('success') }}</p>
</div>
@ -58,8 +66,10 @@
<td class="p-2">{{ $wali->no_hp ?? '-' }}</td>
<td class="p-2 text-sm text-gray-600">{{ $wali->alamat ?? '-' }}</td>
<td class="p-2 space-x-2">
<a href="{{ route('wali-murid.edit', $wali->id) }}" class="text-blue-500 hover:underline">Edit</a>
<form action="{{ route('wali-murid.destroy', $wali->id) }}" method="POST" class="inline" onsubmit="return confirm('Yakin hapus?');">
<a href="{{ route('wali-murid.edit', $wali->id) }}"
class="text-blue-500 hover:underline">Edit</a>
<form action="{{ route('wali-murid.destroy', $wali->id) }}" method="POST" class="inline"
onsubmit="return confirm('Yakin hapus?');">
@csrf
@method('DELETE')
<button type="submit" class="text-red-500 hover:underline">Hapus</button>
@ -75,5 +85,5 @@
</table>
</div>
</div>
</div>
</div>
@endsection

View File

@ -31,16 +31,26 @@ class="w-full border border-gray-300 rounded-lg p-2 focus:ring-2 focus:ring-gree
required>
</div>
<div class="mb-4">
<label class="block text-gray-700 font-medium mb-1">Email (Login)</label>
{{-- Gunakan $data->user --}}
<div class="bg-yellow-50 p-4 rounded-lg border border-yellow-200 mb-6 mt-4">
<h2 class="text-lg font-bold text-yellow-800 mb-2 flex items-center gap-2">🔐 Pengaturan Akun Login</h2>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label class="block text-gray-700 font-medium mb-1">Email Login</label>
<input type="email" name="email"
value="{{ old('email', $data->user?->email ?? '') }}"
class="w-full border border-gray-300 rounded-lg p-2 focus:ring-2 focus:ring-green-500 focus:outline-none"
class="w-full border border-gray-300 rounded-lg p-2 focus:ring-2 focus:ring-yellow-500 focus:outline-none"
placeholder="Email belum didaftarkan">
</div>
<div>
<label class="block text-gray-700 font-medium mb-1">Password Baru</label>
<input type="password" name="password" class="w-full border border-gray-300 rounded-lg p-2 focus:ring-2 focus:ring-yellow-500 focus:outline-none" placeholder="Kosongkan jika tidak ingin ganti">
<p class="text-xs text-gray-500 mt-1">*Isi hanya jika ingin mengganti password login.</p>
</div>
</div>
</div>
<div class="mb-4">
<div class="mb-4 mt-4">
<label class="block text-gray-700 font-medium mb-1">No HP</label>
<input type="text" name="no_hp"
value="{{ old('no_hp', $data->no_hp) }}"

View File

@ -197,7 +197,7 @@
<!-- Search Input with Icon -->
<div class="relative hidden md:block">
<i class="fas fa-search absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 text-sm"></i>
<input type="text" placeholder="Cari..."
<input type="text" id="global-search" placeholder="Cari data di tabel..."
class="pl-10 pr-4 py-2 bg-gray-50/50 border border-gray-200 focus:bg-white rounded-xl w-64 text-sm transition-all focus:w-80 shadow-sm">
</div>
@ -224,4 +224,28 @@ class="pl-10 pr-4 py-2 bg-gray-50/50 border border-gray-200 focus:bg-white round
</div>
</body>
<script>
document.addEventListener('DOMContentLoaded', function() {
const searchInput = document.getElementById('global-search');
if(searchInput) {
searchInput.addEventListener('input', function(e) {
const query = e.target.value.toLowerCase();
const rows = document.querySelectorAll('tbody tr');
rows.forEach(row => {
// Jangan sembunyikan baris "Belum ada data pesan"
if(row.querySelector('td[colspan]')) return;
const text = row.textContent.toLowerCase();
if(text.includes(query)) {
row.style.display = '';
} else {
row.style.display = 'none';
}
});
});
}
});
</script>
</html>

View File

@ -11,6 +11,7 @@
use App\Http\Controllers\Api\GuruController;
use App\Http\Controllers\Api\PenjemputanController;
use App\Http\Controllers\Api\AStarController;
use App\Http\Controllers\Api\HomeVisitController;
/*
|--------------------------------------------------------------------------
@ -37,6 +38,7 @@
// --- UMUM ---
Route::get('/siswa-saya', [SiswaController::class, 'index']); // Pindah ke sini biar bisa baca Auth::user()
Route::post('/logout', [AuthController::class, 'logout']);
Route::post('/update-fcm-token', [AuthController::class, 'updateFcmToken']);
Route::get('/user', function (Request $request) {
return $request->user(); // Cek siapa yang login
});
@ -69,5 +71,9 @@
Route::get('/rute-astar', [AStarController::class, 'cariRute']);
// RUTE HOME VISIT / ZONASI
Route::get('/zonasi', [HomeVisitController::class, 'getZonasi']);
Route::get('/home-visit/zona/{zona_id}', [HomeVisitController::class, 'getSiswaByZona']);
});

View File

@ -0,0 +1,13 @@
{
"type": "service_account",
"project_id": "simpaudkartoharjo",
"private_key_id": "d5856c1910f178842deff72bb591d8480181c6fc",
"private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDYK3IGvE4dnkiy\nOhLyBDZGXigJ3Eu3nqUCixbSs/tBvURF8YR1Wxxmadw7v/ozJNwy5/aHo1wdd0j+\nFrIv5JVhpAWuO7OIXvodtRKYONmyPj9B9ioV9yGsIYsqj3942etbfyUVDdOpwniO\nAQBnJanu4pg6yoAGXLAjo//AuUMI5b+3NUwcfCva1dZgrLvz+pWZclN8nwOx/npU\nXj7SoWveSQXBqnhJFm5TLlacj9OHVW4TWx7DoAC5ePpVvXJGGC7s8xUgdlRXyoPL\n6DrFZVHHYmrdzSSVtgp8Hr0v0iLiKu8y7v79uN7jOyxZkw9ukzwA025TCQxtifSr\n/vEO0l3xAgMBAAECggEAWOGgLEHPsqDqzhFPyd/OeydqugcwwMqDmWScGT10kUaj\nZEjWSDSSnE9phM2+L7o3qdyzgni6PslVo1eso0GO5Es/JLEac/dtSrqxbxJs/DtY\n4iO3kTmASFiwcmr3JDch7Qh9tEbvoSy7SdQCmOalFPppUj8B3dvNdpIPbewesnCX\naNLHx1FkokKnrBD8H9oqSj97q6DutDM8BZpn9xxvZd9vDgFH1PYLO8FM8m7GMR3p\nJEU0Xs1gk9DfC9CQGcmF4WSqY0CDtvC9fscIcLTNG83fp0/DO74Wb6r6RT4q1lFb\nifYBmTiOuQT9J7tMMGGhkPXyQYW6Nw18TyOphE67GwKBgQDuI4FfXot4EcRVU/Lp\nm2BzD8aNAFZcUF/vOGWGiKp2kTLiDCxwEXS01gZzre+MtEGXK+40QpztkVnaU6zN\nlcXZuNHFOXsDA4LLhR2LRC4bOWchH8usroorfzM0kDfFkPMiwY+k6LZQAL1IvKuF\nIsqRTcnpGDDXvvyXVBYbOqrWZwKBgQDoYh063eXL4HIlh/oCOD3Fhp5p9zd/dHzN\nCv2ODOcEQG3N43YLPHHf2mCSpv8Vcp17cV3aGgMYUEU2i7f6TpOX9VUpgLip8tEj\nOxZL4xN3GAy57MC2v1t3RBU58waYk1fOdqFlvwy7xxdCqU/zB8vvdjJ1vqIJnAsw\nICD087eB5wKBgHLGtB0mMWxui8Vgj8yeMc9jRBxDlFwr9QEUmoJMLnS1KOQgX+6n\nyys5mKR6qeGUI6Tb7JRNotsx2i/Lcpcn39M/LAO1358lOw4im4m7E8nVUep6K62P\n9lJenWxxMiBL65PN3RDrhKtsn86F+NlTWnTMHEv3d9sUVyQMyBbZoOtzAoGBAJPj\nvQ51oYU6deqEuwsml8lZfv+ZIWyvya0ETZFVjMAb8MWS+ND1ytLXu5YZSUVxB+BD\nqaLf4xBaJXItQQy/bRbMP0KGdP9TVN3DANGS1hR47cB1d7/V0HP6lDeo/o2jV8JB\npT2HdKcccSUvc34LfDINWtesVpse/8/E4rSBVkwJAoGAI00acL5ragdj1Sz/eTiU\nnvi4uOhRbcegDOnk3H1VYULoy2d6bvTfNObDnI2laWTIZluwBJ4WrBbDAGjNkL4d\nDHNO5ZgjyqtK+3LoSixEac+YKxTvmPLtmXgBExjHwQ5lSWG3VQyCbPYBmruZFLhE\nKb868a/RtMJm9f8P1WDkb/I=\n-----END PRIVATE KEY-----\n",
"client_email": "firebase-adminsdk-fbsvc@simpaudkartoharjo.iam.gserviceaccount.com",
"client_id": "106199666854739826761",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-fbsvc%40simpaudkartoharjo.iam.gserviceaccount.com",
"universe_domain": "googleapis.com"
}

View File

@ -1 +0,0 @@
a:3:{s:6:"_token";s:40:"vYUfuBlzhzFJwH2XXHUItujz2a2gJxSN3nu71JBO";s:9:"_previous";a:1:{s:3:"url";s:21:"http://127.0.0.1:8000";}s:6:"_flash";a:2:{s:3:"old";a:0:{}s:3:"new";a:0:{}}}

View File

@ -0,0 +1 @@
a:4:{s:6:"_token";s:40:"ocZHTeLJ29EH7CNr3zDNqY5dmsDthSoRJrHMTTx8";s:9:"_previous";a:1:{s:3:"url";s:32:"http://127.0.0.1:8000/pengumuman";}s:6:"_flash";a:2:{s:3:"old";a:0:{}s:3:"new";a:0:{}}s:50:"login_web_59ba36addc2b2f9401580f014c7f58ea4e30989d";i:1;}

View File

@ -1 +0,0 @@
a:4:{s:6:"_token";s:40:"00mfxFm9DrbF1elsEluX9X6oWjH0R4XSNXCoGuB3";s:6:"_flash";a:2:{s:3:"old";a:0:{}s:3:"new";a:0:{}}s:9:"_previous";a:1:{s:3:"url";s:31:"http://127.0.0.1:8000/dashboard";}s:50:"login_web_59ba36addc2b2f9401580f014c7f58ea4e30989d";i:1;}

View File

@ -1 +0,0 @@
a:3:{s:6:"_token";s:40:"Wli1wb6syOPQUamEet6OVXObBcjjwOw1H8ICY0Ck";s:9:"_previous";a:1:{s:3:"url";s:27:"http://127.0.0.1:8000/login";}s:6:"_flash";a:2:{s:3:"old";a:0:{}s:3:"new";a:0:{}}}

Binary file not shown.