From 33999768fdcfe3631f303adda1221ff265c699c2 Mon Sep 17 00:00:00 2001 From: Ryan Maulana Date: Sat, 27 Jun 2026 19:08:56 +0700 Subject: [PATCH] peresmian finalisasi perumahan --- .history/.env_20260414140457 | 66 - .history/.env_20260516092137 | 66 - .history/.env_20260516092138 | 66 - .history/.env_20260520085420 | 64 - .history/.env_20260520085427 | 64 - .history/.env_20260520085434 | 64 - .history/.env_20260520085648 | 66 - .history/.env_20260520085725 | 66 - .history/.env_20260520085919 | 64 - .history/.env_20260520090106 | 66 - .history/.env_20260520115238 | 66 - .history/.env_20260520115247 | 66 - .history/.env_20260520115411 | 66 - .history/.env_20260520115419 | 66 - .history/.env_20260521114440 | 66 - .history/.env_20260521115228 | 66 - .history/.env_20260521115334 | 66 - .history/.env_20260521115335 | 66 - .history/.env_20260521115338 | 66 - .history/.env_20260521115339 | 66 - .history/.env_20260521115342 | 66 - .history/.env_20260521115345 | 66 - .history/.env_20260521115424 | 66 - .history/.env_20260521115432 | 66 - .history/.env_20260521115440 | 66 - .history/.env_20260521115442 | 66 - .history/.env_20260521115446 | 66 - .history/.env_20260521165900 | 66 - .history/.env_20260521165902 | 66 - .history/.env_20260521165904 | 66 - .history/.env_20260521165916 | 66 - .history/.env_20260521165925 | 66 - .history/.env_20260521165951 | 66 - .history/.env_20260521170051 | 66 - .history/.env_20260521170054 | 66 - .history/.env_20260521170058 | 66 - ...env_20260520115245 => .env_20260625025301} | 10 +- ...env_20260520115241 => .env_20260625025304} | 10 +- ...env_20260520115243 => .env_20260625025306} | 10 +- ...env_20260520115251 => .env_20260625025308} | 10 +- ...env_20260521115329 => .env_20260625025310} | 10 +- ...env_20260520115422 => .env_20260625025319} | 8 +- .history/.env_20260625025325 | 66 + ...env_20260521115117 => .env_20260625025330} | 6 +- ...env_20260520115432 => .env_20260625030808} | 6 +- ...env_20260521114417 => .env_20260625030809} | 6 +- ...env_20260521114434 => .env_20260625115711} | 8 +- .../Admin/UserController_20260521201056.php | 96 ++ .../Admin/UserController_20260521201058.php | 96 ++ .../AuthController_20260506180715.php | 171 -- .../AuthController_20260507083718.php | 171 -- .../AuthController_20260507083845.php | 171 -- .../AuthController_20260507083847.php | 171 -- .../AuthController_20260524190202.php | 275 +++ .../AuthController_20260524190210.php | 275 +++ .../AuthController_20260524190212.php | 274 +++ .../AuthController_20260524190233.php | 275 +++ .../AuthController_20260524190234.php | 275 +++ .../AuthController_20260524190235.php | 275 +++ ....php => AuthController_20260524190240.php} | 0 .../AuthController_20260524190256.php | 275 +++ .../AuthController_20260524190306.php | 274 +++ .../AuthController_20260524191313.php | 270 +++ .../AuthController_20260524192503.php | 291 ++++ .../AuthController_20260524200654.php | 302 ++++ .../AuthController_20260524201955.php | 290 ++++ .../AuthController_20260524202342.php | 287 ++++ .../AuthController_20260524212628.php | 71 + .../AuthController_20260524212631.php | 287 ++++ .../AuthController_20260524212644.php | 287 ++++ .../AuthController_20260524212651.php | 290 ++++ .../AuthController_20260524212653.php | 287 ++++ .../AuthController_20260524212713.php | 290 ++++ .../AuthController_20260619112926.php | 291 ++++ ...GantiPasswordController_20260619110719.php | 0 ...GantiPasswordController_20260619110726.php | 46 + ...GantiPasswordController_20260619111038.php | 46 + ...GantiPasswordController_20260619111040.php | 46 + ...GantiPasswordController_20260619111537.php | 46 + ...GantiPasswordController_20260619111552.php | 46 + ...GantiPasswordController_20260619111555.php | 47 + ...GantiPasswordController_20260619111557.php | 46 + ...GantiPasswordController_20260619111559.php | 47 + ...GantiPasswordController_20260619111601.php | 46 + ...GantiPasswordController_20260619111602.php | 46 + ...GantiPasswordController_20260619111605.php | 46 + ...GantiPasswordController_20260619111613.php | 47 + ...GantiPasswordController_20260619111616.php | 47 + ...GantiPasswordController_20260619111619.php | 46 + ...GantiPasswordController_20260619111624.php | 46 + ...GantiPasswordController_20260619111626.php | 46 + ...GantiPasswordController_20260619111911.php | 46 + ...GantiPasswordController_20260619111913.php | 46 + .../IuranController_20260619091229.php | 0 .../IuranController_20260619091233.php | 107 ++ .../IuranController_20260619114355.php | 107 ++ .../IuranController_20260619114400.php | 107 ++ .../IuranController_20260620132415.php | 125 ++ .../KasController_20260619185433.php | 0 .../KasController_20260619185447.php | 52 + .../KasController_20260619191326.php | 49 + .../KasController_20260619212536.php | 104 ++ .../KasController_20260620082653.php | 106 ++ .../RekapController_20260619095636.php | 0 .../RekapController_20260619095645.php | 69 + .../RekapController_20260619101907.php | 70 + .../RekapController_20260619101908.php | 70 + .../RekapController_20260619101916.php | 69 + .../RekapController_20260620133154.php | 66 + .../RekapController_20260620134854.php | 66 + .../DashboardController_20260428130350.php | 112 -- .../DashboardController_20260507082141.php | 140 -- .../DashboardController_20260507082206.php | 140 -- .../DashboardController_20260507082214.php | 140 -- .../DashboardController_20260507082225.php | 141 -- .../DashboardController_20260507082229.php | 141 -- .../DashboardController_20260507083233.php | 118 -- .../DashboardController_20260622095816.php | 118 ++ ...=> DashboardController_20260622095819.php} | 0 .../DashboardController_20260622095829.php | 121 ++ .../DashboardController_20260622095850.php | 166 ++ .../DashboardController_20260622100905.php | 178 ++ .../DashboardController_20260622100935.php | 181 ++ .../IuranController_20260421225646.php | 185 +++ .../IuranController_20260615104208.php | 185 +++ .../IuranController_20260615104211.php | 185 +++ .../IuranController_20260615104218.php | 185 +++ .../IuranController_20260615175424.php | 208 +++ .../IuranController_20260615175433.php | 208 +++ .../IuranController_20260615175446.php | 262 +++ .../IuranController_20260615175452.php | 262 +++ .../IuranController_20260615180801.php | 267 +++ .../IuranController_20260615180806.php | 267 +++ .../IuranController_20260615180826.php | 273 +++ .../IuranController_20260615180830.php | 273 +++ .../IuranController_20260615180832.php | 273 +++ .../IuranController_20260615181323.php | 272 +++ .../IuranController_20260615181330.php | 272 +++ .../LaporanController_20260504203010.php | 67 - .../LaporanController_20260507090744.php | 95 -- .../LaporanController_20260507091544.php | 95 -- .../LaporanController_20260507153841.php | 94 -- .../LaporanController_20260507153850.php | 94 -- .../LaporanController_20260623182610.php | 107 ++ .../LayananController_20260610222522.php | 173 ++ .../LayananController_20260610222606.php | 173 ++ .../LayananController_20260610222608.php | 173 ++ .../LayananController_20260610222623.php | 173 ++ .../LayananController_20260610222625.php | 173 ++ .../LayananController_20260624223324.php | 197 +++ .../LayananController_20260624223327.php | 196 +++ .../LayananController_20260624223329.php | 173 ++ .../LayananController_20260624223344.php | 196 +++ .../LayananController_20260624223520.php | 173 ++ .../LayananController_20260624223529.php | 173 ++ .../LayananController_20260624223625.php | 173 ++ .../LayananController_20260624223627.php | 173 ++ .../LayananController_20260624223815.php | 173 ++ .../LayananController_20260624223845.php | 205 +++ .../LayananController_20260624223857.php | 205 +++ .../LayananController_20260624224251.php | 173 ++ .../LayananController_20260625013509.php | 232 +++ .../LayananController_20260625013511.php | 173 ++ .../LayananController_20260625013512.php | 232 +++ .../LayananController_20260625013514.php | 173 ++ .../LayananController_20260625013516.php | 232 +++ .../LayananController_20260625013554.php | 30 + .../LayananController_20260625013557.php | 232 +++ .../LayananController_20260625013601.php | 30 + .../LayananController_20260625013607.php | 232 +++ .../LayananController_20260625014723.php | 233 +++ .../LayananController_20260625014724.php | 233 +++ .../LayananController_20260625014727.php | 232 +++ .../LayananController_20260625014952.php | 233 +++ .../LayananController_20260625014958.php | 233 +++ .../LayananController_20260625015033.php | 233 +++ .../LayananController_20260625022400.php | 233 +++ .../PenghuniController_20260604090538.php | 508 ++++++ .../PenghuniController_20260604090540.php | 507 ++++++ .../PenghuniController_20260604090543.php | 508 ++++++ .../PenghuniController_20260604090547.php | 508 ++++++ .../PenghuniController_20260604090549.php | 509 ++++++ .../PenghuniController_20260604090552.php | 510 ++++++ .../PenghuniController_20260604090557.php | 510 ++++++ .../PenghuniController_20260604090600.php | 511 ++++++ .../PenghuniController_20260604090603.php | 512 ++++++ .../PenghuniController_20260604090606.php | 512 ++++++ .../PenghuniController_20260604090607.php | 512 ++++++ .../PenghuniController_20260604090611.php | 511 ++++++ .../PenghuniController_20260604090612.php | 512 ++++++ .../PenghuniController_20260604090616.php | 512 ++++++ .../PenghuniController_20260604090617.php | 512 ++++++ .../PenghuniController_20260604090619.php | 513 ++++++ .../PenghuniController_20260604090621.php | 514 ++++++ .../PenghuniController_20260604090659.php | 514 ++++++ .../PenghuniController_20260604090702.php | 514 ++++++ .../PenghuniController_20260604090704.php | 514 ++++++ .../PenghuniController_20260604090714.php | 513 ++++++ .../PenghuniController_20260610222045.php | 513 ++++++ .../PenghuniController_20260610222048.php | 513 ++++++ .../PenghuniController_20260610222051.php | 513 ++++++ .../PenghuniController_20260610222056.php | 513 ++++++ .../PenghuniController_20260610222059.php | 513 ++++++ .../PenghuniController_20260610222102.php | 513 ++++++ .../PenghuniController_20260610222105.php | 513 ++++++ .../PenghuniController_20260610222108.php | 513 ++++++ .../PenghuniController_20260610222110.php | 513 ++++++ .../PenghuniController_20260610222113.php | 513 ++++++ .../PenghuniController_20260610222117.php | 513 ++++++ .../PenghuniController_20260610222119.php | 513 ++++++ .../PenghuniController_20260610222120.php | 513 ++++++ .../PenghuniController_20260610222123.php | 513 ++++++ .../PenghuniController_20260614183436.php | 517 ++++++ .../PenghuniController_20260614183442.php | 517 ++++++ .../PenghuniController_20260614183444.php | 517 ++++++ .../PenghuniController_20260614183449.php | 513 ++++++ .../PenghuniController_20260614183500.php | 518 ++++++ .../PenghuniController_20260614183504.php | 518 ++++++ .../PenghuniController_20260614183546.php | 520 ++++++ .../PenghuniController_20260614183547.php | 527 ++++++ .../PenghuniController_20260614183556.php | 527 ++++++ .../PenghuniController_20260614183933.php | 529 ++++++ .../PenghuniController_20260614183935.php | 527 ++++++ .../PenghuniController_20260614183941.php | 528 ++++++ .../PenghuniController_20260614183944.php | 528 ++++++ .../PenghuniController_20260614184208.php | 530 ++++++ .../PenghuniController_20260614184210.php | 529 ++++++ .../PenghuniController_20260614184211.php | 537 ++++++ .../PenghuniController_20260614184217.php | 537 ++++++ .../PenghuniController_20260614184219.php | 538 ++++++ .../PenghuniController_20260614184337.php | 538 ++++++ .../PenghuniController_20260614184732.php | 556 +++++++ .../PenghuniController_20260614184735.php | 538 ++++++ .../PenghuniController_20260614184747.php | 535 ++++++ .../PenghuniController_20260614184931.php | 540 ++++++ .../PenghuniController_20260614185304.php | 547 ++++++ .../PenghuniController_20260614190042.php | 536 ++++++ .../RT/BendaharaController_20260619090446.php | 0 .../RT/BendaharaController_20260619090459.php | 76 + .../RT/BendaharaController_20260619105958.php | 77 + .../RT/BendaharaController_20260619110049.php | 76 + .../RT/BendaharaController_20260619110051.php | 76 + .../RT/KasController_20260619185519.php | 0 .../RT/KasController_20260619185522.php | 27 + .../RT/KasController_20260619185527.php | 27 + .../RT/KasController_20260619191405.php | 27 + .../RT/KasRTController_20260619191404.php | 27 + .../RT/KasRTController_20260620081459.php | 27 + .../RT/KasRTController_20260620081519.php | 27 + .../RT/KasRTController_20260620081649.php | 27 + .../RT/KasRTController_20260620082003.php | 27 + .../RT/KasRTController_20260620082010.php | 27 + .../RT/KasRTController_20260620082012.php | 27 + .../RT/KasRTController_20260620082018.php | 27 + .../ReviewIuranController_20260619091258.php | 0 .../ReviewIuranController_20260619091314.php | 61 + .../ReviewIuranController_20260619115439.php | 76 + .../ReviewIuranController_20260619115450.php | 77 + .../ReviewRekapController_20260619095716.php | 0 .../ReviewRekapController_20260619095826.php | 82 + .../ReviewRekapController_20260619095848.php | 83 + .../ReviewRekapController_20260619095852.php | 82 + .../ReviewRekapController_20260619101839.php | 82 + .../ReviewRekapController_20260619101840.php | 82 + .../ReviewRekapController_20260619101847.php | 81 + .../ReviewRekapController_20260620132653.php | 35 + .../ReviewRekapController_20260620134923.php | 78 + .../UserController_20260505205724.php | 376 +++++ .../UserController_20260521214525.php | 366 ++++ .../UserController_20260521214527.php | 376 +++++ .../UserController_20260521214529.php | 366 ++++ .../UserIuranController_20260416200452.php | 103 ++ .../UserIuranController_20260615175138.php | 101 ++ .../UserIuranController_20260615175149.php | 101 ++ .../UserIuranController_20260615175302.php | 96 ++ .../UserIuranController_20260615175304.php | 101 ++ .../UserIuranController_20260615175324.php | 93 ++ .../UserIuranController_20260615175327.php | 93 ++ .../UserIuranController_20260619094756.php | 113 ++ .../UserIuranController_20260619094803.php | 113 ++ .../UserIuranController_20260619094845.php | 128 ++ .../UserIuranController_20260619094849.php | 128 ++ .../UserIuranController_20260619095405.php | 129 ++ .../UserIuranController_20260619095428.php | 129 ++ .../UserIuranController_20260619101939.php | 130 ++ .../UserIuranController_20260619101940.php | 130 ++ .../UserIuranController_20260619213550.php | 132 ++ .../UserIuranController_20260619213554.php | 134 ++ .../UserIuranController_20260619213608.php | 134 ++ .../UserIuranController_20260620090407.php | 122 ++ .../UserIuranController_20260620090422.php | 120 ++ .../UserIuranController_20260620090436.php | 108 ++ .../UserIuranController_20260622094632.php | 110 ++ .../UserKasController_20260619212656.php | 0 .../UserKasController_20260619212704.php | 48 + .../Middleware/CheckRole_20260619003211.php | 0 .../Middleware/CheckRole_20260619003234.php | 23 + .../CheckStatusAkun_20260619003128.php | 0 .../CheckStatusAkun_20260619003152.php | 21 + .../CheckStatusAkun_20260619003159.php | 21 + .../ForcePasswordChange_20260619110357.php | 0 .../ForcePasswordChange_20260619110404.php | 25 + .../NotifPengaduanSelesai_20260625013755.php | 0 .../NotifPengaduanSelesai_20260625015248.php | 21 + .../Mail/NotifPengaduan_20260413213025.php | 21 + .../Mail/NotifPengaduan_20260625022333.php | 28 + .../Mail/NotifPengaduan_20260625022335.php | 28 + .../Mail/NotifPengaduan_20260625022337.php | 21 + .../Mail/NotifPengaduan_20260625022338.php | 28 + .../Mail/NotifPengaduan_20260625093324.php | 28 + .history/app/Models/Iuran_20260421222156.php | 37 + .history/app/Models/Iuran_20260618225040.php | 50 + .history/app/Models/Iuran_20260619102004.php | 50 + .history/app/Models/Iuran_20260619102005.php | 50 + .../Models/KasBendahara_20260619101754.php | 0 .../Models/KasBendahara_20260619101758.php | 29 + .../Models/KasBendahara_20260619193847.php | 38 + .../app/Models/Layanan_20260410140848.php | 31 + .../app/Models/Layanan_20260625013618.php | 30 + .../app/Models/RekapIuran_20260619101721.php | 0 .../app/Models/RekapIuran_20260619101725.php | 33 + .history/app/Models/User_20260419103641.php | 60 + .history/app/Models/User_20260618224625.php | 45 + .history/app/Models/User_20260618224628.php | 60 + .history/app/Models/User_20260618224631.php | 45 + .history/app/Models/User_20260618224635.php | 45 + .history/app/Models/User_20260618224638.php | 60 + .history/app/Models/User_20260618224642.php | 45 + .history/app/Models/User_20260618224646.php | 45 + .history/app/Models/User_20260618224650.php | 45 + .history/app/Models/User_20260618224652.php | 60 + .history/app/Models/User_20260618225014.php | 65 + .history/app/Models/User_20260618225019.php | 60 + .history/app/Models/User_20260618225021.php | 65 + .history/app/Models/User_20260620144354.php | 66 + .../WhatsappService_20260524190026.php | 0 .../WhatsappService_20260524190118.php | 58 + .../WhatsappService_20260524190126.php | 58 + .../WhatsappService_20260524190129.php | 57 + .../WhatsappService_20260524192851.php | 40 + .../WhatsappService_20260524192854.php | 57 + .../WhatsappService_20260524192902.php | 53 + .../WhatsappService_20260524192908.php | 57 + .../WhatsappService_20260524192910.php | 53 + .../WhatsappService_20260524192920.php | 53 + .../WhatsappService_20260524193040.php | 79 + .../WhatsappService_20260524195438.php | 80 + .../WhatsappService_20260524211140.php | 83 + .history/bootstrap/app_20260331095420.php | 20 + .history/bootstrap/app_20260619003314.php | 21 + .history/bootstrap/app_20260619110428.php | 22 + .history/config/services_20240312205242.php | 34 + .history/config/services_20260524193111.php | 39 + .history/config/services_20260524193115.php | 39 + .history/config/services_20260524194140.php | 220 +++ .history/config/services_20260524194142.php | 39 + .history/config/services_20260524194146.php | 35 + .history/config/services_20260524212555.php | 43 + .history/config/services_20260524212557.php | 43 + ...dd_photo_to_users_table_20260401155008.php | 28 + ...dd_photo_to_users_table_20260524185303.php | 38 + ...rs_add_bendahara_fields_20260618215157.php | 24 + ...rs_add_bendahara_fields_20260618215235.php | 118 ++ ...rs_add_bendahara_fields_20260618221428.php | 31 + ...rs_add_bendahara_fields_20260618221432.php | 31 + ...rs_add_bendahara_fields_20260618221434.php | 118 ++ ..._columns_to_users_table_20260618222119.php | 28 + ..._columns_to_users_table_20260618222148.php | 31 + ..._columns_to_users_table_20260618222527.php | 30 + ..._columns_to_iuran_table_20260618223155.php | 28 + ..._columns_to_iuran_table_20260618223253.php | 30 + ...reate_rekap_iuran_table_20260618224251.php | 27 + ...reate_rekap_iuran_table_20260618224306.php | 26 + ...ate_kas_bendahara_table_20260618224444.php | 27 + ...ate_kas_bendahara_table_20260618224454.php | 27 + ...password_to_users_table_20260619104834.php | 28 + ...password_to_users_table_20260619104847.php | 22 + ..._to_kas_bendahara_table_20260619193623.php | 28 + ..._to_kas_bendahara_table_20260619193636.php | 25 + ...php => dashboard.blade_20260622103728.php} | 198 ++- ...php => dashboard.blade_20260622103740.php} | 0 ...php => dashboard.blade_20260622103810.php} | 188 ++- ...php => dashboard.blade_20260622103822.php} | 192 ++- ...php => dashboard.blade_20260622103832.php} | 196 ++- .../iuran/create.blade_20260508232532.php | 577 ------- .../iuran/create.blade_20260508232551.php | 469 ------ ...08.php => create.blade_20260615184627.php} | 2 +- .../iuran/index.blade_20260506111125.php | 447 ----- .../iuran/index.blade_20260510234127.php | 584 ------- ...822.php => index.blade_20260615104315.php} | 7 - ...050.php => index.blade_20260615104328.php} | 14 - ...147.php => index.blade_20260615104705.php} | 16 +- .../iuran/index.blade_20260615104707.php | 644 +++++++ .../iuran/index.blade_20260615175750.php | 649 ++++++++ ...037.php => index.blade_20260615175753.php} | 25 +- .../iuran/index.blade_20260615175809.php | 708 ++++++++ .../iuran/index.blade_20260615190548.php | 711 ++++++++ .../iuran/index.blade_20260615190552.php | 711 ++++++++ .../iuran/index.blade_20260615190652.php | 708 ++++++++ .../iuran/index.blade_20260615190701.php | 711 ++++++++ .../iuran/index.blade_20260615190928.php | 713 ++++++++ .../iuran/index.blade_20260615190931.php | 713 ++++++++ .../laporan/cetak.blade_20260506100551.php | 471 ------ .../laporan/cetak.blade_20260507080224.php | 471 ------ .../laporan/cetak.blade_20260507080226.php | 471 ------ .../laporan/cetak.blade_20260623183140.php | 91 + .../laporan/index.blade_20260506105854.php | 459 ----- .../laporan/index.blade_20260506213904.php | 478 ------ .../laporan/index.blade_20260507090947.php | 612 ------- .../laporan/index.blade_20260507091231.php | 618 ------- .../laporan/index.blade_20260507091242.php | 618 ------- .../laporan/index.blade_20260510230302.php | 493 ------ .../laporan/index.blade_20260510230315.php | 618 ------- .../laporan/index.blade_20260510235120.php | 495 ------ .../laporan/index.blade_20260510235122.php | 618 ------- .../laporan/index.blade_20260510235129.php | 493 ------ .../laporan/index.blade_20260510235145.php | 618 ------- .../laporan/index.blade_20260519181246.php | 575 ------- .../laporan/index.blade_20260623182956.php | 128 ++ .../laporan/index.blade_20260625084758.php | 128 ++ .../layanan/index.blade_20260506111303.php | 475 ------ .../layanan/index.blade_20260510225331.php | 475 ------ .../layanan/index.blade_20260510225333.php | 475 ------ .../layanan/index.blade_20260510225336.php | 475 ------ .../layanan/index.blade_20260510225343.php | 378 ----- .../layanan/index.blade_20260510225403.php | 475 ------ .../layanan/index.blade_20260510234428.php | 378 ----- .../layanan/index.blade_20260510234449.php | 475 ------ .../layanan/index.blade_20260520234535.php | 479 ------ .../layanan/index.blade_20260520234540.php | 479 ------ .../layanan/index.blade_20260521003519.php | 475 ------ .../layanan/index.blade_20260521172813.php | 490 ------ .../layanan/index.blade_20260521172856.php | 491 ------ .../layanan/index.blade_20260521172858.php | 491 ------ .../layanan/index.blade_20260521172917.php | 492 ------ .../layanan/index.blade_20260521172919.php | 492 ------ .../layanan/index.blade_20260521172921.php | 492 ------ .../layanan/index.blade_20260625013700.php | 379 +++++ .../layanan/index.blade_20260627161355.php | 379 +++++ .../penghuni/index.blade_20260506110729.php | 899 ---------- ...657.php => index.blade_20260610223246.php} | 12 +- ...210.php => index.blade_20260610223247.php} | 2 +- .../penghuni/index.blade_20260611091508.php | 1071 ++++++++++++ ...752.php => index.blade_20260611091510.php} | 2 +- .../penghuni/index.blade_20260611091511.php | 1071 ++++++++++++ ...639.php => index.blade_20260611091549.php} | 6 +- .../penghuni/index.blade_20260611092101.php | 1003 +++++++++++ .../penghuni/index.blade_20260614183657.php | 1010 +++++++++++ .../penghuni/index.blade_20260614183701.php | 1010 +++++++++++ .../penghuni/index.blade_20260614184456.php | 1010 +++++++++++ .../penghuni/index.blade_20260614184525.php | 1010 +++++++++++ .../penghuni/index.blade_20260614190013.php | 1025 ++++++++++++ .../penghuni/index.blade_20260614190018.php | 1025 ++++++++++++ .../penghuni/index.blade_20260614191551.php | 1033 ++++++++++++ .../penghuni/index.blade_20260614191620.php | 1037 ++++++++++++ .../penghuni/index.blade_20260614191625.php | 1037 ++++++++++++ .../penghuni/index.blade_20260614191641.php | 1054 ++++++++++++ .../penghuni/index.blade_20260614191646.php | 1054 ++++++++++++ .../penghuni/index.blade_20260614191648.php | 1054 ++++++++++++ .../penghuni/index.blade_20260614191916.php | 1060 ++++++++++++ .../penghuni/index.blade_20260614191919.php | 1054 ++++++++++++ .../penghuni/index.blade_20260614191920.php | 1060 ++++++++++++ .../penghuni/index.blade_20260614191926.php | 1060 ++++++++++++ .../penghuni/index.blade_20260614191927.php | 1060 ++++++++++++ .../penghuni/index.blade_20260614192034.php | 1064 ++++++++++++ .../penghuni/index.blade_20260614192106.php | 1060 ++++++++++++ .../penghuni/index.blade_20260614192108.php | 1060 ++++++++++++ .../penghuni/index.blade_20260614192114.php | 1054 ++++++++++++ .../penghuni/index.blade_20260614192125.php | 1054 ++++++++++++ .../penghuni/index.blade_20260614192128.php | 1054 ++++++++++++ .../penghuni/index.blade_20260614192130.php | 1054 ++++++++++++ .../penghuni/index.blade_20260614192133.php | 1060 ++++++++++++ .../penghuni/index.blade_20260614192137.php | 1054 ++++++++++++ ...722.php => index.blade_20260614192155.php} | 377 ++--- .../penghuni/index.blade_20260614192158.php | 1060 ++++++++++++ .../penghuni/index.blade_20260614192200.php | 1060 ++++++++++++ .../penghuni/index.blade_20260614192210.php | 1064 ++++++++++++ .../penghuni/index.blade_20260614192314.php | 1060 ++++++++++++ .../penghuni/index.blade_20260614192318.php | 1054 ++++++++++++ .../penghuni/index.blade_20260614192321.php | 1060 ++++++++++++ .../penghuni/index.blade_20260614192322.php | 1054 ++++++++++++ .../penghuni/index.blade_20260614192335.php | 1060 ++++++++++++ .../penghuni/index.blade_20260614192340.php | 1060 ++++++++++++ .../penghuni/index.blade_20260614193806.php | 1076 ++++++++++++ .../penghuni/index.blade_20260614193929.php | 1130 +++++++++++++ .../penghuni/index.blade_20260614193941.php | 1130 +++++++++++++ .../penghuni/index.blade_20260614194150.php | 1128 +++++++++++++ .../penghuni/index.blade_20260614194233.php | 1173 +++++++++++++ .../penghuni/index.blade_20260614194701.php | 1190 +++++++++++++ .../penghuni/index.blade_20260614194702.php | 1173 +++++++++++++ .../penghuni/index.blade_20260614194744.php | 1187 +++++++++++++ .../penghuni/index.blade_20260614194748.php | 1187 +++++++++++++ .../penghuni/index.blade_20260614194829.php | 1188 +++++++++++++ .../penghuni/index.blade_20260614194835.php | 1188 +++++++++++++ .../penghuni/index.blade_20260614194837.php | 1188 +++++++++++++ .../penghuni/index.blade_20260614194909.php | 1202 ++++++++++++++ .../penghuni/index.blade_20260614194914.php | 1202 ++++++++++++++ .../penghuni/index.blade_20260614194918.php | 1202 ++++++++++++++ .../penghuni/index.blade_20260614194922.php | 1202 ++++++++++++++ .../penghuni/index.blade_20260614194938.php | 1203 ++++++++++++++ .../penghuni/index.blade_20260614194943.php | 1203 ++++++++++++++ .../penghuni/index.blade_20260614195056.php | 1202 ++++++++++++++ .../penghuni/index.blade_20260614195100.php | 1202 ++++++++++++++ .../penghuni/index.blade_20260614195112.php | 1202 ++++++++++++++ .../penghuni/index.blade_20260614195114.php | 1203 ++++++++++++++ .../penghuni/index.blade_20260614195121.php | 1203 ++++++++++++++ .../penghuni/index.blade_20260614195124.php | 1203 ++++++++++++++ .../penghuni/index.blade_20260614195135.php | 1204 ++++++++++++++ .../penghuni/index.blade_20260614195139.php | 1204 ++++++++++++++ .../penghuni/index.blade_20260614195140.php | 1204 ++++++++++++++ .../penghuni/index.blade_20260614195144.php | 1203 ++++++++++++++ .../penghuni/index.blade_20260614195155.php | 1204 ++++++++++++++ .../penghuni/index.blade_20260614195159.php | 1204 ++++++++++++++ .../penghuni/index.blade_20260614195203.php | 1203 ++++++++++++++ .../penghuni/index.blade_20260614195252.php | 1203 ++++++++++++++ .../penghuni/index.blade_20260614195420.php | 1213 ++++++++++++++ .../penghuni/index.blade_20260614195555.php | 1203 ++++++++++++++ .../penghuni/index.blade_20260614195609.php | 1200 +++++++++++++ .../penghuni/index.blade_20260614203424.php | 1210 ++++++++++++++ .../auth/forgot.blade_20260524190438.php | 181 ++ .../auth/forgot.blade_20260524190440.php | 181 ++ .../auth/forgot.blade_20260524190442.php | 485 ++++++ .../auth/forgot.blade_20260524190443.php | 181 ++ .../auth/forgot.blade_20260524191350.php | 181 ++ .../auth/forgot.blade_20260524191401.php | 181 ++ .../auth/forgot.blade_20260524191407.php | 181 ++ .../auth/forgot.blade_20260524191410.php | 181 ++ .../auth/forgot.blade_20260524194211.php | 220 +++ .../auth/forgot.blade_20260524194219.php | 220 +++ .../auth/forgot.blade_20260524194221.php | 219 +++ .../auth/forgot.blade_20260524202012.php | 207 +++ .../auth/forgot.blade_20260524212609.php | 197 +++ .../form.blade_20260619111322.php | 0 .../form.blade_20260619111440.php | 35 + .../form.blade_20260627101006.php | 200 +++ .../iuran/create.blade_20260619093318.php | 54 + .../iuran/create.blade_20260619113234.php | 54 + .../iuran/create.blade_20260622094230.php | 61 + .../iuran/create.blade_20260627101335.php | 233 +++ .../iuran/edit.blade_20260619093340.php | 60 + .../iuran/edit.blade_20260619113228.php | 60 + .../iuran/edit.blade_20260622094249.php | 65 + .../iuran/edit.blade_20260627101457.php | 240 +++ .../iuran/index.blade_20260619093140.php | 62 + .../iuran/index.blade_20260619113221.php | 62 + .../iuran/index.blade_20260620092157.php | 63 + .../iuran/index.blade_20260620092210.php | 63 + .../iuran/index.blade_20260620092541.php | 73 + .../iuran/index.blade_20260620092543.php | 64 + .../iuran/index.blade_20260620092553.php | 70 + .../iuran/index.blade_20260620132629.php | 76 + .../iuran/index.blade_20260627101630.php | 328 ++++ .../create-tagihan.blade_20260619213138.php | 0 .../create-tagihan.blade_20260619213158.php | 30 + .../create-tagihan.blade_20260627101841.php | 215 +++ .../kas/index.blade_20260619190357.php | 0 .../kas/index.blade_20260619190413.php | 90 + .../kas/index.blade_20260619213355.php | 101 ++ .../kas/index.blade_20260620081741.php | 101 ++ .../kas/index.blade_20260620081754.php | 144 ++ .../kas/index.blade_20260627102131.php | 448 +++++ .../rekap/index.blade_20260619100932.php | 0 .../rekap/index.blade_20260619100938.php | 91 + .../rekap/index.blade_20260620091153.php | 92 + .../rekap/index.blade_20260620091214.php | 92 + .../rekap/index.blade_20260620091234.php | 91 + .../rekap/index.blade_20260620091335.php | 92 + .../rekap/index.blade_20260620091337.php | 92 + .../rekap/index.blade_20260620091448.php | 99 ++ .../rekap/index.blade_20260620091452.php | 99 ++ .../rekap/index.blade_20260620091517.php | 92 + .../rekap/index.blade_20260620091519.php | 91 + .../rekap/index.blade_20260627102508.php | 387 +++++ .../rekap/show.blade_20260619101010.php | 0 .../rekap/show.blade_20260619101020.php | 43 + .../rekap/show.blade_20260627102818.php | 92 + .../rekap/show.blade_20260627103021.php | 92 + .../rekap/show.blade_20260627103043.php | 312 ++++ .../rekap/show.blade_20260627103219.php | 312 ++++ .../rekap/show.blade_20260627103231.php | 312 ++++ .../rekap/show.blade_20260627103235.php | 312 ++++ .../rekap/show.blade_20260627103237.php | 312 ++++ .../rekap/show.blade_20260627103307.php | 312 ++++ .../rekap/show.blade_20260627103342.php | 312 ++++ .../rekap/show.blade_20260627103344.php | 312 ++++ .../rekap/show.blade_20260627103345.php | 312 ++++ .../rekap/show.blade_20260627103347.php | 312 ++++ .../sidebar.blade_20260506102833.php | 574 ------- .../sidebar.blade_20260506212056.php | 791 --------- .../sidebar.blade_20260507154036.php | 791 --------- .../sidebar.blade_20260507154043.php | 791 --------- .../sidebar.blade_20260507154047.php | 791 --------- .../sidebar.blade_20260516015132.php | 791 --------- .../sidebar.blade_20260516015145.php | 791 --------- .../sidebar.blade_20260516015155.php | 791 --------- .../sidebar.blade_20260516015204.php | 791 --------- ...5.php => sidebar.blade_20260622095045.php} | 4 +- ...1.php => sidebar.blade_20260627161521.php} | 11 +- ...8.php => sidebar.blade_20260627161523.php} | 11 +- .../sidebar.blade_20260627161729.php | 452 +++++ .../sidebar.blade_20260627161731.php | 452 +++++ ...sidebar_bendahara.blade_20260619094101.php | 0 ...sidebar_bendahara.blade_20260619094109.php | 94 ++ ...idebar_bendahara.blade_20260619113715.php} | 91 +- ...sidebar_bendahara.blade_20260619113717.php | 94 ++ ...sidebar_bendahara.blade_20260619113719.php | 345 ++++ ...sidebar_bendahara.blade_20260619190807.php | 346 ++++ ...idebar_bendahara.blade_20260619190808.php} | 91 +- ...sidebar_bendahara.blade_20260619190811.php | 345 ++++ ...idebar_bendahara.blade_20260619190814.php} | 91 +- ...idebar_bendahara.blade_20260619190815.php} | 91 +- ...sidebar_bendahara.blade_20260619213311.php | 351 ++++ ...sidebar_bendahara.blade_20260627141538.php | 505 ++++++ ...sidebar_bendahara.blade_20260627141631.php | 351 ++++ ...sidebar_bendahara.blade_20260627141641.php | 505 ++++++ ...sidebar_bendahara.blade_20260627141644.php | 351 ++++ ...sidebar_bendahara.blade_20260627141646.php | 505 ++++++ ...sidebar_bendahara.blade_20260627141815.php | 509 ++++++ ...sidebar_bendahara.blade_20260627141817.php | 505 ++++++ ...sidebar_bendahara.blade_20260627141849.php | 501 ++++++ ...sidebar_bendahara.blade_20260627141900.php | 501 ++++++ ...sidebar_bendahara.blade_20260627141908.php | 502 ++++++ ...sidebar_bendahara.blade_20260627141909.php | 505 ++++++ ...sidebar_bendahara.blade_20260627141917.php | 501 ++++++ ...sidebar_bendahara.blade_20260627141937.php | 501 ++++++ ...sidebar_bendahara.blade_20260627141958.php | 501 ++++++ ...sidebar_bendahara.blade_20260627142004.php | 501 ++++++ ...sidebar_bendahara.blade_20260627142018.php | 501 ++++++ ...sidebar_bendahara.blade_20260627142034.php | 501 ++++++ ...sidebar_bendahara.blade_20260627142051.php | 501 ++++++ ...sidebar_bendahara.blade_20260627142053.php | 501 ++++++ ...sidebar_bendahara.blade_20260627142057.php | 501 ++++++ ...sidebar_bendahara.blade_20260627142100.php | 501 ++++++ ...sidebar_bendahara.blade_20260627142113.php | 501 ++++++ ...sidebar_bendahara.blade_20260627142114.php | 501 ++++++ ...sidebar_bendahara.blade_20260627142118.php | 501 ++++++ ...sidebar_bendahara.blade_20260627142121.php | 501 ++++++ ...sidebar_bendahara.blade_20260627142124.php | 501 ++++++ ...sidebar_bendahara.blade_20260627142127.php | 501 ++++++ ...sidebar_bendahara.blade_20260627142132.php | 501 ++++++ .../sidebar_rt.blade_20260506103149.php | 540 ------ .../sidebar_rt.blade_20260506220429.php | 755 --------- .../sidebar_rt.blade_20260507165948.php | 767 --------- .../sidebar_rt.blade_20260507170159.php | 767 --------- .../sidebar_rt.blade_20260507170317.php | 767 --------- .../sidebar_rt.blade_20260507170336.php | 767 --------- .../sidebar_rt.blade_20260507170348.php | 767 --------- .../sidebar_rt.blade_20260507170357.php | 767 --------- .../sidebar_rt.blade_20260507170407.php | 767 --------- .../sidebar_rt.blade_20260507170419.php | 766 --------- .../sidebar_rt.blade_20260507170426.php | 766 --------- .../sidebar_rt.blade_20260520233032.php | 408 ----- .../sidebar_rt.blade_20260520233103.php | 408 ----- .../sidebar_rt.blade_20260520233212.php | 408 ----- .../sidebar_rt.blade_20260520233217.php | 408 ----- .../sidebar_rt.blade_20260520233236.php | 408 ----- .../sidebar_rt.blade_20260520233429.php | 409 ----- .../sidebar_rt.blade_20260520233432.php | 409 ----- .../sidebar_rt.blade_20260520233434.php | 409 ----- .../sidebar_rt.blade_20260520233440.php | 409 ----- .../sidebar_rt.blade_20260520233443.php | 409 ----- ...hp => sidebar_rt.blade_20260619103922.php} | 7 + ...hp => sidebar_rt.blade_20260619114913.php} | 9 + ...hp => sidebar_rt.blade_20260619114915.php} | 23 +- ...hp => sidebar_rt.blade_20260619183033.php} | 8 + .../sidebar_rt.blade_20260619183041.php | 428 +++++ .../sidebar_rt.blade_20260619183047.php | 428 +++++ .../sidebar_rt.blade_20260619190553.php | 433 +++++ .../sidebar_rt.blade_20260627142705.php | 557 +++++++ ...pengaduan_selesai.blade_20260625013913.php | 0 ...pengaduan_selesai.blade_20260625013920.php | 80 + .../layouts/app.blade_20260506014525.php | 864 ---------- .../layouts/app.blade_20260507171636.php | 822 --------- ...75911.php => app.blade_20260619094017.php} | 5 + .../bendahara/index.blade_20260619090821.php | 0 .../bendahara/index.blade_20260619090951.php | 98 ++ .../bendahara/index.blade_20260619104014.php | 98 ++ .../bendahara/index.blade_20260619110237.php | 93 ++ .../bendahara/index.blade_20260627140505.php | 428 +++++ .../bendahara/index.blade_20260627163811.php | 428 +++++ .../iuran/create.blade_20260619093205.php | 0 .../iuran/create.blade_20260619093319.php | 54 + .../iuran/edit.blade_20260619093333.php | 0 .../iuran/edit.blade_20260619093341.php | 60 + .../iuran/index.blade_20260619093119.php | 0 .../iuran/index.blade_20260619093122.php | 1 + .../iuran/index.blade_20260619093125.php | 1 + .../iuran/index.blade_20260619093127.php | 0 .../iuran/index.blade_20260619093141.php | 62 + .../rt/dashboard.blade_20260506090847.php | 533 ------ .../rt/dashboard.blade_20260507082949.php | 557 ------- .../rt/dashboard.blade_20260507083054.php | 557 ------- .../rt/dashboard.blade_20260507083056.php | 533 ------ .../rt/dashboard.blade_20260507083323.php | 542 ------ .../rt/dashboard.blade_20260507083342.php | 714 -------- ...php => dashboard.blade_20260615104851.php} | 333 ++-- ...php => dashboard.blade_20260615105018.php} | 0 ...php => dashboard.blade_20260622100005.php} | 430 +++-- .../rt/dashboard.blade_20260622100338.php | 790 +++++++++ .../rt/dashboard.blade_20260622100411.php | 790 +++++++++ ...php => dashboard.blade_20260622100426.php} | 430 +++-- .../rt/dashboard.blade_20260622100428.php | 790 +++++++++ .../rt/dashboard.blade_20260622100455.php | 790 +++++++++ .../rt/dashboard.blade_20260622100456.php | 790 +++++++++ ...php => dashboard.blade_20260622100458.php} | 431 +++-- .../rt/dashboard.blade_20260622100504.php | 790 +++++++++ .../rt/dashboard.blade_20260622100506.php | 790 +++++++++ .../rt/dashboard.blade_20260622100511.php | 790 +++++++++ .../rt/dashboard.blade_20260622100528.php | 790 +++++++++ .../rt/dashboard.blade_20260622100534.php | 790 +++++++++ .../rt/dashboard.blade_20260622100544.php | 790 +++++++++ .../rt/dashboard.blade_20260622101022.php | 873 ++++++++++ .../rt/dashboard.blade_20260622101030.php | 790 +++++++++ ...php => dashboard.blade_20260622101118.php} | 511 +++--- ...php => dashboard.blade_20260622101125.php} | 511 +++--- .../rt/dashboard.blade_20260622101130.php | 764 +++++++++ .../rt/dashboard.blade_20260622101239.php | 793 +++++++++ .../rt/dashboard.blade_20260622101448.php | 764 +++++++++ .../rt/dashboard.blade_20260627162322.php | 469 ++++++ .../rt/kas/index.blade_20260619190446.php | 0 .../rt/kas/index.blade_20260619190452.php | 68 + .../rt/kas/index.blade_20260627140230.php | 324 ++++ .../rt/laporan/cetak.blade_20260625083149.php | 0 .../rt/laporan/cetak.blade_20260625083156.php | 206 +++ .../rt/laporan/index.blade_20260623182820.php | 0 .../rt/laporan/index.blade_20260623182826.php | 211 +++ .../rt/laporan/index.blade_20260625084727.php | 128 ++ .../rt/laporan/index.blade_20260625084737.php | 211 +++ .../rt/laporan/index.blade_20260627163336.php | 1 + .../rt/laporan/index.blade_20260627163339.php | 1 + .../rt/laporan/index.blade_20260627163343.php | 480 ++++++ .../penghuni/index.blade_20260506174552.php | 271 --- .../penghuni/index.blade_20260510233610.php | 412 ----- ...950.php => index.blade_20260615171252.php} | 129 +- ...607.php => index.blade_20260615171422.php} | 220 ++- ...338.php => index.blade_20260615171426.php} | 263 +-- ...940.php => index.blade_20260615171429.php} | 265 +-- .../index.blade_20260619093431.php | 0 .../index.blade_20260619093445.php | 72 + .../index.blade_20260619114950.php | 72 + .../index.blade_20260627133706.php | 406 +++++ .../index.blade_20260627133733.php | 72 + .../index.blade_20260627133740.php | 406 +++++ .../index.blade_20260619101253.php | 0 .../index.blade_20260619101300.php | 38 + .../index.blade_20260620133220.php | 34 + .../index.blade_20260620135156.php | 38 + .../index.blade_20260620135203.php | 38 + .../index.blade_20260627134958.php | 272 +++ .../show.blade_20260619101312.php | 0 .../show.blade_20260619101319.php | 67 + .../show.blade_20260620133229.php | 38 + .../show.blade_20260620135212.php | 67 + .../show.blade_20260627135513.php | 420 +++++ ...743.php => index.blade_20260615171039.php} | 54 +- ...842.php => index.blade_20260615171041.php} | 0 ...723.php => index.blade_20260615171058.php} | 55 +- .../rt/rumah/index.blade_20260615171119.php | 286 ++++ .../user/iuran/index.blade_20260505200948.php | 265 --- .../user/iuran/index.blade_20260507172115.php | 264 --- .../user/iuran/index.blade_20260507172523.php | 375 ----- .../user/iuran/index.blade_20260511031518.php | 375 ----- .../user/iuran/index.blade_20260511031534.php | 322 ---- .../user/iuran/index.blade_20260511031548.php | 322 ---- .../user/iuran/index.blade_20260511031605.php | 375 ----- .../user/iuran/index.blade_20260521101154.php | 375 ----- .../user/iuran/index.blade_20260521101158.php | 375 ----- .../user/iuran/index.blade_20260521101228.php | 375 ----- .../user/iuran/index.blade_20260521101326.php | 379 ----- .../user/iuran/index.blade_20260521101331.php | 379 ----- .../user/iuran/index.blade_20260521101335.php | 379 ----- .../user/iuran/index.blade_20260521101337.php | 379 ----- .../user/iuran/index.blade_20260521101339.php | 379 ----- ...505.php => index.blade_20260529171547.php} | 2 +- ...503.php => index.blade_20260529171548.php} | 3 +- ...451.php => index.blade_20260529171554.php} | 3 +- ...447.php => index.blade_20260529171645.php} | 35 +- .../user/iuran/index.blade_20260615180336.php | 386 +++++ .../user/iuran/index.blade_20260615180340.php | 386 +++++ .../user/iuran/index.blade_20260615180342.php | 384 +++++ .../user/iuran/index.blade_20260615180346.php | 385 +++++ .../user/iuran/index.blade_20260615180349.php | 385 +++++ .../user/iuran/index.blade_20260615180351.php | 385 +++++ .../user/iuran/index.blade_20260615180548.php | 389 +++++ .../user/iuran/index.blade_20260615180556.php | 389 +++++ .../user/iuran/index.blade_20260615180557.php | 389 +++++ ...329.php => index.blade_20260619213834.php} | 82 +- .../user/iuran/index.blade_20260619213843.php | 428 +++++ .../user/iuran/index.blade_20260619214028.php | 450 +++++ .../user/iuran/index.blade_20260619214117.php | 451 +++++ .../user/iuran/index.blade_20260619214118.php | 451 +++++ .../user/iuran/index.blade_20260619214129.php | 451 +++++ .../user/iuran/index.blade_20260619214137.php | 451 +++++ .../user/iuran/index.blade_20260619214155.php | 450 +++++ .../user/iuran/index.blade_20260619214210.php | 452 +++++ .../user/iuran/index.blade_20260619214211.php | 467 ++++++ .../user/iuran/index.blade_20260619214753.php | 466 ++++++ .../user/iuran/index.blade_20260619214757.php | 467 ++++++ .../user/iuran/index.blade_20260619214800.php | 466 ++++++ .../user/iuran/index.blade_20260620083132.php | 446 +++++ .../user/iuran/index.blade_20260620083206.php | 467 ++++++ .../user/iuran/index.blade_20260620083211.php | 467 ++++++ .../user/iuran/index.blade_20260620083327.php | 448 +++++ .../user/iuran/index.blade_20260620083329.php | 446 +++++ .../user/iuran/index.blade_20260620083331.php | 445 +++++ .../user/iuran/index.blade_20260620083333.php | 446 +++++ .../user/iuran/index.blade_20260620083346.php | 915 ++++++++++ .../user/iuran/index.blade_20260620083351.php | 448 +++++ .../user/iuran/index.blade_20260620083357.php | 467 ++++++ .../user/iuran/index.blade_20260620083405.php | 467 ++++++ .../user/iuran/index.blade_20260620083503.php | 446 +++++ .../user/iuran/index.blade_20260620083623.php | 466 ++++++ .../user/iuran/index.blade_20260620083700.php | 467 ++++++ .../user/iuran/index.blade_20260620083703.php | 467 ++++++ .../user/iuran/index.blade_20260620084052.php | 466 ++++++ .../user/iuran/index.blade_20260620084332.php | 430 +++++ .../user/iuran/index.blade_20260620084404.php | 500 ++++++ .../user/iuran/index.blade_20260620084410.php | 498 ++++++ .../user/iuran/index.blade_20260620084639.php | 499 ++++++ .../user/iuran/index.blade_20260620084644.php | 499 ++++++ .../user/iuran/index.blade_20260620084645.php | 499 ++++++ .../user/iuran/index.blade_20260620084653.php | 499 ++++++ .../user/iuran/index.blade_20260620084714.php | 497 ++++++ .../user/iuran/index.blade_20260620084830.php | 492 ++++++ .../user/iuran/index.blade_20260620084913.php | 497 ++++++ .../user/iuran/index.blade_20260620141427.php | 497 ++++++ .../user/iuran/index.blade_20260620141431.php | 497 ++++++ .../user/iuran/index.blade_20260620141437.php | 497 ++++++ .../user/iuran/index.blade_20260620141438.php | 497 ++++++ .../user/iuran/index.blade_20260620141440.php | 497 ++++++ .../user/iuran/index.blade_20260620141441.php | 497 ++++++ .../user/iuran/index.blade_20260622094706.php | 502 ++++++ .../user/iuran/index.blade_20260627170632.php | 588 +++++++ .../user/iuran/index.blade_20260627170650.php | 588 +++++++ .../iuran/upload.blade_20260505210628.php | 634 +++++++ .../iuran/upload.blade_20260615180656.php | 650 ++++++++ .../iuran/upload.blade_20260615180708.php | 650 ++++++++ .../user/kas/upload.blade_20260619213231.php | 0 .../user/kas/upload.blade_20260619213238.php | 16 + .../user/kas/upload.blade_20260620085228.php | 198 +++ .../layanan/status.blade_20260505213925.php | 657 ++++++++ .../layanan/status.blade_20260625013734.php | 269 +++ .../views/user/rumah.blade_20260511001052.php | 1373 --------------- .../views/user/rumah.blade_20260511001108.php | 1373 --------------- .../views/user/rumah.blade_20260511001118.php | 1373 --------------- .../views/user/rumah.blade_20260511001137.php | 1358 --------------- .../views/user/rumah.blade_20260511001201.php | 1296 --------------- .../views/user/rumah.blade_20260511001216.php | 1119 ------------- ...605.php => rumah.blade_20260521212139.php} | 26 +- ...231.php => rumah.blade_20260521212151.php} | 26 +- ...037.php => rumah.blade_20260521212225.php} | 47 +- ...102.php => rumah.blade_20260521212229.php} | 318 ++-- .../views/user/rumah.blade_20260521213605.php | 1375 +++++++++++++++ .../views/user/rumah.blade_20260521213610.php | 1375 +++++++++++++++ .../views/user/rumah.blade_20260530182842.php | 1398 ++++++++++++++++ .../views/user/rumah.blade_20260530182917.php | 1375 +++++++++++++++ .../views/user/rumah.blade_20260530182925.php | 1398 ++++++++++++++++ .../views/user/rumah.blade_20260530182932.php | 1375 +++++++++++++++ .../views/user/rumah.blade_20260530182937.php | 1398 ++++++++++++++++ .../views/user/rumah.blade_20260530184903.php | 1433 ++++++++++++++++ .../views/user/rumah.blade_20260530184906.php | 1433 ++++++++++++++++ .../views/user/rumah.blade_20260614200048.php | 1450 ++++++++++++++++ .../views/user/rumah.blade_20260614200057.php | 1450 ++++++++++++++++ .../views/user/rumah.blade_20260614200225.php | 1458 ++++++++++++++++ .../views/user/rumah.blade_20260614200235.php | 1458 ++++++++++++++++ .../views/user/rumah.blade_20260614200259.php | 1459 ++++++++++++++++ .../views/user/rumah.blade_20260614200301.php | 1463 ++++++++++++++++ .../views/user/rumah.blade_20260614200303.php | 1459 ++++++++++++++++ .../views/user/rumah.blade_20260614200304.php | 1459 ++++++++++++++++ .../views/user/rumah.blade_20260614200306.php | 1458 ++++++++++++++++ .../views/user/rumah.blade_20260614200320.php | 1460 ++++++++++++++++ .../views/user/rumah.blade_20260614200324.php | 1458 ++++++++++++++++ .../views/user/rumah.blade_20260614200342.php | 1459 ++++++++++++++++ .../views/user/rumah.blade_20260614200349.php | 1459 ++++++++++++++++ .../views/user/rumah.blade_20260614200628.php | 1478 +++++++++++++++++ .../views/user/rumah.blade_20260614200636.php | 1478 +++++++++++++++++ .../views/user/rumah.blade_20260614200719.php | 1478 +++++++++++++++++ .../views/user/rumah.blade_20260614200723.php | 1478 +++++++++++++++++ .../views/user/rumah.blade_20260614200804.php | 1478 +++++++++++++++++ .../views/user/rumah.blade_20260614200808.php | 1478 +++++++++++++++++ .../views/user/rumah.blade_20260614202400.php | 1476 ++++++++++++++++ .../views/user/rumah.blade_20260614202422.php | 1476 ++++++++++++++++ .../views/user/rumah.blade_20260614202622.php | 1478 +++++++++++++++++ .../views/user/rumah.blade_20260614202624.php | 1478 +++++++++++++++++ .../views/user/rumah.blade_20260614202626.php | 1478 +++++++++++++++++ .../views/user/rumah.blade_20260614202629.php | 1476 ++++++++++++++++ .../views/user/rumah.blade_20260614202632.php | 1476 ++++++++++++++++ .../views/user/rumah.blade_20260614202636.php | 1476 ++++++++++++++++ .../views/user/rumah.blade_20260614202638.php | 1478 +++++++++++++++++ .../views/user/rumah.blade_20260614202718.php | 1386 ++++++++++++++++ .../views/user/rumah.blade_20260614202937.php | 1472 ++++++++++++++++ .history/routes/web_20260520130451.php | 215 --- .history/routes/web_20260520225300.php | 218 --- .history/routes/web_20260520225304.php | 217 --- .history/routes/web_20260520231651.php | 203 --- .history/routes/web_20260520231712.php | 217 --- .history/routes/web_20260520232111.php | 203 --- .history/routes/web_20260520232144.php | 217 --- .history/routes/web_20260520232604.php | 218 --- .history/routes/web_20260520232630.php | 217 --- .history/routes/web_20260520232913.php | 220 --- .history/routes/web_20260520233138.php | 221 --- .history/routes/web_20260520233343.php | 222 --- .history/routes/web_20260520234406.php | 225 --- .history/routes/web_20260520234408.php | 224 --- .history/routes/web_20260520234411.php | 224 --- .history/routes/web_20260520234412.php | 224 --- .history/routes/web_20260521002413.php | 224 --- ...60521003138.php => web_20260615175706.php} | 10 + ...60506190711.php => web_20260615175712.php} | 10 + .history/routes/web_20260619003354.php | 342 ++++ .history/routes/web_20260619003355.php | 344 ++++ .history/routes/web_20260619090711.php | 351 ++++ .history/routes/web_20260619091403.php | 355 ++++ .history/routes/web_20260619091405.php | 355 ++++ .history/routes/web_20260619091429.php | 356 ++++ .history/routes/web_20260619100048.php | 355 ++++ .history/routes/web_20260619100050.php | 351 ++++ .history/routes/web_20260619100052.php | 356 ++++ .history/routes/web_20260619100111.php | 357 ++++ .history/routes/web_20260619100112.php | 359 ++++ .history/routes/web_20260619100119.php | 359 ++++ .history/routes/web_20260619100140.php | 363 ++++ .history/routes/web_20260619103632.php | 367 ++++ .history/routes/web_20260619103636.php | 367 ++++ .history/routes/web_20260619110515.php | 368 ++++ .history/routes/web_20260619110520.php | 366 ++++ .history/routes/web_20260619111140.php | 372 +++++ .history/routes/web_20260619190122.php | 374 +++++ .history/routes/web_20260619190125.php | 374 +++++ .history/routes/web_20260619190235.php | 376 +++++ .history/routes/web_20260619190237.php | 376 +++++ .history/routes/web_20260619212831.php | 378 +++++ .history/routes/web_20260619212833.php | 380 +++++ .history/routes/web_20260619212847.php | 381 +++++ .history/routes/web_20260619212850.php | 381 +++++ .history/routes/web_20260619212856.php | 380 +++++ .history/routes/web_20260619212900.php | 381 +++++ .history/routes/web_20260619212907.php | 381 +++++ .history/routes/web_20260619212930.php | 382 +++++ .history/routes/web_20260619212937.php | 382 +++++ .history/routes/web_20260619214532.php | 386 +++++ .history/routes/web_20260620132444.php | 388 +++++ .history/routes/web_20260620132729.php | 386 +++++ .history/routes/web_20260620135103.php | 388 +++++ .history/routes/web_20260620143722.php | 388 +++++ .history/routes/web_20260620143724.php | 387 +++++ .history/routes/web_20260624224135.php | 389 +++++ .history/routes/web_20260624224233.php | 387 +++++ .history/routes/web_20260625013633.php | 387 +++++ app/Http/Controllers/Admin/UserController.php | 2 +- app/Http/Controllers/AuthController.php | 168 +- .../Bendahara/GantiPasswordController.php | 46 + .../Controllers/Bendahara/IuranController.php | 125 ++ .../Controllers/Bendahara/KasController.php | 106 ++ .../Controllers/Bendahara/RekapController.php | 66 + app/Http/Controllers/IuranController.php | 127 +- app/Http/Controllers/LaporanController.php | 117 +- app/Http/Controllers/LayananController.php | 361 ++-- app/Http/Controllers/PenghuniController.php | 101 +- .../Controllers/RT/BendaharaController.php | 76 + app/Http/Controllers/RT/KasRTController.php | 27 + .../Controllers/RT/ReviewIuranController.php | 77 + .../Controllers/RT/ReviewRekapController.php | 78 + app/Http/Controllers/UserController.php | 24 +- app/Http/Controllers/UserIuranController.php | 39 +- app/Http/Controllers/UserKasController.php | 48 + app/Http/Controllers/dashboardController.php | 87 +- app/Http/Middleware/CheckRole.php | 23 + app/Http/Middleware/CheckStatusAkun.php | 21 + app/Http/Middleware/ForcePasswordChange.php | 25 + app/Mail/NotifPengaduan.php | 9 +- app/Mail/NotifPengaduanSelesai.php | 21 + app/Models/Iuran.php | 19 +- app/Models/KasBendahara.php | 38 + app/Models/Layanan.php | 7 +- app/Models/RekapIuran.php | 33 + app/Models/User.php | 42 +- app/Services/WhatsappService.php | 83 + bootstrap/app.php | 2 + config/services.php | 9 + ..._04_01_084939_add_photo_to_users_table.php | 32 +- ...0_add_bendahara_columns_to_users_table.php | 30 + ...6_add_bendahara_columns_to_iuran_table.php | 30 + ..._06_18_224252_create_rekap_iuran_table.php | 26 + ...6_18_224445_create_kas_bendahara_table.php | 27 + ...dd_wajib_ganti_password_to_users_table.php | 22 + ...tagihan_columns_to_kas_bendahara_table.php | 25 + public/bukti/1781494398.jpeg | Bin 0 -> 201476 bytes public/bukti/1781495172.png | Bin 0 -> 438264 bytes public/bukti/1781524095.jpeg | Bin 0 -> 1193569 bytes public/bukti/1781765374.png | Bin 0 -> 333662 bytes public/bukti/1781867951.jpeg | Bin 0 -> 119704 bytes public/bukti/1781920365_kas.jpeg | Bin 0 -> 238460 bytes public/bukti/1781920711.jpeg | Bin 0 -> 146672 bytes public/bukti/1781921394.jpeg | Bin 0 -> 74347 bytes public/bukti/1781939498.jpeg | Bin 0 -> 93622 bytes public/bukti/1782219223.jpeg | Bin 0 -> 49421 bytes public/bukti/1782219503_kas.png | Bin 0 -> 1140269 bytes public/bukti/1782308827.png | Bin 0 -> 89838 bytes public/bukti/1782308961_kas.png | Bin 0 -> 37142 bytes public/foto_rumah/1779372927.jpeg | Bin 0 -> 161338 bytes public/informasi/1780985587.jpg | Bin 0 -> 69196 bytes public/informasi/1780985792.jpg | Bin 0 -> 69196 bytes public/informasi/1781766199.jpg | Bin 0 -> 69196 bytes public/qris/qris_baru.png | Bin 0 -> 48135 bytes public/qris/qris_code_clean.jpg | Bin 0 -> 185406 bytes resources/views/admin/dashboard.blade.php | 4 +- resources/views/admin/iuran/create.blade.php | 2 +- resources/views/admin/iuran/index.blade.php | 91 +- resources/views/admin/laporan/cetak.blade.php | 520 +----- resources/views/admin/laporan/index.blade.php | 673 ++------ resources/views/admin/layanan/index.blade.php | 679 ++++---- .../views/admin/penghuni/index.blade.php | 735 ++++---- resources/views/auth/forgot.blade.php | 538 ++---- resources/views/bendahara - Shortcut.lnk | Bin 0 -> 1372 bytes .../bendahara/ganti-password/form.blade.php | 200 +++ .../views/bendahara/iuran/create.blade.php | 233 +++ .../views/bendahara/iuran/edit.blade.php | 240 +++ .../views/bendahara/iuran/index.blade.php | 328 ++++ .../bendahara/kas/create-tagihan.blade.php | 215 +++ resources/views/bendahara/kas/index.blade.php | 448 +++++ .../views/bendahara/rekap/index.blade.php | 387 +++++ .../views/bendahara/rekap/show.blade.php | 312 ++++ resources/views/components/sidebar.blade.php | 880 +++------- .../components/sidebar_bendahara.blade.php | 501 ++++++ .../views/components/sidebar_rt.blade.php | 313 +++- .../views/emails/pengaduan_selesai.blade.php | 80 + resources/views/layouts/app.blade.php | 5 + resources/views/rt/bendahara/index.blade.php | 428 +++++ resources/views/rt/dashboard.blade.php | 1080 +++++------- resources/views/rt/kas/index.blade.php | 324 ++++ resources/views/rt/laporan/cetak.blade.php | 206 +++ resources/views/rt/laporan/index.blade.php | 480 ++++++ resources/views/rt/penghuni/index.blade.php | 265 +-- .../views/rt/review-iuran/index.blade.php | 406 +++++ .../views/rt/review-rekap/index.blade.php | 272 +++ .../views/rt/review-rekap/show.blade.php | 420 +++++ resources/views/rt/rumah/index.blade.php | 92 +- resources/views/user/iuran/index.blade.php | 818 +++++---- resources/views/user/iuran/upload.blade.php | 22 +- resources/views/user/kas/upload.blade.php | 198 +++ resources/views/user/layanan/status.blade.php | 646 ++----- resources/views/user/rumah.blade.php | 617 ++++--- routes/web.php | 61 +- 1045 files changed, 310546 insertions(+), 73110 deletions(-) delete mode 100644 .history/.env_20260414140457 delete mode 100644 .history/.env_20260516092137 delete mode 100644 .history/.env_20260516092138 delete mode 100644 .history/.env_20260520085420 delete mode 100644 .history/.env_20260520085427 delete mode 100644 .history/.env_20260520085434 delete mode 100644 .history/.env_20260520085648 delete mode 100644 .history/.env_20260520085725 delete mode 100644 .history/.env_20260520085919 delete mode 100644 .history/.env_20260520090106 delete mode 100644 .history/.env_20260520115238 delete mode 100644 .history/.env_20260520115247 delete mode 100644 .history/.env_20260520115411 delete mode 100644 .history/.env_20260520115419 delete mode 100644 .history/.env_20260521114440 delete mode 100644 .history/.env_20260521115228 delete mode 100644 .history/.env_20260521115334 delete mode 100644 .history/.env_20260521115335 delete mode 100644 .history/.env_20260521115338 delete mode 100644 .history/.env_20260521115339 delete mode 100644 .history/.env_20260521115342 delete mode 100644 .history/.env_20260521115345 delete mode 100644 .history/.env_20260521115424 delete mode 100644 .history/.env_20260521115432 delete mode 100644 .history/.env_20260521115440 delete mode 100644 .history/.env_20260521115442 delete mode 100644 .history/.env_20260521115446 delete mode 100644 .history/.env_20260521165900 delete mode 100644 .history/.env_20260521165902 delete mode 100644 .history/.env_20260521165904 delete mode 100644 .history/.env_20260521165916 delete mode 100644 .history/.env_20260521165925 delete mode 100644 .history/.env_20260521165951 delete mode 100644 .history/.env_20260521170051 delete mode 100644 .history/.env_20260521170054 delete mode 100644 .history/.env_20260521170058 rename .history/{.env_20260520115245 => .env_20260625025301} (91%) rename .history/{.env_20260520115241 => .env_20260625025304} (91%) rename .history/{.env_20260520115243 => .env_20260625025306} (91%) rename .history/{.env_20260520115251 => .env_20260625025308} (91%) rename .history/{.env_20260521115329 => .env_20260625025310} (92%) rename .history/{.env_20260520115422 => .env_20260625025319} (94%) create mode 100644 .history/.env_20260625025325 rename .history/{.env_20260521115117 => .env_20260625025330} (97%) rename .history/{.env_20260520115432 => .env_20260625030808} (94%) rename .history/{.env_20260521114417 => .env_20260625030809} (94%) rename .history/{.env_20260521114434 => .env_20260625115711} (91%) create mode 100644 .history/app/Http/Controllers/Admin/UserController_20260521201056.php create mode 100644 .history/app/Http/Controllers/Admin/UserController_20260521201058.php delete mode 100644 .history/app/Http/Controllers/AuthController_20260506180715.php delete mode 100644 .history/app/Http/Controllers/AuthController_20260507083718.php delete mode 100644 .history/app/Http/Controllers/AuthController_20260507083845.php delete mode 100644 .history/app/Http/Controllers/AuthController_20260507083847.php create mode 100644 .history/app/Http/Controllers/AuthController_20260524190202.php create mode 100644 .history/app/Http/Controllers/AuthController_20260524190210.php create mode 100644 .history/app/Http/Controllers/AuthController_20260524190212.php create mode 100644 .history/app/Http/Controllers/AuthController_20260524190233.php create mode 100644 .history/app/Http/Controllers/AuthController_20260524190234.php create mode 100644 .history/app/Http/Controllers/AuthController_20260524190235.php rename .history/app/Http/Controllers/{AuthController_20260507083619.php => AuthController_20260524190240.php} (100%) create mode 100644 .history/app/Http/Controllers/AuthController_20260524190256.php create mode 100644 .history/app/Http/Controllers/AuthController_20260524190306.php create mode 100644 .history/app/Http/Controllers/AuthController_20260524191313.php create mode 100644 .history/app/Http/Controllers/AuthController_20260524192503.php create mode 100644 .history/app/Http/Controllers/AuthController_20260524200654.php create mode 100644 .history/app/Http/Controllers/AuthController_20260524201955.php create mode 100644 .history/app/Http/Controllers/AuthController_20260524202342.php create mode 100644 .history/app/Http/Controllers/AuthController_20260524212628.php create mode 100644 .history/app/Http/Controllers/AuthController_20260524212631.php create mode 100644 .history/app/Http/Controllers/AuthController_20260524212644.php create mode 100644 .history/app/Http/Controllers/AuthController_20260524212651.php create mode 100644 .history/app/Http/Controllers/AuthController_20260524212653.php create mode 100644 .history/app/Http/Controllers/AuthController_20260524212713.php create mode 100644 .history/app/Http/Controllers/AuthController_20260619112926.php create mode 100644 .history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619110719.php create mode 100644 .history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619110726.php create mode 100644 .history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111038.php create mode 100644 .history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111040.php create mode 100644 .history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111537.php create mode 100644 .history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111552.php create mode 100644 .history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111555.php create mode 100644 .history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111557.php create mode 100644 .history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111559.php create mode 100644 .history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111601.php create mode 100644 .history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111602.php create mode 100644 .history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111605.php create mode 100644 .history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111613.php create mode 100644 .history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111616.php create mode 100644 .history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111619.php create mode 100644 .history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111624.php create mode 100644 .history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111626.php create mode 100644 .history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111911.php create mode 100644 .history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111913.php create mode 100644 .history/app/Http/Controllers/Bendahara/IuranController_20260619091229.php create mode 100644 .history/app/Http/Controllers/Bendahara/IuranController_20260619091233.php create mode 100644 .history/app/Http/Controllers/Bendahara/IuranController_20260619114355.php create mode 100644 .history/app/Http/Controllers/Bendahara/IuranController_20260619114400.php create mode 100644 .history/app/Http/Controllers/Bendahara/IuranController_20260620132415.php create mode 100644 .history/app/Http/Controllers/Bendahara/KasController_20260619185433.php create mode 100644 .history/app/Http/Controllers/Bendahara/KasController_20260619185447.php create mode 100644 .history/app/Http/Controllers/Bendahara/KasController_20260619191326.php create mode 100644 .history/app/Http/Controllers/Bendahara/KasController_20260619212536.php create mode 100644 .history/app/Http/Controllers/Bendahara/KasController_20260620082653.php create mode 100644 .history/app/Http/Controllers/Bendahara/RekapController_20260619095636.php create mode 100644 .history/app/Http/Controllers/Bendahara/RekapController_20260619095645.php create mode 100644 .history/app/Http/Controllers/Bendahara/RekapController_20260619101907.php create mode 100644 .history/app/Http/Controllers/Bendahara/RekapController_20260619101908.php create mode 100644 .history/app/Http/Controllers/Bendahara/RekapController_20260619101916.php create mode 100644 .history/app/Http/Controllers/Bendahara/RekapController_20260620133154.php create mode 100644 .history/app/Http/Controllers/Bendahara/RekapController_20260620134854.php delete mode 100644 .history/app/Http/Controllers/DashboardController_20260428130350.php delete mode 100644 .history/app/Http/Controllers/DashboardController_20260507082141.php delete mode 100644 .history/app/Http/Controllers/DashboardController_20260507082206.php delete mode 100644 .history/app/Http/Controllers/DashboardController_20260507082214.php delete mode 100644 .history/app/Http/Controllers/DashboardController_20260507082225.php delete mode 100644 .history/app/Http/Controllers/DashboardController_20260507082229.php delete mode 100644 .history/app/Http/Controllers/DashboardController_20260507083233.php create mode 100644 .history/app/Http/Controllers/DashboardController_20260622095816.php rename .history/app/Http/Controllers/{DashboardController_20260520084156.php => DashboardController_20260622095819.php} (100%) create mode 100644 .history/app/Http/Controllers/DashboardController_20260622095829.php create mode 100644 .history/app/Http/Controllers/DashboardController_20260622095850.php create mode 100644 .history/app/Http/Controllers/DashboardController_20260622100905.php create mode 100644 .history/app/Http/Controllers/DashboardController_20260622100935.php create mode 100644 .history/app/Http/Controllers/IuranController_20260421225646.php create mode 100644 .history/app/Http/Controllers/IuranController_20260615104208.php create mode 100644 .history/app/Http/Controllers/IuranController_20260615104211.php create mode 100644 .history/app/Http/Controllers/IuranController_20260615104218.php create mode 100644 .history/app/Http/Controllers/IuranController_20260615175424.php create mode 100644 .history/app/Http/Controllers/IuranController_20260615175433.php create mode 100644 .history/app/Http/Controllers/IuranController_20260615175446.php create mode 100644 .history/app/Http/Controllers/IuranController_20260615175452.php create mode 100644 .history/app/Http/Controllers/IuranController_20260615180801.php create mode 100644 .history/app/Http/Controllers/IuranController_20260615180806.php create mode 100644 .history/app/Http/Controllers/IuranController_20260615180826.php create mode 100644 .history/app/Http/Controllers/IuranController_20260615180830.php create mode 100644 .history/app/Http/Controllers/IuranController_20260615180832.php create mode 100644 .history/app/Http/Controllers/IuranController_20260615181323.php create mode 100644 .history/app/Http/Controllers/IuranController_20260615181330.php delete mode 100644 .history/app/Http/Controllers/LaporanController_20260504203010.php delete mode 100644 .history/app/Http/Controllers/LaporanController_20260507090744.php delete mode 100644 .history/app/Http/Controllers/LaporanController_20260507091544.php delete mode 100644 .history/app/Http/Controllers/LaporanController_20260507153841.php delete mode 100644 .history/app/Http/Controllers/LaporanController_20260507153850.php create mode 100644 .history/app/Http/Controllers/LaporanController_20260623182610.php create mode 100644 .history/app/Http/Controllers/LayananController_20260610222522.php create mode 100644 .history/app/Http/Controllers/LayananController_20260610222606.php create mode 100644 .history/app/Http/Controllers/LayananController_20260610222608.php create mode 100644 .history/app/Http/Controllers/LayananController_20260610222623.php create mode 100644 .history/app/Http/Controllers/LayananController_20260610222625.php create mode 100644 .history/app/Http/Controllers/LayananController_20260624223324.php create mode 100644 .history/app/Http/Controllers/LayananController_20260624223327.php create mode 100644 .history/app/Http/Controllers/LayananController_20260624223329.php create mode 100644 .history/app/Http/Controllers/LayananController_20260624223344.php create mode 100644 .history/app/Http/Controllers/LayananController_20260624223520.php create mode 100644 .history/app/Http/Controllers/LayananController_20260624223529.php create mode 100644 .history/app/Http/Controllers/LayananController_20260624223625.php create mode 100644 .history/app/Http/Controllers/LayananController_20260624223627.php create mode 100644 .history/app/Http/Controllers/LayananController_20260624223815.php create mode 100644 .history/app/Http/Controllers/LayananController_20260624223845.php create mode 100644 .history/app/Http/Controllers/LayananController_20260624223857.php create mode 100644 .history/app/Http/Controllers/LayananController_20260624224251.php create mode 100644 .history/app/Http/Controllers/LayananController_20260625013509.php create mode 100644 .history/app/Http/Controllers/LayananController_20260625013511.php create mode 100644 .history/app/Http/Controllers/LayananController_20260625013512.php create mode 100644 .history/app/Http/Controllers/LayananController_20260625013514.php create mode 100644 .history/app/Http/Controllers/LayananController_20260625013516.php create mode 100644 .history/app/Http/Controllers/LayananController_20260625013554.php create mode 100644 .history/app/Http/Controllers/LayananController_20260625013557.php create mode 100644 .history/app/Http/Controllers/LayananController_20260625013601.php create mode 100644 .history/app/Http/Controllers/LayananController_20260625013607.php create mode 100644 .history/app/Http/Controllers/LayananController_20260625014723.php create mode 100644 .history/app/Http/Controllers/LayananController_20260625014724.php create mode 100644 .history/app/Http/Controllers/LayananController_20260625014727.php create mode 100644 .history/app/Http/Controllers/LayananController_20260625014952.php create mode 100644 .history/app/Http/Controllers/LayananController_20260625014958.php create mode 100644 .history/app/Http/Controllers/LayananController_20260625015033.php create mode 100644 .history/app/Http/Controllers/LayananController_20260625022400.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260604090538.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260604090540.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260604090543.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260604090547.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260604090549.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260604090552.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260604090557.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260604090600.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260604090603.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260604090606.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260604090607.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260604090611.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260604090612.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260604090616.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260604090617.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260604090619.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260604090621.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260604090659.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260604090702.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260604090704.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260604090714.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260610222045.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260610222048.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260610222051.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260610222056.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260610222059.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260610222102.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260610222105.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260610222108.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260610222110.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260610222113.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260610222117.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260610222119.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260610222120.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260610222123.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260614183436.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260614183442.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260614183444.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260614183449.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260614183500.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260614183504.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260614183546.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260614183547.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260614183556.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260614183933.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260614183935.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260614183941.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260614183944.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260614184208.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260614184210.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260614184211.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260614184217.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260614184219.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260614184337.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260614184732.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260614184735.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260614184747.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260614184931.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260614185304.php create mode 100644 .history/app/Http/Controllers/PenghuniController_20260614190042.php create mode 100644 .history/app/Http/Controllers/RT/BendaharaController_20260619090446.php create mode 100644 .history/app/Http/Controllers/RT/BendaharaController_20260619090459.php create mode 100644 .history/app/Http/Controllers/RT/BendaharaController_20260619105958.php create mode 100644 .history/app/Http/Controllers/RT/BendaharaController_20260619110049.php create mode 100644 .history/app/Http/Controllers/RT/BendaharaController_20260619110051.php create mode 100644 .history/app/Http/Controllers/RT/KasController_20260619185519.php create mode 100644 .history/app/Http/Controllers/RT/KasController_20260619185522.php create mode 100644 .history/app/Http/Controllers/RT/KasController_20260619185527.php create mode 100644 .history/app/Http/Controllers/RT/KasController_20260619191405.php create mode 100644 .history/app/Http/Controllers/RT/KasRTController_20260619191404.php create mode 100644 .history/app/Http/Controllers/RT/KasRTController_20260620081459.php create mode 100644 .history/app/Http/Controllers/RT/KasRTController_20260620081519.php create mode 100644 .history/app/Http/Controllers/RT/KasRTController_20260620081649.php create mode 100644 .history/app/Http/Controllers/RT/KasRTController_20260620082003.php create mode 100644 .history/app/Http/Controllers/RT/KasRTController_20260620082010.php create mode 100644 .history/app/Http/Controllers/RT/KasRTController_20260620082012.php create mode 100644 .history/app/Http/Controllers/RT/KasRTController_20260620082018.php create mode 100644 .history/app/Http/Controllers/RT/ReviewIuranController_20260619091258.php create mode 100644 .history/app/Http/Controllers/RT/ReviewIuranController_20260619091314.php create mode 100644 .history/app/Http/Controllers/RT/ReviewIuranController_20260619115439.php create mode 100644 .history/app/Http/Controllers/RT/ReviewIuranController_20260619115450.php create mode 100644 .history/app/Http/Controllers/RT/ReviewRekapController_20260619095716.php create mode 100644 .history/app/Http/Controllers/RT/ReviewRekapController_20260619095826.php create mode 100644 .history/app/Http/Controllers/RT/ReviewRekapController_20260619095848.php create mode 100644 .history/app/Http/Controllers/RT/ReviewRekapController_20260619095852.php create mode 100644 .history/app/Http/Controllers/RT/ReviewRekapController_20260619101839.php create mode 100644 .history/app/Http/Controllers/RT/ReviewRekapController_20260619101840.php create mode 100644 .history/app/Http/Controllers/RT/ReviewRekapController_20260619101847.php create mode 100644 .history/app/Http/Controllers/RT/ReviewRekapController_20260620132653.php create mode 100644 .history/app/Http/Controllers/RT/ReviewRekapController_20260620134923.php create mode 100644 .history/app/Http/Controllers/UserController_20260505205724.php create mode 100644 .history/app/Http/Controllers/UserController_20260521214525.php create mode 100644 .history/app/Http/Controllers/UserController_20260521214527.php create mode 100644 .history/app/Http/Controllers/UserController_20260521214529.php create mode 100644 .history/app/Http/Controllers/UserIuranController_20260416200452.php create mode 100644 .history/app/Http/Controllers/UserIuranController_20260615175138.php create mode 100644 .history/app/Http/Controllers/UserIuranController_20260615175149.php create mode 100644 .history/app/Http/Controllers/UserIuranController_20260615175302.php create mode 100644 .history/app/Http/Controllers/UserIuranController_20260615175304.php create mode 100644 .history/app/Http/Controllers/UserIuranController_20260615175324.php create mode 100644 .history/app/Http/Controllers/UserIuranController_20260615175327.php create mode 100644 .history/app/Http/Controllers/UserIuranController_20260619094756.php create mode 100644 .history/app/Http/Controllers/UserIuranController_20260619094803.php create mode 100644 .history/app/Http/Controllers/UserIuranController_20260619094845.php create mode 100644 .history/app/Http/Controllers/UserIuranController_20260619094849.php create mode 100644 .history/app/Http/Controllers/UserIuranController_20260619095405.php create mode 100644 .history/app/Http/Controllers/UserIuranController_20260619095428.php create mode 100644 .history/app/Http/Controllers/UserIuranController_20260619101939.php create mode 100644 .history/app/Http/Controllers/UserIuranController_20260619101940.php create mode 100644 .history/app/Http/Controllers/UserIuranController_20260619213550.php create mode 100644 .history/app/Http/Controllers/UserIuranController_20260619213554.php create mode 100644 .history/app/Http/Controllers/UserIuranController_20260619213608.php create mode 100644 .history/app/Http/Controllers/UserIuranController_20260620090407.php create mode 100644 .history/app/Http/Controllers/UserIuranController_20260620090422.php create mode 100644 .history/app/Http/Controllers/UserIuranController_20260620090436.php create mode 100644 .history/app/Http/Controllers/UserIuranController_20260622094632.php create mode 100644 .history/app/Http/Controllers/UserKasController_20260619212656.php create mode 100644 .history/app/Http/Controllers/UserKasController_20260619212704.php create mode 100644 .history/app/Http/Middleware/CheckRole_20260619003211.php create mode 100644 .history/app/Http/Middleware/CheckRole_20260619003234.php create mode 100644 .history/app/Http/Middleware/CheckStatusAkun_20260619003128.php create mode 100644 .history/app/Http/Middleware/CheckStatusAkun_20260619003152.php create mode 100644 .history/app/Http/Middleware/CheckStatusAkun_20260619003159.php create mode 100644 .history/app/Http/Middleware/ForcePasswordChange_20260619110357.php create mode 100644 .history/app/Http/Middleware/ForcePasswordChange_20260619110404.php create mode 100644 .history/app/Mail/NotifPengaduanSelesai_20260625013755.php create mode 100644 .history/app/Mail/NotifPengaduanSelesai_20260625015248.php create mode 100644 .history/app/Mail/NotifPengaduan_20260413213025.php create mode 100644 .history/app/Mail/NotifPengaduan_20260625022333.php create mode 100644 .history/app/Mail/NotifPengaduan_20260625022335.php create mode 100644 .history/app/Mail/NotifPengaduan_20260625022337.php create mode 100644 .history/app/Mail/NotifPengaduan_20260625022338.php create mode 100644 .history/app/Mail/NotifPengaduan_20260625093324.php create mode 100644 .history/app/Models/Iuran_20260421222156.php create mode 100644 .history/app/Models/Iuran_20260618225040.php create mode 100644 .history/app/Models/Iuran_20260619102004.php create mode 100644 .history/app/Models/Iuran_20260619102005.php create mode 100644 .history/app/Models/KasBendahara_20260619101754.php create mode 100644 .history/app/Models/KasBendahara_20260619101758.php create mode 100644 .history/app/Models/KasBendahara_20260619193847.php create mode 100644 .history/app/Models/Layanan_20260410140848.php create mode 100644 .history/app/Models/Layanan_20260625013618.php create mode 100644 .history/app/Models/RekapIuran_20260619101721.php create mode 100644 .history/app/Models/RekapIuran_20260619101725.php create mode 100644 .history/app/Models/User_20260419103641.php create mode 100644 .history/app/Models/User_20260618224625.php create mode 100644 .history/app/Models/User_20260618224628.php create mode 100644 .history/app/Models/User_20260618224631.php create mode 100644 .history/app/Models/User_20260618224635.php create mode 100644 .history/app/Models/User_20260618224638.php create mode 100644 .history/app/Models/User_20260618224642.php create mode 100644 .history/app/Models/User_20260618224646.php create mode 100644 .history/app/Models/User_20260618224650.php create mode 100644 .history/app/Models/User_20260618224652.php create mode 100644 .history/app/Models/User_20260618225014.php create mode 100644 .history/app/Models/User_20260618225019.php create mode 100644 .history/app/Models/User_20260618225021.php create mode 100644 .history/app/Models/User_20260620144354.php create mode 100644 .history/app/Services/WhatsappService_20260524190026.php create mode 100644 .history/app/Services/WhatsappService_20260524190118.php create mode 100644 .history/app/Services/WhatsappService_20260524190126.php create mode 100644 .history/app/Services/WhatsappService_20260524190129.php create mode 100644 .history/app/Services/WhatsappService_20260524192851.php create mode 100644 .history/app/Services/WhatsappService_20260524192854.php create mode 100644 .history/app/Services/WhatsappService_20260524192902.php create mode 100644 .history/app/Services/WhatsappService_20260524192908.php create mode 100644 .history/app/Services/WhatsappService_20260524192910.php create mode 100644 .history/app/Services/WhatsappService_20260524192920.php create mode 100644 .history/app/Services/WhatsappService_20260524193040.php create mode 100644 .history/app/Services/WhatsappService_20260524195438.php create mode 100644 .history/app/Services/WhatsappService_20260524211140.php create mode 100644 .history/bootstrap/app_20260331095420.php create mode 100644 .history/bootstrap/app_20260619003314.php create mode 100644 .history/bootstrap/app_20260619110428.php create mode 100644 .history/config/services_20240312205242.php create mode 100644 .history/config/services_20260524193111.php create mode 100644 .history/config/services_20260524193115.php create mode 100644 .history/config/services_20260524194140.php create mode 100644 .history/config/services_20260524194142.php create mode 100644 .history/config/services_20260524194146.php create mode 100644 .history/config/services_20260524212555.php create mode 100644 .history/config/services_20260524212557.php create mode 100644 .history/database/migrations/2026_04_01_084939_add_photo_to_users_table_20260401155008.php create mode 100644 .history/database/migrations/2026_04_01_084939_add_photo_to_users_table_20260524185303.php create mode 100644 .history/database/migrations/2026_06_18_215158_alter_users_add_bendahara_fields_20260618215157.php create mode 100644 .history/database/migrations/2026_06_18_215158_alter_users_add_bendahara_fields_20260618215235.php create mode 100644 .history/database/migrations/2026_06_18_215158_alter_users_add_bendahara_fields_20260618221428.php create mode 100644 .history/database/migrations/2026_06_18_215158_alter_users_add_bendahara_fields_20260618221432.php create mode 100644 .history/database/migrations/2026_06_18_215158_alter_users_add_bendahara_fields_20260618221434.php create mode 100644 .history/database/migrations/2026_06_18_222120_add_bendahara_columns_to_users_table_20260618222119.php create mode 100644 .history/database/migrations/2026_06_18_222120_add_bendahara_columns_to_users_table_20260618222148.php create mode 100644 .history/database/migrations/2026_06_18_222120_add_bendahara_columns_to_users_table_20260618222527.php create mode 100644 .history/database/migrations/2026_06_18_223156_add_bendahara_columns_to_iuran_table_20260618223155.php create mode 100644 .history/database/migrations/2026_06_18_223156_add_bendahara_columns_to_iuran_table_20260618223253.php create mode 100644 .history/database/migrations/2026_06_18_224252_create_rekap_iuran_table_20260618224251.php create mode 100644 .history/database/migrations/2026_06_18_224252_create_rekap_iuran_table_20260618224306.php create mode 100644 .history/database/migrations/2026_06_18_224445_create_kas_bendahara_table_20260618224444.php create mode 100644 .history/database/migrations/2026_06_18_224445_create_kas_bendahara_table_20260618224454.php create mode 100644 .history/database/migrations/2026_06_19_104835_add_wajib_ganti_password_to_users_table_20260619104834.php create mode 100644 .history/database/migrations/2026_06_19_104835_add_wajib_ganti_password_to_users_table_20260619104847.php create mode 100644 .history/database/migrations/2026_06_19_193624_add_tagihan_columns_to_kas_bendahara_table_20260619193623.php create mode 100644 .history/database/migrations/2026_06_19_193624_add_tagihan_columns_to_kas_bendahara_table_20260619193636.php rename .history/resources/views/admin/{dashboard.blade_20260510224500.php => dashboard.blade_20260622103728.php} (68%) rename .history/resources/views/admin/{dashboard.blade_20260521104935.php => dashboard.blade_20260622103740.php} (100%) rename .history/resources/views/admin/{dashboard.blade_20260506104729.php => dashboard.blade_20260622103810.php} (66%) rename .history/resources/views/admin/{dashboard.blade_20260506213729.php => dashboard.blade_20260622103822.php} (69%) rename .history/resources/views/admin/{dashboard.blade_20260510224523.php => dashboard.blade_20260622103832.php} (69%) delete mode 100644 .history/resources/views/admin/iuran/create.blade_20260508232532.php delete mode 100644 .history/resources/views/admin/iuran/create.blade_20260508232551.php rename .history/resources/views/admin/iuran/{create.blade_20260506101108.php => create.blade_20260615184627.php} (99%) delete mode 100644 .history/resources/views/admin/iuran/index.blade_20260506111125.php delete mode 100644 .history/resources/views/admin/iuran/index.blade_20260510234127.php rename .history/resources/views/admin/iuran/{index.blade_20260506215822.php => index.blade_20260615104315.php} (97%) rename .history/resources/views/admin/iuran/{index.blade_20260510225050.php => index.blade_20260615104328.php} (95%) rename .history/resources/views/admin/iuran/{index.blade_20260510234147.php => index.blade_20260615104705.php} (95%) create mode 100644 .history/resources/views/admin/iuran/index.blade_20260615104707.php create mode 100644 .history/resources/views/admin/iuran/index.blade_20260615175750.php rename .history/resources/views/admin/iuran/{index.blade_20260510225037.php => index.blade_20260615175753.php} (95%) create mode 100644 .history/resources/views/admin/iuran/index.blade_20260615175809.php create mode 100644 .history/resources/views/admin/iuran/index.blade_20260615190548.php create mode 100644 .history/resources/views/admin/iuran/index.blade_20260615190552.php create mode 100644 .history/resources/views/admin/iuran/index.blade_20260615190652.php create mode 100644 .history/resources/views/admin/iuran/index.blade_20260615190701.php create mode 100644 .history/resources/views/admin/iuran/index.blade_20260615190928.php create mode 100644 .history/resources/views/admin/iuran/index.blade_20260615190931.php delete mode 100644 .history/resources/views/admin/laporan/cetak.blade_20260506100551.php delete mode 100644 .history/resources/views/admin/laporan/cetak.blade_20260507080224.php delete mode 100644 .history/resources/views/admin/laporan/cetak.blade_20260507080226.php create mode 100644 .history/resources/views/admin/laporan/cetak.blade_20260623183140.php delete mode 100644 .history/resources/views/admin/laporan/index.blade_20260506105854.php delete mode 100644 .history/resources/views/admin/laporan/index.blade_20260506213904.php delete mode 100644 .history/resources/views/admin/laporan/index.blade_20260507090947.php delete mode 100644 .history/resources/views/admin/laporan/index.blade_20260507091231.php delete mode 100644 .history/resources/views/admin/laporan/index.blade_20260507091242.php delete mode 100644 .history/resources/views/admin/laporan/index.blade_20260510230302.php delete mode 100644 .history/resources/views/admin/laporan/index.blade_20260510230315.php delete mode 100644 .history/resources/views/admin/laporan/index.blade_20260510235120.php delete mode 100644 .history/resources/views/admin/laporan/index.blade_20260510235122.php delete mode 100644 .history/resources/views/admin/laporan/index.blade_20260510235129.php delete mode 100644 .history/resources/views/admin/laporan/index.blade_20260510235145.php delete mode 100644 .history/resources/views/admin/laporan/index.blade_20260519181246.php create mode 100644 .history/resources/views/admin/laporan/index.blade_20260623182956.php create mode 100644 .history/resources/views/admin/laporan/index.blade_20260625084758.php delete mode 100644 .history/resources/views/admin/layanan/index.blade_20260506111303.php delete mode 100644 .history/resources/views/admin/layanan/index.blade_20260510225331.php delete mode 100644 .history/resources/views/admin/layanan/index.blade_20260510225333.php delete mode 100644 .history/resources/views/admin/layanan/index.blade_20260510225336.php delete mode 100644 .history/resources/views/admin/layanan/index.blade_20260510225343.php delete mode 100644 .history/resources/views/admin/layanan/index.blade_20260510225403.php delete mode 100644 .history/resources/views/admin/layanan/index.blade_20260510234428.php delete mode 100644 .history/resources/views/admin/layanan/index.blade_20260510234449.php delete mode 100644 .history/resources/views/admin/layanan/index.blade_20260520234535.php delete mode 100644 .history/resources/views/admin/layanan/index.blade_20260520234540.php delete mode 100644 .history/resources/views/admin/layanan/index.blade_20260521003519.php delete mode 100644 .history/resources/views/admin/layanan/index.blade_20260521172813.php delete mode 100644 .history/resources/views/admin/layanan/index.blade_20260521172856.php delete mode 100644 .history/resources/views/admin/layanan/index.blade_20260521172858.php delete mode 100644 .history/resources/views/admin/layanan/index.blade_20260521172917.php delete mode 100644 .history/resources/views/admin/layanan/index.blade_20260521172919.php delete mode 100644 .history/resources/views/admin/layanan/index.blade_20260521172921.php create mode 100644 .history/resources/views/admin/layanan/index.blade_20260625013700.php create mode 100644 .history/resources/views/admin/layanan/index.blade_20260627161355.php delete mode 100644 .history/resources/views/admin/penghuni/index.blade_20260506110729.php rename .history/resources/views/admin/penghuni/{index.blade_20260510224657.php => index.blade_20260610223246.php} (99%) rename .history/resources/views/admin/penghuni/{index.blade_20260506215210.php => index.blade_20260610223247.php} (99%) create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260611091508.php rename .history/resources/views/admin/penghuni/{index.blade_20260510224752.php => index.blade_20260611091510.php} (99%) create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260611091511.php rename .history/resources/views/admin/penghuni/{index.blade_20260510224639.php => index.blade_20260611091549.php} (99%) create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260611092101.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614183657.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614183701.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614184456.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614184525.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614190013.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614190018.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614191551.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614191620.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614191625.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614191641.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614191646.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614191648.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614191916.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614191919.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614191920.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614191926.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614191927.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614192034.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614192106.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614192108.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614192114.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614192125.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614192128.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614192130.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614192133.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614192137.php rename .history/resources/views/admin/penghuni/{index.blade_20260510224722.php => index.blade_20260614192155.php} (76%) create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614192158.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614192200.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614192210.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614192314.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614192318.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614192321.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614192322.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614192335.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614192340.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614193806.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614193929.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614193941.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614194150.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614194233.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614194701.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614194702.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614194744.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614194748.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614194829.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614194835.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614194837.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614194909.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614194914.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614194918.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614194922.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614194938.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614194943.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614195056.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614195100.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614195112.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614195114.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614195121.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614195124.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614195135.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614195139.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614195140.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614195144.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614195155.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614195159.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614195203.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614195252.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614195420.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614195555.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614195609.php create mode 100644 .history/resources/views/admin/penghuni/index.blade_20260614203424.php create mode 100644 .history/resources/views/auth/forgot.blade_20260524190438.php create mode 100644 .history/resources/views/auth/forgot.blade_20260524190440.php create mode 100644 .history/resources/views/auth/forgot.blade_20260524190442.php create mode 100644 .history/resources/views/auth/forgot.blade_20260524190443.php create mode 100644 .history/resources/views/auth/forgot.blade_20260524191350.php create mode 100644 .history/resources/views/auth/forgot.blade_20260524191401.php create mode 100644 .history/resources/views/auth/forgot.blade_20260524191407.php create mode 100644 .history/resources/views/auth/forgot.blade_20260524191410.php create mode 100644 .history/resources/views/auth/forgot.blade_20260524194211.php create mode 100644 .history/resources/views/auth/forgot.blade_20260524194219.php create mode 100644 .history/resources/views/auth/forgot.blade_20260524194221.php create mode 100644 .history/resources/views/auth/forgot.blade_20260524202012.php create mode 100644 .history/resources/views/auth/forgot.blade_20260524212609.php create mode 100644 .history/resources/views/bendahara/ganti-password/form.blade_20260619111322.php create mode 100644 .history/resources/views/bendahara/ganti-password/form.blade_20260619111440.php create mode 100644 .history/resources/views/bendahara/ganti-password/form.blade_20260627101006.php create mode 100644 .history/resources/views/bendahara/iuran/create.blade_20260619093318.php create mode 100644 .history/resources/views/bendahara/iuran/create.blade_20260619113234.php create mode 100644 .history/resources/views/bendahara/iuran/create.blade_20260622094230.php create mode 100644 .history/resources/views/bendahara/iuran/create.blade_20260627101335.php create mode 100644 .history/resources/views/bendahara/iuran/edit.blade_20260619093340.php create mode 100644 .history/resources/views/bendahara/iuran/edit.blade_20260619113228.php create mode 100644 .history/resources/views/bendahara/iuran/edit.blade_20260622094249.php create mode 100644 .history/resources/views/bendahara/iuran/edit.blade_20260627101457.php create mode 100644 .history/resources/views/bendahara/iuran/index.blade_20260619093140.php create mode 100644 .history/resources/views/bendahara/iuran/index.blade_20260619113221.php create mode 100644 .history/resources/views/bendahara/iuran/index.blade_20260620092157.php create mode 100644 .history/resources/views/bendahara/iuran/index.blade_20260620092210.php create mode 100644 .history/resources/views/bendahara/iuran/index.blade_20260620092541.php create mode 100644 .history/resources/views/bendahara/iuran/index.blade_20260620092543.php create mode 100644 .history/resources/views/bendahara/iuran/index.blade_20260620092553.php create mode 100644 .history/resources/views/bendahara/iuran/index.blade_20260620132629.php create mode 100644 .history/resources/views/bendahara/iuran/index.blade_20260627101630.php create mode 100644 .history/resources/views/bendahara/kas/create-tagihan.blade_20260619213138.php create mode 100644 .history/resources/views/bendahara/kas/create-tagihan.blade_20260619213158.php create mode 100644 .history/resources/views/bendahara/kas/create-tagihan.blade_20260627101841.php create mode 100644 .history/resources/views/bendahara/kas/index.blade_20260619190357.php create mode 100644 .history/resources/views/bendahara/kas/index.blade_20260619190413.php create mode 100644 .history/resources/views/bendahara/kas/index.blade_20260619213355.php create mode 100644 .history/resources/views/bendahara/kas/index.blade_20260620081741.php create mode 100644 .history/resources/views/bendahara/kas/index.blade_20260620081754.php create mode 100644 .history/resources/views/bendahara/kas/index.blade_20260627102131.php create mode 100644 .history/resources/views/bendahara/rekap/index.blade_20260619100932.php create mode 100644 .history/resources/views/bendahara/rekap/index.blade_20260619100938.php create mode 100644 .history/resources/views/bendahara/rekap/index.blade_20260620091153.php create mode 100644 .history/resources/views/bendahara/rekap/index.blade_20260620091214.php create mode 100644 .history/resources/views/bendahara/rekap/index.blade_20260620091234.php create mode 100644 .history/resources/views/bendahara/rekap/index.blade_20260620091335.php create mode 100644 .history/resources/views/bendahara/rekap/index.blade_20260620091337.php create mode 100644 .history/resources/views/bendahara/rekap/index.blade_20260620091448.php create mode 100644 .history/resources/views/bendahara/rekap/index.blade_20260620091452.php create mode 100644 .history/resources/views/bendahara/rekap/index.blade_20260620091517.php create mode 100644 .history/resources/views/bendahara/rekap/index.blade_20260620091519.php create mode 100644 .history/resources/views/bendahara/rekap/index.blade_20260627102508.php create mode 100644 .history/resources/views/bendahara/rekap/show.blade_20260619101010.php create mode 100644 .history/resources/views/bendahara/rekap/show.blade_20260619101020.php create mode 100644 .history/resources/views/bendahara/rekap/show.blade_20260627102818.php create mode 100644 .history/resources/views/bendahara/rekap/show.blade_20260627103021.php create mode 100644 .history/resources/views/bendahara/rekap/show.blade_20260627103043.php create mode 100644 .history/resources/views/bendahara/rekap/show.blade_20260627103219.php create mode 100644 .history/resources/views/bendahara/rekap/show.blade_20260627103231.php create mode 100644 .history/resources/views/bendahara/rekap/show.blade_20260627103235.php create mode 100644 .history/resources/views/bendahara/rekap/show.blade_20260627103237.php create mode 100644 .history/resources/views/bendahara/rekap/show.blade_20260627103307.php create mode 100644 .history/resources/views/bendahara/rekap/show.blade_20260627103342.php create mode 100644 .history/resources/views/bendahara/rekap/show.blade_20260627103344.php create mode 100644 .history/resources/views/bendahara/rekap/show.blade_20260627103345.php create mode 100644 .history/resources/views/bendahara/rekap/show.blade_20260627103347.php delete mode 100644 .history/resources/views/components/sidebar.blade_20260506102833.php delete mode 100644 .history/resources/views/components/sidebar.blade_20260506212056.php delete mode 100644 .history/resources/views/components/sidebar.blade_20260507154036.php delete mode 100644 .history/resources/views/components/sidebar.blade_20260507154043.php delete mode 100644 .history/resources/views/components/sidebar.blade_20260507154047.php delete mode 100644 .history/resources/views/components/sidebar.blade_20260516015132.php delete mode 100644 .history/resources/views/components/sidebar.blade_20260516015145.php delete mode 100644 .history/resources/views/components/sidebar.blade_20260516015155.php delete mode 100644 .history/resources/views/components/sidebar.blade_20260516015204.php rename .history/resources/views/components/{sidebar.blade_20260516092325.php => sidebar.blade_20260622095045.php} (99%) rename .history/resources/views/components/{sidebar.blade_20260516015211.php => sidebar.blade_20260627161521.php} (97%) rename .history/resources/views/components/{sidebar.blade_20260516015208.php => sidebar.blade_20260627161523.php} (97%) create mode 100644 .history/resources/views/components/sidebar.blade_20260627161729.php create mode 100644 .history/resources/views/components/sidebar.blade_20260627161731.php create mode 100644 .history/resources/views/components/sidebar_bendahara.blade_20260619094101.php create mode 100644 .history/resources/views/components/sidebar_bendahara.blade_20260619094109.php rename .history/resources/views/components/{sidebar_rt.blade_20260520233209.php => sidebar_bendahara.blade_20260619113715.php} (81%) create mode 100644 .history/resources/views/components/sidebar_bendahara.blade_20260619113717.php create mode 100644 .history/resources/views/components/sidebar_bendahara.blade_20260619113719.php create mode 100644 .history/resources/views/components/sidebar_bendahara.blade_20260619190807.php rename .history/resources/views/components/{sidebar_rt.blade_20260520233503.php => sidebar_bendahara.blade_20260619190808.php} (81%) create mode 100644 .history/resources/views/components/sidebar_bendahara.blade_20260619190811.php rename .history/resources/views/components/{sidebar_rt.blade_20260520233221.php => sidebar_bendahara.blade_20260619190814.php} (81%) rename .history/resources/views/components/{sidebar_rt.blade_20260520233100.php => sidebar_bendahara.blade_20260619190815.php} (81%) create mode 100644 .history/resources/views/components/sidebar_bendahara.blade_20260619213311.php create mode 100644 .history/resources/views/components/sidebar_bendahara.blade_20260627141538.php create mode 100644 .history/resources/views/components/sidebar_bendahara.blade_20260627141631.php create mode 100644 .history/resources/views/components/sidebar_bendahara.blade_20260627141641.php create mode 100644 .history/resources/views/components/sidebar_bendahara.blade_20260627141644.php create mode 100644 .history/resources/views/components/sidebar_bendahara.blade_20260627141646.php create mode 100644 .history/resources/views/components/sidebar_bendahara.blade_20260627141815.php create mode 100644 .history/resources/views/components/sidebar_bendahara.blade_20260627141817.php create mode 100644 .history/resources/views/components/sidebar_bendahara.blade_20260627141849.php create mode 100644 .history/resources/views/components/sidebar_bendahara.blade_20260627141900.php create mode 100644 .history/resources/views/components/sidebar_bendahara.blade_20260627141908.php create mode 100644 .history/resources/views/components/sidebar_bendahara.blade_20260627141909.php create mode 100644 .history/resources/views/components/sidebar_bendahara.blade_20260627141917.php create mode 100644 .history/resources/views/components/sidebar_bendahara.blade_20260627141937.php create mode 100644 .history/resources/views/components/sidebar_bendahara.blade_20260627141958.php create mode 100644 .history/resources/views/components/sidebar_bendahara.blade_20260627142004.php create mode 100644 .history/resources/views/components/sidebar_bendahara.blade_20260627142018.php create mode 100644 .history/resources/views/components/sidebar_bendahara.blade_20260627142034.php create mode 100644 .history/resources/views/components/sidebar_bendahara.blade_20260627142051.php create mode 100644 .history/resources/views/components/sidebar_bendahara.blade_20260627142053.php create mode 100644 .history/resources/views/components/sidebar_bendahara.blade_20260627142057.php create mode 100644 .history/resources/views/components/sidebar_bendahara.blade_20260627142100.php create mode 100644 .history/resources/views/components/sidebar_bendahara.blade_20260627142113.php create mode 100644 .history/resources/views/components/sidebar_bendahara.blade_20260627142114.php create mode 100644 .history/resources/views/components/sidebar_bendahara.blade_20260627142118.php create mode 100644 .history/resources/views/components/sidebar_bendahara.blade_20260627142121.php create mode 100644 .history/resources/views/components/sidebar_bendahara.blade_20260627142124.php create mode 100644 .history/resources/views/components/sidebar_bendahara.blade_20260627142127.php create mode 100644 .history/resources/views/components/sidebar_bendahara.blade_20260627142132.php delete mode 100644 .history/resources/views/components/sidebar_rt.blade_20260506103149.php delete mode 100644 .history/resources/views/components/sidebar_rt.blade_20260506220429.php delete mode 100644 .history/resources/views/components/sidebar_rt.blade_20260507165948.php delete mode 100644 .history/resources/views/components/sidebar_rt.blade_20260507170159.php delete mode 100644 .history/resources/views/components/sidebar_rt.blade_20260507170317.php delete mode 100644 .history/resources/views/components/sidebar_rt.blade_20260507170336.php delete mode 100644 .history/resources/views/components/sidebar_rt.blade_20260507170348.php delete mode 100644 .history/resources/views/components/sidebar_rt.blade_20260507170357.php delete mode 100644 .history/resources/views/components/sidebar_rt.blade_20260507170407.php delete mode 100644 .history/resources/views/components/sidebar_rt.blade_20260507170419.php delete mode 100644 .history/resources/views/components/sidebar_rt.blade_20260507170426.php delete mode 100644 .history/resources/views/components/sidebar_rt.blade_20260520233032.php delete mode 100644 .history/resources/views/components/sidebar_rt.blade_20260520233103.php delete mode 100644 .history/resources/views/components/sidebar_rt.blade_20260520233212.php delete mode 100644 .history/resources/views/components/sidebar_rt.blade_20260520233217.php delete mode 100644 .history/resources/views/components/sidebar_rt.blade_20260520233236.php delete mode 100644 .history/resources/views/components/sidebar_rt.blade_20260520233429.php delete mode 100644 .history/resources/views/components/sidebar_rt.blade_20260520233432.php delete mode 100644 .history/resources/views/components/sidebar_rt.blade_20260520233434.php delete mode 100644 .history/resources/views/components/sidebar_rt.blade_20260520233440.php delete mode 100644 .history/resources/views/components/sidebar_rt.blade_20260520233443.php rename .history/resources/views/components/{sidebar_rt.blade_20260521003331.php => sidebar_rt.blade_20260619103922.php} (98%) rename .history/resources/views/components/{sidebar_rt.blade_20260520233034.php => sidebar_rt.blade_20260619114913.php} (98%) rename .history/resources/views/components/{sidebar_rt.blade_20260520233038.php => sidebar_rt.blade_20260619114915.php} (94%) rename .history/resources/views/components/{sidebar_rt.blade_20260507170712.php => sidebar_rt.blade_20260619183033.php} (98%) create mode 100644 .history/resources/views/components/sidebar_rt.blade_20260619183041.php create mode 100644 .history/resources/views/components/sidebar_rt.blade_20260619183047.php create mode 100644 .history/resources/views/components/sidebar_rt.blade_20260619190553.php create mode 100644 .history/resources/views/components/sidebar_rt.blade_20260627142705.php create mode 100644 .history/resources/views/emails/pengaduan_selesai.blade_20260625013913.php create mode 100644 .history/resources/views/emails/pengaduan_selesai.blade_20260625013920.php delete mode 100644 .history/resources/views/layouts/app.blade_20260506014525.php delete mode 100644 .history/resources/views/layouts/app.blade_20260507171636.php rename .history/resources/views/layouts/{app.blade_20260519175911.php => app.blade_20260619094017.php} (99%) create mode 100644 .history/resources/views/rt/bendahara/index.blade_20260619090821.php create mode 100644 .history/resources/views/rt/bendahara/index.blade_20260619090951.php create mode 100644 .history/resources/views/rt/bendahara/index.blade_20260619104014.php create mode 100644 .history/resources/views/rt/bendahara/index.blade_20260619110237.php create mode 100644 .history/resources/views/rt/bendahara/index.blade_20260627140505.php create mode 100644 .history/resources/views/rt/bendahara/index.blade_20260627163811.php create mode 100644 .history/resources/views/rt/bendahara/iuran/create.blade_20260619093205.php create mode 100644 .history/resources/views/rt/bendahara/iuran/create.blade_20260619093319.php create mode 100644 .history/resources/views/rt/bendahara/iuran/edit.blade_20260619093333.php create mode 100644 .history/resources/views/rt/bendahara/iuran/edit.blade_20260619093341.php create mode 100644 .history/resources/views/rt/bendahara/iuran/index.blade_20260619093119.php create mode 100644 .history/resources/views/rt/bendahara/iuran/index.blade_20260619093122.php create mode 100644 .history/resources/views/rt/bendahara/iuran/index.blade_20260619093125.php create mode 100644 .history/resources/views/rt/bendahara/iuran/index.blade_20260619093127.php create mode 100644 .history/resources/views/rt/bendahara/iuran/index.blade_20260619093141.php delete mode 100644 .history/resources/views/rt/dashboard.blade_20260506090847.php delete mode 100644 .history/resources/views/rt/dashboard.blade_20260507082949.php delete mode 100644 .history/resources/views/rt/dashboard.blade_20260507083054.php delete mode 100644 .history/resources/views/rt/dashboard.blade_20260507083056.php delete mode 100644 .history/resources/views/rt/dashboard.blade_20260507083323.php delete mode 100644 .history/resources/views/rt/dashboard.blade_20260507083342.php rename .history/resources/views/rt/{dashboard.blade_20260507083346.php => dashboard.blade_20260615104851.php} (72%) rename .history/resources/views/rt/{dashboard.blade_20260521104447.php => dashboard.blade_20260615105018.php} (100%) rename .history/resources/views/rt/{dashboard.blade_20260507083344.php => dashboard.blade_20260622100005.php} (60%) create mode 100644 .history/resources/views/rt/dashboard.blade_20260622100338.php create mode 100644 .history/resources/views/rt/dashboard.blade_20260622100411.php rename .history/resources/views/rt/{dashboard.blade_20260507083326.php => dashboard.blade_20260622100426.php} (60%) create mode 100644 .history/resources/views/rt/dashboard.blade_20260622100428.php create mode 100644 .history/resources/views/rt/dashboard.blade_20260622100455.php create mode 100644 .history/resources/views/rt/dashboard.blade_20260622100456.php rename .history/resources/views/rt/{dashboard.blade_20260507083341.php => dashboard.blade_20260622100458.php} (60%) create mode 100644 .history/resources/views/rt/dashboard.blade_20260622100504.php create mode 100644 .history/resources/views/rt/dashboard.blade_20260622100506.php create mode 100644 .history/resources/views/rt/dashboard.blade_20260622100511.php create mode 100644 .history/resources/views/rt/dashboard.blade_20260622100528.php create mode 100644 .history/resources/views/rt/dashboard.blade_20260622100534.php create mode 100644 .history/resources/views/rt/dashboard.blade_20260622100544.php create mode 100644 .history/resources/views/rt/dashboard.blade_20260622101022.php create mode 100644 .history/resources/views/rt/dashboard.blade_20260622101030.php rename .history/resources/views/rt/{dashboard.blade_20260507082956.php => dashboard.blade_20260622101118.php} (52%) rename .history/resources/views/rt/{dashboard.blade_20260507083011.php => dashboard.blade_20260622101125.php} (52%) create mode 100644 .history/resources/views/rt/dashboard.blade_20260622101130.php create mode 100644 .history/resources/views/rt/dashboard.blade_20260622101239.php create mode 100644 .history/resources/views/rt/dashboard.blade_20260622101448.php create mode 100644 .history/resources/views/rt/dashboard.blade_20260627162322.php create mode 100644 .history/resources/views/rt/kas/index.blade_20260619190446.php create mode 100644 .history/resources/views/rt/kas/index.blade_20260619190452.php create mode 100644 .history/resources/views/rt/kas/index.blade_20260627140230.php create mode 100644 .history/resources/views/rt/laporan/cetak.blade_20260625083149.php create mode 100644 .history/resources/views/rt/laporan/cetak.blade_20260625083156.php create mode 100644 .history/resources/views/rt/laporan/index.blade_20260623182820.php create mode 100644 .history/resources/views/rt/laporan/index.blade_20260623182826.php create mode 100644 .history/resources/views/rt/laporan/index.blade_20260625084727.php create mode 100644 .history/resources/views/rt/laporan/index.blade_20260625084737.php create mode 100644 .history/resources/views/rt/laporan/index.blade_20260627163336.php create mode 100644 .history/resources/views/rt/laporan/index.blade_20260627163339.php create mode 100644 .history/resources/views/rt/laporan/index.blade_20260627163343.php delete mode 100644 .history/resources/views/rt/penghuni/index.blade_20260506174552.php delete mode 100644 .history/resources/views/rt/penghuni/index.blade_20260510233610.php rename .history/resources/views/rt/penghuni/{index.blade_20260508231950.php => index.blade_20260615171252.php} (78%) rename .history/resources/views/rt/penghuni/{index.blade_20260510232607.php => index.blade_20260615171422.php} (58%) rename .history/resources/views/rt/penghuni/{index.blade_20260507165338.php => index.blade_20260615171426.php} (56%) rename .history/resources/views/rt/penghuni/{index.blade_20260508231940.php => index.blade_20260615171429.php} (56%) create mode 100644 .history/resources/views/rt/review-iuran/index.blade_20260619093431.php create mode 100644 .history/resources/views/rt/review-iuran/index.blade_20260619093445.php create mode 100644 .history/resources/views/rt/review-iuran/index.blade_20260619114950.php create mode 100644 .history/resources/views/rt/review-iuran/index.blade_20260627133706.php create mode 100644 .history/resources/views/rt/review-iuran/index.blade_20260627133733.php create mode 100644 .history/resources/views/rt/review-iuran/index.blade_20260627133740.php create mode 100644 .history/resources/views/rt/review-rekap/index.blade_20260619101253.php create mode 100644 .history/resources/views/rt/review-rekap/index.blade_20260619101300.php create mode 100644 .history/resources/views/rt/review-rekap/index.blade_20260620133220.php create mode 100644 .history/resources/views/rt/review-rekap/index.blade_20260620135156.php create mode 100644 .history/resources/views/rt/review-rekap/index.blade_20260620135203.php create mode 100644 .history/resources/views/rt/review-rekap/index.blade_20260627134958.php create mode 100644 .history/resources/views/rt/review-rekap/show.blade_20260619101312.php create mode 100644 .history/resources/views/rt/review-rekap/show.blade_20260619101319.php create mode 100644 .history/resources/views/rt/review-rekap/show.blade_20260620133229.php create mode 100644 .history/resources/views/rt/review-rekap/show.blade_20260620135212.php create mode 100644 .history/resources/views/rt/review-rekap/show.blade_20260627135513.php rename .history/resources/views/rt/rumah/{index.blade_20260510233743.php => index.blade_20260615171039.php} (76%) rename .history/resources/views/rt/rumah/{index.blade_20260506174842.php => index.blade_20260615171041.php} (100%) rename .history/resources/views/rt/rumah/{index.blade_20260510233723.php => index.blade_20260615171058.php} (72%) create mode 100644 .history/resources/views/rt/rumah/index.blade_20260615171119.php delete mode 100644 .history/resources/views/user/iuran/index.blade_20260505200948.php delete mode 100644 .history/resources/views/user/iuran/index.blade_20260507172115.php delete mode 100644 .history/resources/views/user/iuran/index.blade_20260507172523.php delete mode 100644 .history/resources/views/user/iuran/index.blade_20260511031518.php delete mode 100644 .history/resources/views/user/iuran/index.blade_20260511031534.php delete mode 100644 .history/resources/views/user/iuran/index.blade_20260511031548.php delete mode 100644 .history/resources/views/user/iuran/index.blade_20260511031605.php delete mode 100644 .history/resources/views/user/iuran/index.blade_20260521101154.php delete mode 100644 .history/resources/views/user/iuran/index.blade_20260521101158.php delete mode 100644 .history/resources/views/user/iuran/index.blade_20260521101228.php delete mode 100644 .history/resources/views/user/iuran/index.blade_20260521101326.php delete mode 100644 .history/resources/views/user/iuran/index.blade_20260521101331.php delete mode 100644 .history/resources/views/user/iuran/index.blade_20260521101335.php delete mode 100644 .history/resources/views/user/iuran/index.blade_20260521101337.php delete mode 100644 .history/resources/views/user/iuran/index.blade_20260521101339.php rename .history/resources/views/user/iuran/{index.blade_20260521101505.php => index.blade_20260529171547.php} (99%) rename .history/resources/views/user/iuran/{index.blade_20260521101503.php => index.blade_20260529171548.php} (99%) rename .history/resources/views/user/iuran/{index.blade_20260521101451.php => index.blade_20260529171554.php} (99%) rename .history/resources/views/user/iuran/{index.blade_20260521101447.php => index.blade_20260529171645.php} (95%) create mode 100644 .history/resources/views/user/iuran/index.blade_20260615180336.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260615180340.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260615180342.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260615180346.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260615180349.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260615180351.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260615180548.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260615180556.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260615180557.php rename .history/resources/views/user/iuran/{index.blade_20260521101329.php => index.blade_20260619213834.php} (87%) create mode 100644 .history/resources/views/user/iuran/index.blade_20260619213843.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260619214028.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260619214117.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260619214118.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260619214129.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260619214137.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260619214155.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260619214210.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260619214211.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260619214753.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260619214757.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260619214800.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260620083132.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260620083206.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260620083211.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260620083327.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260620083329.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260620083331.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260620083333.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260620083346.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260620083351.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260620083357.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260620083405.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260620083503.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260620083623.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260620083700.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260620083703.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260620084052.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260620084332.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260620084404.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260620084410.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260620084639.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260620084644.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260620084645.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260620084653.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260620084714.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260620084830.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260620084913.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260620141427.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260620141431.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260620141437.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260620141438.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260620141440.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260620141441.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260622094706.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260627170632.php create mode 100644 .history/resources/views/user/iuran/index.blade_20260627170650.php create mode 100644 .history/resources/views/user/iuran/upload.blade_20260505210628.php create mode 100644 .history/resources/views/user/iuran/upload.blade_20260615180656.php create mode 100644 .history/resources/views/user/iuran/upload.blade_20260615180708.php create mode 100644 .history/resources/views/user/kas/upload.blade_20260619213231.php create mode 100644 .history/resources/views/user/kas/upload.blade_20260619213238.php create mode 100644 .history/resources/views/user/kas/upload.blade_20260620085228.php create mode 100644 .history/resources/views/user/layanan/status.blade_20260505213925.php create mode 100644 .history/resources/views/user/layanan/status.blade_20260625013734.php delete mode 100644 .history/resources/views/user/rumah.blade_20260511001052.php delete mode 100644 .history/resources/views/user/rumah.blade_20260511001108.php delete mode 100644 .history/resources/views/user/rumah.blade_20260511001118.php delete mode 100644 .history/resources/views/user/rumah.blade_20260511001137.php delete mode 100644 .history/resources/views/user/rumah.blade_20260511001201.php delete mode 100644 .history/resources/views/user/rumah.blade_20260511001216.php rename .history/resources/views/user/{rumah.blade_20260506115605.php => rumah.blade_20260521212139.php} (98%) rename .history/resources/views/user/{rumah.blade_20260511001231.php => rumah.blade_20260521212151.php} (98%) rename .history/resources/views/user/{rumah.blade_20260511001037.php => rumah.blade_20260521212225.php} (97%) rename .history/resources/views/user/{rumah.blade_20260511001102.php => rumah.blade_20260521212229.php} (84%) create mode 100644 .history/resources/views/user/rumah.blade_20260521213605.php create mode 100644 .history/resources/views/user/rumah.blade_20260521213610.php create mode 100644 .history/resources/views/user/rumah.blade_20260530182842.php create mode 100644 .history/resources/views/user/rumah.blade_20260530182917.php create mode 100644 .history/resources/views/user/rumah.blade_20260530182925.php create mode 100644 .history/resources/views/user/rumah.blade_20260530182932.php create mode 100644 .history/resources/views/user/rumah.blade_20260530182937.php create mode 100644 .history/resources/views/user/rumah.blade_20260530184903.php create mode 100644 .history/resources/views/user/rumah.blade_20260530184906.php create mode 100644 .history/resources/views/user/rumah.blade_20260614200048.php create mode 100644 .history/resources/views/user/rumah.blade_20260614200057.php create mode 100644 .history/resources/views/user/rumah.blade_20260614200225.php create mode 100644 .history/resources/views/user/rumah.blade_20260614200235.php create mode 100644 .history/resources/views/user/rumah.blade_20260614200259.php create mode 100644 .history/resources/views/user/rumah.blade_20260614200301.php create mode 100644 .history/resources/views/user/rumah.blade_20260614200303.php create mode 100644 .history/resources/views/user/rumah.blade_20260614200304.php create mode 100644 .history/resources/views/user/rumah.blade_20260614200306.php create mode 100644 .history/resources/views/user/rumah.blade_20260614200320.php create mode 100644 .history/resources/views/user/rumah.blade_20260614200324.php create mode 100644 .history/resources/views/user/rumah.blade_20260614200342.php create mode 100644 .history/resources/views/user/rumah.blade_20260614200349.php create mode 100644 .history/resources/views/user/rumah.blade_20260614200628.php create mode 100644 .history/resources/views/user/rumah.blade_20260614200636.php create mode 100644 .history/resources/views/user/rumah.blade_20260614200719.php create mode 100644 .history/resources/views/user/rumah.blade_20260614200723.php create mode 100644 .history/resources/views/user/rumah.blade_20260614200804.php create mode 100644 .history/resources/views/user/rumah.blade_20260614200808.php create mode 100644 .history/resources/views/user/rumah.blade_20260614202400.php create mode 100644 .history/resources/views/user/rumah.blade_20260614202422.php create mode 100644 .history/resources/views/user/rumah.blade_20260614202622.php create mode 100644 .history/resources/views/user/rumah.blade_20260614202624.php create mode 100644 .history/resources/views/user/rumah.blade_20260614202626.php create mode 100644 .history/resources/views/user/rumah.blade_20260614202629.php create mode 100644 .history/resources/views/user/rumah.blade_20260614202632.php create mode 100644 .history/resources/views/user/rumah.blade_20260614202636.php create mode 100644 .history/resources/views/user/rumah.blade_20260614202638.php create mode 100644 .history/resources/views/user/rumah.blade_20260614202718.php create mode 100644 .history/resources/views/user/rumah.blade_20260614202937.php delete mode 100644 .history/routes/web_20260520130451.php delete mode 100644 .history/routes/web_20260520225300.php delete mode 100644 .history/routes/web_20260520225304.php delete mode 100644 .history/routes/web_20260520231651.php delete mode 100644 .history/routes/web_20260520231712.php delete mode 100644 .history/routes/web_20260520232111.php delete mode 100644 .history/routes/web_20260520232144.php delete mode 100644 .history/routes/web_20260520232604.php delete mode 100644 .history/routes/web_20260520232630.php delete mode 100644 .history/routes/web_20260520232913.php delete mode 100644 .history/routes/web_20260520233138.php delete mode 100644 .history/routes/web_20260520233343.php delete mode 100644 .history/routes/web_20260520234406.php delete mode 100644 .history/routes/web_20260520234408.php delete mode 100644 .history/routes/web_20260520234411.php delete mode 100644 .history/routes/web_20260520234412.php delete mode 100644 .history/routes/web_20260521002413.php rename .history/routes/{web_20260521003138.php => web_20260615175706.php} (97%) rename .history/routes/{web_20260506190711.php => web_20260615175712.php} (96%) create mode 100644 .history/routes/web_20260619003354.php create mode 100644 .history/routes/web_20260619003355.php create mode 100644 .history/routes/web_20260619090711.php create mode 100644 .history/routes/web_20260619091403.php create mode 100644 .history/routes/web_20260619091405.php create mode 100644 .history/routes/web_20260619091429.php create mode 100644 .history/routes/web_20260619100048.php create mode 100644 .history/routes/web_20260619100050.php create mode 100644 .history/routes/web_20260619100052.php create mode 100644 .history/routes/web_20260619100111.php create mode 100644 .history/routes/web_20260619100112.php create mode 100644 .history/routes/web_20260619100119.php create mode 100644 .history/routes/web_20260619100140.php create mode 100644 .history/routes/web_20260619103632.php create mode 100644 .history/routes/web_20260619103636.php create mode 100644 .history/routes/web_20260619110515.php create mode 100644 .history/routes/web_20260619110520.php create mode 100644 .history/routes/web_20260619111140.php create mode 100644 .history/routes/web_20260619190122.php create mode 100644 .history/routes/web_20260619190125.php create mode 100644 .history/routes/web_20260619190235.php create mode 100644 .history/routes/web_20260619190237.php create mode 100644 .history/routes/web_20260619212831.php create mode 100644 .history/routes/web_20260619212833.php create mode 100644 .history/routes/web_20260619212847.php create mode 100644 .history/routes/web_20260619212850.php create mode 100644 .history/routes/web_20260619212856.php create mode 100644 .history/routes/web_20260619212900.php create mode 100644 .history/routes/web_20260619212907.php create mode 100644 .history/routes/web_20260619212930.php create mode 100644 .history/routes/web_20260619212937.php create mode 100644 .history/routes/web_20260619214532.php create mode 100644 .history/routes/web_20260620132444.php create mode 100644 .history/routes/web_20260620132729.php create mode 100644 .history/routes/web_20260620135103.php create mode 100644 .history/routes/web_20260620143722.php create mode 100644 .history/routes/web_20260620143724.php create mode 100644 .history/routes/web_20260624224135.php create mode 100644 .history/routes/web_20260624224233.php create mode 100644 .history/routes/web_20260625013633.php create mode 100644 app/Http/Controllers/Bendahara/GantiPasswordController.php create mode 100644 app/Http/Controllers/Bendahara/IuranController.php create mode 100644 app/Http/Controllers/Bendahara/KasController.php create mode 100644 app/Http/Controllers/Bendahara/RekapController.php create mode 100644 app/Http/Controllers/RT/BendaharaController.php create mode 100644 app/Http/Controllers/RT/KasRTController.php create mode 100644 app/Http/Controllers/RT/ReviewIuranController.php create mode 100644 app/Http/Controllers/RT/ReviewRekapController.php create mode 100644 app/Http/Controllers/UserKasController.php create mode 100644 app/Http/Middleware/CheckRole.php create mode 100644 app/Http/Middleware/CheckStatusAkun.php create mode 100644 app/Http/Middleware/ForcePasswordChange.php create mode 100644 app/Mail/NotifPengaduanSelesai.php create mode 100644 app/Models/KasBendahara.php create mode 100644 app/Models/RekapIuran.php create mode 100644 app/Services/WhatsappService.php create mode 100644 database/migrations/2026_06_18_222120_add_bendahara_columns_to_users_table.php create mode 100644 database/migrations/2026_06_18_223156_add_bendahara_columns_to_iuran_table.php create mode 100644 database/migrations/2026_06_18_224252_create_rekap_iuran_table.php create mode 100644 database/migrations/2026_06_18_224445_create_kas_bendahara_table.php create mode 100644 database/migrations/2026_06_19_104835_add_wajib_ganti_password_to_users_table.php create mode 100644 database/migrations/2026_06_19_193624_add_tagihan_columns_to_kas_bendahara_table.php create mode 100644 public/bukti/1781494398.jpeg create mode 100644 public/bukti/1781495172.png create mode 100644 public/bukti/1781524095.jpeg create mode 100644 public/bukti/1781765374.png create mode 100644 public/bukti/1781867951.jpeg create mode 100644 public/bukti/1781920365_kas.jpeg create mode 100644 public/bukti/1781920711.jpeg create mode 100644 public/bukti/1781921394.jpeg create mode 100644 public/bukti/1781939498.jpeg create mode 100644 public/bukti/1782219223.jpeg create mode 100644 public/bukti/1782219503_kas.png create mode 100644 public/bukti/1782308827.png create mode 100644 public/bukti/1782308961_kas.png create mode 100644 public/foto_rumah/1779372927.jpeg create mode 100644 public/informasi/1780985587.jpg create mode 100644 public/informasi/1780985792.jpg create mode 100644 public/informasi/1781766199.jpg create mode 100644 public/qris/qris_baru.png create mode 100644 public/qris/qris_code_clean.jpg create mode 100644 resources/views/bendahara - Shortcut.lnk create mode 100644 resources/views/bendahara/ganti-password/form.blade.php create mode 100644 resources/views/bendahara/iuran/create.blade.php create mode 100644 resources/views/bendahara/iuran/edit.blade.php create mode 100644 resources/views/bendahara/iuran/index.blade.php create mode 100644 resources/views/bendahara/kas/create-tagihan.blade.php create mode 100644 resources/views/bendahara/kas/index.blade.php create mode 100644 resources/views/bendahara/rekap/index.blade.php create mode 100644 resources/views/bendahara/rekap/show.blade.php create mode 100644 resources/views/components/sidebar_bendahara.blade.php create mode 100644 resources/views/emails/pengaduan_selesai.blade.php create mode 100644 resources/views/rt/bendahara/index.blade.php create mode 100644 resources/views/rt/kas/index.blade.php create mode 100644 resources/views/rt/laporan/cetak.blade.php create mode 100644 resources/views/rt/laporan/index.blade.php create mode 100644 resources/views/rt/review-iuran/index.blade.php create mode 100644 resources/views/rt/review-rekap/index.blade.php create mode 100644 resources/views/rt/review-rekap/show.blade.php create mode 100644 resources/views/user/kas/upload.blade.php diff --git a/.history/.env_20260414140457 b/.history/.env_20260414140457 deleted file mode 100644 index c9c0a93..0000000 --- a/.history/.env_20260414140457 +++ /dev/null @@ -1,66 +0,0 @@ -APP_NAME=Laravel -APP_ENV=local -APP_KEY=base64:VGjxoHXnll7wWiXgXTzgWYAFLsyenxO+NwqA4c4Tu6k= -APP_DEBUG=true -APP_TIMEZONE=UTC -APP_URL=http://localhost - -APP_LOCALE=en -APP_FALLBACK_LOCALE=en -APP_FAKER_LOCALE=en_US - -APP_MAINTENANCE_DRIVER=file -APP_MAINTENANCE_STORE=database - -BCRYPT_ROUNDS=12 - -LOG_CHANNEL=stack -LOG_STACK=single -LOG_DEPRECATIONS_CHANNEL=null -LOG_LEVEL=debug - -DB_CONNECTION=mysql -DB_HOST=127.0.0.1 -DB_PORT=3306 -DB_DATABASE=greenview -DB_USERNAME=root -DB_PASSWORD= - -FONNTE_TOKEN=chpBEnbbsP7BEZQnZ6jj - -SESSION_DRIVER=file -SESSION_LIFETIME=120 -SESSION_ENCRYPT=false -SESSION_PATH=/ -SESSION_DOMAIN=null - -BROADCAST_CONNECTION=log -FILESYSTEM_DISK=local -QUEUE_CONNECTION=database - -CACHE_STORE=database -CACHE_PREFIX= - -MEMCACHED_HOST=127.0.0.1 - -REDIS_CLIENT=phpredis -REDIS_HOST=127.0.0.1 -REDIS_PASSWORD=null -REDIS_PORT=6379 - -MAIL_MAILER=smtp -MAIL_HOST=smtp.gmail.com -MAIL_PORT=587 -MAIL_USERNAME=mlnryan05@gmail.com -MAIL_PASSWORD=qntezkkuhlrgnxzs -MAIL_ENCRYPTION=tls -MAIL_FROM_ADDRESS=mlnryan05@gmail.com -MAIL_FROM_NAME="Green View" - -AWS_ACCESS_KEY_ID= -AWS_SECRET_ACCESS_KEY= -AWS_DEFAULT_REGION=us-east-1 -AWS_BUCKET= -AWS_USE_PATH_STYLE_ENDPOINT=false - -VITE_APP_NAME="${APP_NAME}" diff --git a/.history/.env_20260516092137 b/.history/.env_20260516092137 deleted file mode 100644 index 6e7745b..0000000 --- a/.history/.env_20260516092137 +++ /dev/null @@ -1,66 +0,0 @@ -APP_NAME=Laravel -APP_ENV=local -APP_KEY=base64:VGjxoHXnll7wWiXgXTzgWYAFLsyenxO+NwqA4c4Tu6k= -APP_DEBUG=true -APP_TIMEZONE=UTC -APP_URL=http://localhost - -APP_LOCALE=en -APP_FALLBACK_LOCALE=en -APP_FAKER_LOCALE=en_US - -APP_MAINTENANCE_DRIVER=file -APP_MAINTENANCE_STORE=database - -BCRYPT_ROUNDS=12 - -LOG_CHANNEL=stack -LOG_STACK=single -LOG_DEPRECATIONS_CHANNEL=null -LOG_LEVEL=debug - -DB_CONNECTION=mysql -DB_HOST=127.0.0.1 -DB_PORT=3306 -DB_DATABASE=greenview -DB_USERNAME=root -DB_PASSWORD= - -FONNTE_TOKEN= - -SESSION_DRIVER=file -SESSION_LIFETIME=120 -SESSION_ENCRYPT=false -SESSION_PATH=/ -SESSION_DOMAIN=null - -BROADCAST_CONNECTION=log -FILESYSTEM_DISK=local -QUEUE_CONNECTION=database - -CACHE_STORE=database -CACHE_PREFIX= - -MEMCACHED_HOST=127.0.0.1 - -REDIS_CLIENT=phpredis -REDIS_HOST=127.0.0.1 -REDIS_PASSWORD=null -REDIS_PORT=6379 - -MAIL_MAILER=smtp -MAIL_HOST=smtp.gmail.com -MAIL_PORT=587 -MAIL_USERNAME=mlnryan05@gmail.com -MAIL_PASSWORD=qntezkkuhlrgnxzs -MAIL_ENCRYPTION=tls -MAIL_FROM_ADDRESS=mlnryan05@gmail.com -MAIL_FROM_NAME="Green View" - -AWS_ACCESS_KEY_ID= -AWS_SECRET_ACCESS_KEY= -AWS_DEFAULT_REGION=us-east-1 -AWS_BUCKET= -AWS_USE_PATH_STYLE_ENDPOINT=false - -VITE_APP_NAME="${APP_NAME}" diff --git a/.history/.env_20260516092138 b/.history/.env_20260516092138 deleted file mode 100644 index 65ed640..0000000 --- a/.history/.env_20260516092138 +++ /dev/null @@ -1,66 +0,0 @@ -APP_NAME=Laravel -APP_ENV=local -APP_KEY=base64:VGjxoHXnll7wWiXgXTzgWYAFLsyenxO+NwqA4c4Tu6k= -APP_DEBUG=true -APP_TIMEZONE=UTC -APP_URL=http://localhost - -APP_LOCALE=en -APP_FALLBACK_LOCALE=en -APP_FAKER_LOCALE=en_US - -APP_MAINTENANCE_DRIVER=file -APP_MAINTENANCE_STORE=database - -BCRYPT_ROUNDS=12 - -LOG_CHANNEL=stack -LOG_STACK=single -LOG_DEPRECATIONS_CHANNEL=null -LOG_LEVEL=debug - -DB_CONNECTION=mysql -DB_HOST=127.0.0.1 -DB_PORT=3306 -DB_DATABASE=greenview -DB_USERNAME=root -DB_PASSWORD= - -FONNTE_TOKEN=CEAJquyLniASpRf76eT9 - -SESSION_DRIVER=file -SESSION_LIFETIME=120 -SESSION_ENCRYPT=false -SESSION_PATH=/ -SESSION_DOMAIN=null - -BROADCAST_CONNECTION=log -FILESYSTEM_DISK=local -QUEUE_CONNECTION=database - -CACHE_STORE=database -CACHE_PREFIX= - -MEMCACHED_HOST=127.0.0.1 - -REDIS_CLIENT=phpredis -REDIS_HOST=127.0.0.1 -REDIS_PASSWORD=null -REDIS_PORT=6379 - -MAIL_MAILER=smtp -MAIL_HOST=smtp.gmail.com -MAIL_PORT=587 -MAIL_USERNAME=mlnryan05@gmail.com -MAIL_PASSWORD=qntezkkuhlrgnxzs -MAIL_ENCRYPTION=tls -MAIL_FROM_ADDRESS=mlnryan05@gmail.com -MAIL_FROM_NAME="Green View" - -AWS_ACCESS_KEY_ID= -AWS_SECRET_ACCESS_KEY= -AWS_DEFAULT_REGION=us-east-1 -AWS_BUCKET= -AWS_USE_PATH_STYLE_ENDPOINT=false - -VITE_APP_NAME="${APP_NAME}" diff --git a/.history/.env_20260520085420 b/.history/.env_20260520085420 deleted file mode 100644 index 4166614..0000000 --- a/.history/.env_20260520085420 +++ /dev/null @@ -1,64 +0,0 @@ -APP_NAME=Laravel -APP_ENV=local -APP_KEY=base64:9781LeLTCZR2J6mqgZOpJqqjhLI6QNwwj1CqSUKLF7g= -APP_DEBUG=true -APP_TIMEZONE=UTC -APP_URL=http://localhost - -APP_LOCALE=en -APP_FALLBACK_LOCALE=en -APP_FAKER_LOCALE=en_US - -APP_MAINTENANCE_DRIVER=file -APP_MAINTENANCE_STORE=database - -BCRYPT_ROUNDS=12 - -LOG_CHANNEL=stack -LOG_STACK=single -LOG_DEPRECATIONS_CHANNEL=null -LOG_LEVEL=debug - -DB_CONNECTION=sqlite -DB_HOST=127.0.0.1 -DB_PORT=3306 -DB_DATABASE=laravel -DB_USERNAME=root -DB_PASSWORD= - -SESSION_DRIVER=database -SESSION_LIFETIME=120 -SESSION_ENCRYPT=false -SESSION_PATH=/ -SESSION_DOMAIN=null - -BROADCAST_CONNECTION=log -FILESYSTEM_DISK=local -QUEUE_CONNECTION=database - -CACHE_STORE=database -CACHE_PREFIX= - -MEMCACHED_HOST=127.0.0.1 - -REDIS_CLIENT=phpredis -REDIS_HOST=127.0.0.1 -REDIS_PASSWORD=null -REDIS_PORT=6379 - -MAIL_MAILER=log -MAIL_HOST=127.0.0.1 -MAIL_PORT=2525 -MAIL_USERNAME=null -MAIL_PASSWORD=null -MAIL_ENCRYPTION=null -MAIL_FROM_ADDRESS="hello@example.com" -MAIL_FROM_NAME="${APP_NAME}" - -AWS_ACCESS_KEY_ID= -AWS_SECRET_ACCESS_KEY= -AWS_DEFAULT_REGION=us-east-1 -AWS_BUCKET= -AWS_USE_PATH_STYLE_ENDPOINT=false - -VITE_APP_NAME="${APP_NAME}" diff --git a/.history/.env_20260520085427 b/.history/.env_20260520085427 deleted file mode 100644 index 9e5aab3..0000000 --- a/.history/.env_20260520085427 +++ /dev/null @@ -1,64 +0,0 @@ -APP_NAME=Laravel -APP_ENV=local -APP_KEY=base64:9781LeLTCZR2J6mqgZOpJqqjhLI6QNwwj1CqSUKLF7g= -APP_DEBUG=true -APP_TIMEZONE=UTC -APP_URL=http://localhost - -APP_LOCALE=en -APP_FALLBACK_LOCALE=en -APP_FAKER_LOCALE=en_US - -APP_MAINTENANCE_DRIVER=file -APP_MAINTENANCE_STORE=database - -BCRYPT_ROUNDS=12 - -LOG_CHANNEL=stack -LOG_STACK=single -LOG_DEPRECATIONS_CHANNEL=null -LOG_LEVEL=debug - -DB_CONNECTION=sqlite -DB_HOST=127.0.0.1 -DB_PORT=3306 -DB_DATABASE=greenview -DB_USERNAME=root -DB_PASSWORD= - -SESSION_DRIVER=database -SESSION_LIFETIME=120 -SESSION_ENCRYPT=false -SESSION_PATH=/ -SESSION_DOMAIN=null - -BROADCAST_CONNECTION=log -FILESYSTEM_DISK=local -QUEUE_CONNECTION=database - -CACHE_STORE=database -CACHE_PREFIX= - -MEMCACHED_HOST=127.0.0.1 - -REDIS_CLIENT=phpredis -REDIS_HOST=127.0.0.1 -REDIS_PASSWORD=null -REDIS_PORT=6379 - -MAIL_MAILER=log -MAIL_HOST=127.0.0.1 -MAIL_PORT=2525 -MAIL_USERNAME=null -MAIL_PASSWORD=null -MAIL_ENCRYPTION=null -MAIL_FROM_ADDRESS="hello@example.com" -MAIL_FROM_NAME="${APP_NAME}" - -AWS_ACCESS_KEY_ID= -AWS_SECRET_ACCESS_KEY= -AWS_DEFAULT_REGION=us-east-1 -AWS_BUCKET= -AWS_USE_PATH_STYLE_ENDPOINT=false - -VITE_APP_NAME="${APP_NAME}" diff --git a/.history/.env_20260520085434 b/.history/.env_20260520085434 deleted file mode 100644 index 175aec1..0000000 --- a/.history/.env_20260520085434 +++ /dev/null @@ -1,64 +0,0 @@ -APP_NAME=Laravel -APP_ENV=local -APP_KEY=base64:9781LeLTCZR2J6mqgZOpJqqjhLI6QNwwj1CqSUKLF7g= -APP_DEBUG=true -APP_TIMEZONE=UTC -APP_URL=http://localhost - -APP_LOCALE=en -APP_FALLBACK_LOCALE=en -APP_FAKER_LOCALE=en_US - -APP_MAINTENANCE_DRIVER=file -APP_MAINTENANCE_STORE=database - -BCRYPT_ROUNDS=12 - -LOG_CHANNEL=stack -LOG_STACK=single -LOG_DEPRECATIONS_CHANNEL=null -LOG_LEVEL=debug - -DB_CONNECTION=mysql -DB_HOST=127.0.0.1 -DB_PORT=3306 -DB_DATABASE=greenview -DB_USERNAME=root -DB_PASSWORD= - -SESSION_DRIVER=database -SESSION_LIFETIME=120 -SESSION_ENCRYPT=false -SESSION_PATH=/ -SESSION_DOMAIN=null - -BROADCAST_CONNECTION=log -FILESYSTEM_DISK=local -QUEUE_CONNECTION=database - -CACHE_STORE=database -CACHE_PREFIX= - -MEMCACHED_HOST=127.0.0.1 - -REDIS_CLIENT=phpredis -REDIS_HOST=127.0.0.1 -REDIS_PASSWORD=null -REDIS_PORT=6379 - -MAIL_MAILER=log -MAIL_HOST=127.0.0.1 -MAIL_PORT=2525 -MAIL_USERNAME=null -MAIL_PASSWORD=null -MAIL_ENCRYPTION=null -MAIL_FROM_ADDRESS="hello@example.com" -MAIL_FROM_NAME="${APP_NAME}" - -AWS_ACCESS_KEY_ID= -AWS_SECRET_ACCESS_KEY= -AWS_DEFAULT_REGION=us-east-1 -AWS_BUCKET= -AWS_USE_PATH_STYLE_ENDPOINT=false - -VITE_APP_NAME="${APP_NAME}" diff --git a/.history/.env_20260520085648 b/.history/.env_20260520085648 deleted file mode 100644 index f8c4e3d..0000000 --- a/.history/.env_20260520085648 +++ /dev/null @@ -1,66 +0,0 @@ -APP_NAME=Laravel -APP_ENV=local -APP_KEY=base64:9781LeLTCZR2J6mqgZOpJqqjhLI6QNwwj1CqSUKLF7g= -APP_DEBUG=true -APP_TIMEZONE=UTC -APP_URL=http://localhost - -APP_LOCALE=en -APP_FALLBACK_LOCALE=en -APP_FAKER_LOCALE=en_US - -APP_MAINTENANCE_DRIVER=file -APP_MAINTENANCE_STORE=database - -BCRYPT_ROUNDS=12 - -LOG_CHANNEL=stack -LOG_STACK=single -LOG_DEPRECATIONS_CHANNEL=null -LOG_LEVEL=debug - -DB_CONNECTION=mysql -DB_HOST=127.0.0.1 -DB_PORT=3306 -DB_DATABASE=greenview -DB_USERNAME=root -DB_PASSWORD= - -FONNTE_TOKEN=chpBEnbbsP7BEZQnZ6jj - -SESSION_DRIVER=file -SESSION_LIFETIME=120 -SESSION_ENCRYPT=false -SESSION_PATH=/ -SESSION_DOMAIN=null - -BROADCAST_CONNECTION=log -FILESYSTEM_DISK=local -QUEUE_CONNECTION=database - -CACHE_STORE=database -CACHE_PREFIX= - -MEMCACHED_HOST=127.0.0.1 - -REDIS_CLIENT=phpredis -REDIS_HOST=127.0.0.1 -REDIS_PASSWORD=null -REDIS_PORT=6379 - -MAIL_MAILER=smtp -MAIL_HOST=smtp.gmail.com -MAIL_PORT=587 -MAIL_USERNAME=mlnryan05@gmail.com -MAIL_PASSWORD=qntezkkuhlrgnxzs -MAIL_ENCRYPTION=tls -MAIL_FROM_ADDRESS=mlnryan05@gmail.com -MAIL_FROM_NAME="Green View" - -AWS_ACCESS_KEY_ID= -AWS_SECRET_ACCESS_KEY= -AWS_DEFAULT_REGION=us-east-1 -AWS_BUCKET= -AWS_USE_PATH_STYLE_ENDPOINT=false - -VITE_APP_NAME="${APP_NAME}" diff --git a/.history/.env_20260520085725 b/.history/.env_20260520085725 deleted file mode 100644 index a1870d1..0000000 --- a/.history/.env_20260520085725 +++ /dev/null @@ -1,66 +0,0 @@ -APP_NAME=Laravel -APP_ENV=local -APP_KEY=base64:9781LeLTCZR2J6mqgZOpJqqjhLI6QNwwj1CqSUKLF7g= -APP_DEBUG=true -APP_TIMEZONE=UTC -APP_URL=http://localhost - -APP_LOCALE=en -APP_FALLBACK_LOCALE=en -APP_FAKER_LOCALE=en_US - -APP_MAINTENANCE_DRIVER=file -APP_MAINTENANCE_STORE=database - -BCRYPT_ROUNDS=12 - -LOG_CHANNEL=stack -LOG_STACK=single -LOG_DEPRECATIONS_CHANNEL=null -LOG_LEVEL=debug - -DB_CONNECTION=mysql -DB_HOST=127.0.0.1 -DB_PORT=3306 -DB_DATABASE=greenview -DB_USERNAME=root -DB_PASSWORD= - -FONNTE_TOKEN=CEAJquyLniASpRf76eT9 - -SESSION_DRIVER=file -SESSION_LIFETIME=120 -SESSION_ENCRYPT=false -SESSION_PATH=/ -SESSION_DOMAIN=null - -BROADCAST_CONNECTION=log -FILESYSTEM_DISK=local -QUEUE_CONNECTION=database - -CACHE_STORE=database -CACHE_PREFIX= - -MEMCACHED_HOST=127.0.0.1 - -REDIS_CLIENT=phpredis -REDIS_HOST=127.0.0.1 -REDIS_PASSWORD=null -REDIS_PORT=6379 - -MAIL_MAILER=smtp -MAIL_HOST=smtp.gmail.com -MAIL_PORT=587 -MAIL_USERNAME=mlnryan05@gmail.com -MAIL_PASSWORD=qntezkkuhlrgnxzs -MAIL_ENCRYPTION=tls -MAIL_FROM_ADDRESS=mlnryan05@gmail.com -MAIL_FROM_NAME="Green View" - -AWS_ACCESS_KEY_ID= -AWS_SECRET_ACCESS_KEY= -AWS_DEFAULT_REGION=us-east-1 -AWS_BUCKET= -AWS_USE_PATH_STYLE_ENDPOINT=false - -VITE_APP_NAME="${APP_NAME}" diff --git a/.history/.env_20260520085919 b/.history/.env_20260520085919 deleted file mode 100644 index dcff930..0000000 --- a/.history/.env_20260520085919 +++ /dev/null @@ -1,64 +0,0 @@ -APP_NAME=Laravel -APP_ENV=local -APP_KEY=base64:9781LeLTCZR2J6mqgZOpJqqjhLI6QNwwj1CqSUKLF7g= -APP_DEBUG=true -APP_TIMEZONE=UTC -APP_URL=http://localhost - -APP_LOCALE=en -APP_FALLBACK_LOCALE=en -APP_FAKER_LOCALE=en_US - -APP_MAINTENANCE_DRIVER=file -APP_MAINTENANCE_STORE=database - -BCRYPT_ROUNDS=12 - -LOG_CHANNEL=stack -LOG_STACK=single -LOG_DEPRECATIONS_CHANNEL=null -LOG_LEVEL=debug - -DB_CONNECTION=sqlite -# DB_HOST=127.0.0.1 -# DB_PORT=3306 -# DB_DATABASE=laravel -# DB_USERNAME=root -# DB_PASSWORD= - -SESSION_DRIVER=database -SESSION_LIFETIME=120 -SESSION_ENCRYPT=false -SESSION_PATH=/ -SESSION_DOMAIN=null - -BROADCAST_CONNECTION=log -FILESYSTEM_DISK=local -QUEUE_CONNECTION=database - -CACHE_STORE=database -CACHE_PREFIX= - -MEMCACHED_HOST=127.0.0.1 - -REDIS_CLIENT=phpredis -REDIS_HOST=127.0.0.1 -REDIS_PASSWORD=null -REDIS_PORT=6379 - -MAIL_MAILER=log -MAIL_HOST=127.0.0.1 -MAIL_PORT=2525 -MAIL_USERNAME=null -MAIL_PASSWORD=null -MAIL_ENCRYPTION=null -MAIL_FROM_ADDRESS="hello@example.com" -MAIL_FROM_NAME="${APP_NAME}" - -AWS_ACCESS_KEY_ID= -AWS_SECRET_ACCESS_KEY= -AWS_DEFAULT_REGION=us-east-1 -AWS_BUCKET= -AWS_USE_PATH_STYLE_ENDPOINT=false - -VITE_APP_NAME="${APP_NAME}" diff --git a/.history/.env_20260520090106 b/.history/.env_20260520090106 deleted file mode 100644 index a1870d1..0000000 --- a/.history/.env_20260520090106 +++ /dev/null @@ -1,66 +0,0 @@ -APP_NAME=Laravel -APP_ENV=local -APP_KEY=base64:9781LeLTCZR2J6mqgZOpJqqjhLI6QNwwj1CqSUKLF7g= -APP_DEBUG=true -APP_TIMEZONE=UTC -APP_URL=http://localhost - -APP_LOCALE=en -APP_FALLBACK_LOCALE=en -APP_FAKER_LOCALE=en_US - -APP_MAINTENANCE_DRIVER=file -APP_MAINTENANCE_STORE=database - -BCRYPT_ROUNDS=12 - -LOG_CHANNEL=stack -LOG_STACK=single -LOG_DEPRECATIONS_CHANNEL=null -LOG_LEVEL=debug - -DB_CONNECTION=mysql -DB_HOST=127.0.0.1 -DB_PORT=3306 -DB_DATABASE=greenview -DB_USERNAME=root -DB_PASSWORD= - -FONNTE_TOKEN=CEAJquyLniASpRf76eT9 - -SESSION_DRIVER=file -SESSION_LIFETIME=120 -SESSION_ENCRYPT=false -SESSION_PATH=/ -SESSION_DOMAIN=null - -BROADCAST_CONNECTION=log -FILESYSTEM_DISK=local -QUEUE_CONNECTION=database - -CACHE_STORE=database -CACHE_PREFIX= - -MEMCACHED_HOST=127.0.0.1 - -REDIS_CLIENT=phpredis -REDIS_HOST=127.0.0.1 -REDIS_PASSWORD=null -REDIS_PORT=6379 - -MAIL_MAILER=smtp -MAIL_HOST=smtp.gmail.com -MAIL_PORT=587 -MAIL_USERNAME=mlnryan05@gmail.com -MAIL_PASSWORD=qntezkkuhlrgnxzs -MAIL_ENCRYPTION=tls -MAIL_FROM_ADDRESS=mlnryan05@gmail.com -MAIL_FROM_NAME="Green View" - -AWS_ACCESS_KEY_ID= -AWS_SECRET_ACCESS_KEY= -AWS_DEFAULT_REGION=us-east-1 -AWS_BUCKET= -AWS_USE_PATH_STYLE_ENDPOINT=false - -VITE_APP_NAME="${APP_NAME}" diff --git a/.history/.env_20260520115238 b/.history/.env_20260520115238 deleted file mode 100644 index cea03b5..0000000 --- a/.history/.env_20260520115238 +++ /dev/null @@ -1,66 +0,0 @@ -APP_NAME=Laravel -APP_ENV=local -APP_KEY=base64:iHPDeCnviINzk4hSncvHa8qFuz+iPW99xH+dHwxMhxQ= -APP_DEBUG=true -APP_TIMEZONE=UTC -APP_URL=http://localhost - -APP_LOCALE=en -APP_FALLBACK_LOCALE=en -APP_FAKER_LOCALE=en_US - -APP_MAINTENANCE_DRIVER=file -APP_MAINTENANCE_STORE=database - -BCRYPT_ROUNDS=12 - -LOG_CHANNEL=stack -LOG_STACK=single -LOG_DEPRECATIONS_CHANNEL=null -LOG_LEVEL=debug - -DB_CONNECTION=mysql -DB_HOST=127.0.0.1 -DB_PORT=3306 -DB_DATABASE=greenview -DB_USERNAME=root -DB_PASSWORD= - -FONNTE_TOKEN=CEAJquyLniASpRf76eT9 - -SESSION_DRIVER=file -SESSION_LIFETIME=120 -SESSION_ENCRYPT=false -SESSION_PATH=/ -SESSION_DOMAIN=null - -BROADCAST_CONNECTION=log -FILESYSTEM_DISK=local -QUEUE_CONNECTION=database - -CACHE_STORE=database -CACHE_PREFIX= - -MEMCACHED_HOST=127.0.0.1 - -REDIS_CLIENT=phpredis -REDIS_HOST=127.0.0.1 -REDIS_PASSWORD=null -REDIS_PORT=6379 - -MAIL_MAILER=smtp -MAIL_HOST=smtp.gmail.com -MAIL_PORT=587 -MAIL_USERNAME=mlnryan05@gmail.com -MAIL_PASSWORD=aqjm nueu xlgt fpej -MAIL_ENCRYPTION=tls -MAIL_FROM_ADDRESS=mlnryan05@gmail.com -MAIL_FROM_NAME="Green View" - -AWS_ACCESS_KEY_ID= -AWS_SECRET_ACCESS_KEY= -AWS_DEFAULT_REGION=us-east-1 -AWS_BUCKET= -AWS_USE_PATH_STYLE_ENDPOINT=false - -VITE_APP_NAME="${APP_NAME}" diff --git a/.history/.env_20260520115247 b/.history/.env_20260520115247 deleted file mode 100644 index b0ad04b..0000000 --- a/.history/.env_20260520115247 +++ /dev/null @@ -1,66 +0,0 @@ -APP_NAME=Laravel -APP_ENV=local -APP_KEY=base64:iHPDeCnviINzk4hSncvHa8qFuz+iPW99xH+dHwxMhxQ= -APP_DEBUG=true -APP_TIMEZONE=UTC -APP_URL=http://localhost - -APP_LOCALE=en -APP_FALLBACK_LOCALE=en -APP_FAKER_LOCALE=en_US - -APP_MAINTENANCE_DRIVER=file -APP_MAINTENANCE_STORE=database - -BCRYPT_ROUNDS=12 - -LOG_CHANNEL=stack -LOG_STACK=single -LOG_DEPRECATIONS_CHANNEL=null -LOG_LEVEL=debug - -DB_CONNECTION=mysql -DB_HOST=127.0.0.1 -DB_PORT=3306 -DB_DATABASE=greenview -DB_USERNAME=root -DB_PASSWORD= - -FONNTE_TOKEN=CEAJquyLniASpRf76eT9 - -SESSION_DRIVER=file -SESSION_LIFETIME=120 -SESSION_ENCRYPT=false -SESSION_PATH=/ -SESSION_DOMAIN=null - -BROADCAST_CONNECTION=log -FILESYSTEM_DISK=local -QUEUE_CONNECTION=database - -CACHE_STORE=database -CACHE_PREFIX= - -MEMCACHED_HOST=127.0.0.1 - -REDIS_CLIENT=phpredis -REDIS_HOST=127.0.0.1 -REDIS_PASSWORD=null -REDIS_PORT=6379 - -MAIL_MAILER=smtp -MAIL_HOST=smtp.gmail.com -MAIL_PORT=587 -MAIL_USERNAME=mlnryan05@gmail.com -MAIL_PASSWORD=aqjm nueu xlgtfpej -MAIL_ENCRYPTION=tls -MAIL_FROM_ADDRESS=mlnryan05@gmail.com -MAIL_FROM_NAME="Green View" - -AWS_ACCESS_KEY_ID= -AWS_SECRET_ACCESS_KEY= -AWS_DEFAULT_REGION=us-east-1 -AWS_BUCKET= -AWS_USE_PATH_STYLE_ENDPOINT=false - -VITE_APP_NAME="${APP_NAME}" diff --git a/.history/.env_20260520115411 b/.history/.env_20260520115411 deleted file mode 100644 index f95589a..0000000 --- a/.history/.env_20260520115411 +++ /dev/null @@ -1,66 +0,0 @@ -APP_NAME=Laravel -APP_ENV=local -APP_KEY=base64:iHPDeCnviINzk4hSncvHa8qFuz+iPW99xH+dHwxMhxQ= -APP_DEBUG=true -APP_TIMEZONE=UTC -APP_URL=http://localhost - -APP_LOCALE=en -APP_FALLBACK_LOCALE=en -APP_FAKER_LOCALE=en_US - -APP_MAINTENANCE_DRIVER=file -APP_MAINTENANCE_STORE=database - -BCRYPT_ROUNDS=12 - -LOG_CHANNEL=stack -LOG_STACK=single -LOG_DEPRECATIONS_CHANNEL=null -LOG_LEVEL=debug - -DB_CONNECTION=mysql -DB_HOST=127.0.0.1 -DB_PORT=3306 -DB_DATABASE=greenview -DB_USERNAME=root -DB_PASSWORD= - -FONNTE_TOKEN=CEAJquyLniASpRf76eT9 - -SESSION_DRIVER=file -SESSION_LIFETIME=120 -SESSION_ENCRYPT=false -SESSION_PATH=/ -SESSION_DOMAIN=null - -BROADCAST_CONNECTION=log -FILESYSTEM_DISK=local -QUEUE_CONNECTION=database - -CACHE_STORE=database -CACHE_PREFIX= - -MEMCACHED_HOST=127.0.0.1 - -REDIS_CLIENT=phpredis -REDIS_HOST=127.0.0.1 -REDIS_PASSWORD=null -REDIS_PORT=6379 - -MAIL_MAILER=smtp -MAIL_HOST=smtp.gmail.com -MAIL_PORT=587 -MAIL_USERNAME= -MAIL_PASSWORD=aqjmnueuxlgtfpej -MAIL_ENCRYPTION=tls -MAIL_FROM_ADDRESS=mlnryan05@gmail.com -MAIL_FROM_NAME="Green View" - -AWS_ACCESS_KEY_ID= -AWS_SECRET_ACCESS_KEY= -AWS_DEFAULT_REGION=us-east-1 -AWS_BUCKET= -AWS_USE_PATH_STYLE_ENDPOINT=false - -VITE_APP_NAME="${APP_NAME}" diff --git a/.history/.env_20260520115419 b/.history/.env_20260520115419 deleted file mode 100644 index 66c932d..0000000 --- a/.history/.env_20260520115419 +++ /dev/null @@ -1,66 +0,0 @@ -APP_NAME=Laravel -APP_ENV=local -APP_KEY=base64:iHPDeCnviINzk4hSncvHa8qFuz+iPW99xH+dHwxMhxQ= -APP_DEBUG=true -APP_TIMEZONE=UTC -APP_URL=http://localhost - -APP_LOCALE=en -APP_FALLBACK_LOCALE=en -APP_FAKER_LOCALE=en_US - -APP_MAINTENANCE_DRIVER=file -APP_MAINTENANCE_STORE=database - -BCRYPT_ROUNDS=12 - -LOG_CHANNEL=stack -LOG_STACK=single -LOG_DEPRECATIONS_CHANNEL=null -LOG_LEVEL=debug - -DB_CONNECTION=mysql -DB_HOST=127.0.0.1 -DB_PORT=3306 -DB_DATABASE=greenview -DB_USERNAME=root -DB_PASSWORD= - -FONNTE_TOKEN=CEAJquyLniASpRf76eT9 - -SESSION_DRIVER=file -SESSION_LIFETIME=120 -SESSION_ENCRYPT=false -SESSION_PATH=/ -SESSION_DOMAIN=null - -BROADCAST_CONNECTION=log -FILESYSTEM_DISK=local -QUEUE_CONNECTION=database - -CACHE_STORE=database -CACHE_PREFIX= - -MEMCACHED_HOST=127.0.0.1 - -REDIS_CLIENT=phpredis -REDIS_HOST=127.0.0.1 -REDIS_PASSWORD=null -REDIS_PORT=6379 - -MAIL_MAILER=smtp -MAIL_HOST=smtp.gmail.com -MAIL_PORT=587 -MAIL_USERNAME=unieiffel@gmail.com -MAIL_PASSWORD=aqjmnueuxlgtfpej -MAIL_ENCRYPTION=tls -MAIL_FROM_ADDRESS=mlnryan05@gmail.com -MAIL_FROM_NAME="Green View" - -AWS_ACCESS_KEY_ID= -AWS_SECRET_ACCESS_KEY= -AWS_DEFAULT_REGION=us-east-1 -AWS_BUCKET= -AWS_USE_PATH_STYLE_ENDPOINT=false - -VITE_APP_NAME="${APP_NAME}" diff --git a/.history/.env_20260521114440 b/.history/.env_20260521114440 deleted file mode 100644 index 35ebd95..0000000 --- a/.history/.env_20260521114440 +++ /dev/null @@ -1,66 +0,0 @@ -APP_NAME=Laravel -APP_ENV=local -APP_KEY=base64:iHPDeCnviINzk4hSncvHa8qFuz+iPW99xH+dHwxMhxQ= -APP_DEBUG=true -APP_TIMEZONE=UTC -APP_URL=http://localhost - -APP_LOCALE=en -APP_FALLBACK_LOCALE=en -APP_FAKER_LOCALE=en_US - -APP_MAINTENANCE_DRIVER=file -APP_MAINTENANCE_STORE=database - -BCRYPT_ROUNDS=12 - -LOG_CHANNEL=stack -LOG_STACK=single -LOG_DEPRECATIONS_CHANNEL=null -LOG_LEVEL=debug - -DB_CONNECTION=mysql -DB_HOST=127.0.0.1 -DB_PORT=3306 -DB_DATABASE=greenview -DB_USERNAME=root -DB_PASSWORD= - -FONNTE_TOKEN=CEAJquyLniASpRf76eT9 - -SESSION_DRIVER=file -SESSION_LIFETIME=120 -SESSION_ENCRYPT=false -SESSION_PATH=/ -SESSION_DOMAIN=null - -BROADCAST_CONNECTION=log -FILESYSTEM_DISK=local -QUEUE_CONNECTION=database - -CACHE_STORE=database -CACHE_PREFIX= - -MEMCACHED_HOST=127.0.0.1 - -REDIS_CLIENT=phpredis -REDIS_HOST=127.0.0.1 -REDIS_PASSWORD=null -REDIS_PORT=6379 - -MAIL_MAILER=smtp -MAIL_HOST=smtp.gmail.com -MAIL_PORT=587 -MAIL_USERNAME=reyfandi3008@gmail.com -MAIL_PASSWORD=etvyujyiyrnmylil -MAIL_ENCRYPTION=tls -MAIL_FROM_ADDRESS=reyfandi3008@gmail.com -MAIL_FROM_NAME="Green View" - -AWS_ACCESS_KEY_ID= -AWS_SECRET_ACCESS_KEY= -AWS_DEFAULT_REGION=us-east-1 -AWS_BUCKET= -AWS_USE_PATH_STYLE_ENDPOINT=false - -VITE_APP_NAME="${APP_NAME}" diff --git a/.history/.env_20260521115228 b/.history/.env_20260521115228 deleted file mode 100644 index 35ebd95..0000000 --- a/.history/.env_20260521115228 +++ /dev/null @@ -1,66 +0,0 @@ -APP_NAME=Laravel -APP_ENV=local -APP_KEY=base64:iHPDeCnviINzk4hSncvHa8qFuz+iPW99xH+dHwxMhxQ= -APP_DEBUG=true -APP_TIMEZONE=UTC -APP_URL=http://localhost - -APP_LOCALE=en -APP_FALLBACK_LOCALE=en -APP_FAKER_LOCALE=en_US - -APP_MAINTENANCE_DRIVER=file -APP_MAINTENANCE_STORE=database - -BCRYPT_ROUNDS=12 - -LOG_CHANNEL=stack -LOG_STACK=single -LOG_DEPRECATIONS_CHANNEL=null -LOG_LEVEL=debug - -DB_CONNECTION=mysql -DB_HOST=127.0.0.1 -DB_PORT=3306 -DB_DATABASE=greenview -DB_USERNAME=root -DB_PASSWORD= - -FONNTE_TOKEN=CEAJquyLniASpRf76eT9 - -SESSION_DRIVER=file -SESSION_LIFETIME=120 -SESSION_ENCRYPT=false -SESSION_PATH=/ -SESSION_DOMAIN=null - -BROADCAST_CONNECTION=log -FILESYSTEM_DISK=local -QUEUE_CONNECTION=database - -CACHE_STORE=database -CACHE_PREFIX= - -MEMCACHED_HOST=127.0.0.1 - -REDIS_CLIENT=phpredis -REDIS_HOST=127.0.0.1 -REDIS_PASSWORD=null -REDIS_PORT=6379 - -MAIL_MAILER=smtp -MAIL_HOST=smtp.gmail.com -MAIL_PORT=587 -MAIL_USERNAME=reyfandi3008@gmail.com -MAIL_PASSWORD=etvyujyiyrnmylil -MAIL_ENCRYPTION=tls -MAIL_FROM_ADDRESS=reyfandi3008@gmail.com -MAIL_FROM_NAME="Green View" - -AWS_ACCESS_KEY_ID= -AWS_SECRET_ACCESS_KEY= -AWS_DEFAULT_REGION=us-east-1 -AWS_BUCKET= -AWS_USE_PATH_STYLE_ENDPOINT=false - -VITE_APP_NAME="${APP_NAME}" diff --git a/.history/.env_20260521115334 b/.history/.env_20260521115334 deleted file mode 100644 index 3cc29c1..0000000 --- a/.history/.env_20260521115334 +++ /dev/null @@ -1,66 +0,0 @@ -APP_NAME=Laravel -APP_ENV=local -APP_KEY=base64:iHPDeCnviINzk4hSncvHa8qFuz+iPW99xH+dHwxMhxQ= -APP_DEBUG=true -APP_TIMEZONE=UTC -APP_URL=http://localhost - -APP_LOCALE=en -APP_FALLBACK_LOCALE=en -APP_FAKER_LOCALE=en_US - -APP_MAINTENANCE_DRIVER=file -APP_MAINTENANCE_STORE=database - -BCRYPT_ROUNDS=12 - -LOG_CHANNEL=stack -LOG_STACK=single -LOG_DEPRECATIONS_CHANNEL=null -LOG_LEVEL=debug - -DB_CONNECTION=mysql -DB_HOST=127.0.0.1 -DB_PORT=3306 -DB_DATABASE=greenview -DB_USERNAME=root -DB_PASSWORD= - -FONNTE_TOKEN=CEAJquyLniASpRf76eT9 - -SESSION_DRIVER=file -SESSION_LIFETIME=120 -SESSION_ENCRYPT=false -SESSION_PATH=/ -SESSION_DOMAIN=null - -BROADCAST_CONNECTION=log -FILESYSTEM_DISK=local -QUEUE_CONNECTION=database - -CACHE_STORE=database -CACHE_PREFIX= - -MEMCACHED_HOST=127.0.0.1 - -REDIS_CLIENT=phpredis -REDIS_HOST=127.0.0.1 -REDIS_PASSWORD=null -REDIS_PORT=6379 - -MAIL_MAILER=smtp -MAIL_HOST=smtp.gmail.com -MAIL_PORT=587 -MAIL_USERNAME=reyfandi3008@gmail.com -MAIL_PASSWORD=vhw -MAIL_ENCRYPTION=tls -MAIL_FROM_ADDRESS=reyfandi3008@gmail.com -MAIL_FROM_NAME="Green View" - -AWS_ACCESS_KEY_ID= -AWS_SECRET_ACCESS_KEY= -AWS_DEFAULT_REGION=us-east-1 -AWS_BUCKET= -AWS_USE_PATH_STYLE_ENDPOINT=false - -VITE_APP_NAME="${APP_NAME}" diff --git a/.history/.env_20260521115335 b/.history/.env_20260521115335 deleted file mode 100644 index 3d1a76b..0000000 --- a/.history/.env_20260521115335 +++ /dev/null @@ -1,66 +0,0 @@ -APP_NAME=Laravel -APP_ENV=local -APP_KEY=base64:iHPDeCnviINzk4hSncvHa8qFuz+iPW99xH+dHwxMhxQ= -APP_DEBUG=true -APP_TIMEZONE=UTC -APP_URL=http://localhost - -APP_LOCALE=en -APP_FALLBACK_LOCALE=en -APP_FAKER_LOCALE=en_US - -APP_MAINTENANCE_DRIVER=file -APP_MAINTENANCE_STORE=database - -BCRYPT_ROUNDS=12 - -LOG_CHANNEL=stack -LOG_STACK=single -LOG_DEPRECATIONS_CHANNEL=null -LOG_LEVEL=debug - -DB_CONNECTION=mysql -DB_HOST=127.0.0.1 -DB_PORT=3306 -DB_DATABASE=greenview -DB_USERNAME=root -DB_PASSWORD= - -FONNTE_TOKEN=CEAJquyLniASpRf76eT9 - -SESSION_DRIVER=file -SESSION_LIFETIME=120 -SESSION_ENCRYPT=false -SESSION_PATH=/ -SESSION_DOMAIN=null - -BROADCAST_CONNECTION=log -FILESYSTEM_DISK=local -QUEUE_CONNECTION=database - -CACHE_STORE=database -CACHE_PREFIX= - -MEMCACHED_HOST=127.0.0.1 - -REDIS_CLIENT=phpredis -REDIS_HOST=127.0.0.1 -REDIS_PASSWORD=null -REDIS_PORT=6379 - -MAIL_MAILER=smtp -MAIL_HOST=smtp.gmail.com -MAIL_PORT=587 -MAIL_USERNAME=reyfandi3008@gmail.com -MAIL_PASSWORD=vhwc -MAIL_ENCRYPTION=tls -MAIL_FROM_ADDRESS=reyfandi3008@gmail.com -MAIL_FROM_NAME="Green View" - -AWS_ACCESS_KEY_ID= -AWS_SECRET_ACCESS_KEY= -AWS_DEFAULT_REGION=us-east-1 -AWS_BUCKET= -AWS_USE_PATH_STYLE_ENDPOINT=false - -VITE_APP_NAME="${APP_NAME}" diff --git a/.history/.env_20260521115338 b/.history/.env_20260521115338 deleted file mode 100644 index 20edafb..0000000 --- a/.history/.env_20260521115338 +++ /dev/null @@ -1,66 +0,0 @@ -APP_NAME=Laravel -APP_ENV=local -APP_KEY=base64:iHPDeCnviINzk4hSncvHa8qFuz+iPW99xH+dHwxMhxQ= -APP_DEBUG=true -APP_TIMEZONE=UTC -APP_URL=http://localhost - -APP_LOCALE=en -APP_FALLBACK_LOCALE=en -APP_FAKER_LOCALE=en_US - -APP_MAINTENANCE_DRIVER=file -APP_MAINTENANCE_STORE=database - -BCRYPT_ROUNDS=12 - -LOG_CHANNEL=stack -LOG_STACK=single -LOG_DEPRECATIONS_CHANNEL=null -LOG_LEVEL=debug - -DB_CONNECTION=mysql -DB_HOST=127.0.0.1 -DB_PORT=3306 -DB_DATABASE=greenview -DB_USERNAME=root -DB_PASSWORD= - -FONNTE_TOKEN=CEAJquyLniASpRf76eT9 - -SESSION_DRIVER=file -SESSION_LIFETIME=120 -SESSION_ENCRYPT=false -SESSION_PATH=/ -SESSION_DOMAIN=null - -BROADCAST_CONNECTION=log -FILESYSTEM_DISK=local -QUEUE_CONNECTION=database - -CACHE_STORE=database -CACHE_PREFIX= - -MEMCACHED_HOST=127.0.0.1 - -REDIS_CLIENT=phpredis -REDIS_HOST=127.0.0.1 -REDIS_PASSWORD=null -REDIS_PORT=6379 - -MAIL_MAILER=smtp -MAIL_HOST=smtp.gmail.com -MAIL_PORT=587 -MAIL_USERNAME=reyfandi3008@gmail.com -MAIL_PASSWORD=vhwckujp -MAIL_ENCRYPTION=tls -MAIL_FROM_ADDRESS=reyfandi3008@gmail.com -MAIL_FROM_NAME="Green View" - -AWS_ACCESS_KEY_ID= -AWS_SECRET_ACCESS_KEY= -AWS_DEFAULT_REGION=us-east-1 -AWS_BUCKET= -AWS_USE_PATH_STYLE_ENDPOINT=false - -VITE_APP_NAME="${APP_NAME}" diff --git a/.history/.env_20260521115339 b/.history/.env_20260521115339 deleted file mode 100644 index 596a99f..0000000 --- a/.history/.env_20260521115339 +++ /dev/null @@ -1,66 +0,0 @@ -APP_NAME=Laravel -APP_ENV=local -APP_KEY=base64:iHPDeCnviINzk4hSncvHa8qFuz+iPW99xH+dHwxMhxQ= -APP_DEBUG=true -APP_TIMEZONE=UTC -APP_URL=http://localhost - -APP_LOCALE=en -APP_FALLBACK_LOCALE=en -APP_FAKER_LOCALE=en_US - -APP_MAINTENANCE_DRIVER=file -APP_MAINTENANCE_STORE=database - -BCRYPT_ROUNDS=12 - -LOG_CHANNEL=stack -LOG_STACK=single -LOG_DEPRECATIONS_CHANNEL=null -LOG_LEVEL=debug - -DB_CONNECTION=mysql -DB_HOST=127.0.0.1 -DB_PORT=3306 -DB_DATABASE=greenview -DB_USERNAME=root -DB_PASSWORD= - -FONNTE_TOKEN=CEAJquyLniASpRf76eT9 - -SESSION_DRIVER=file -SESSION_LIFETIME=120 -SESSION_ENCRYPT=false -SESSION_PATH=/ -SESSION_DOMAIN=null - -BROADCAST_CONNECTION=log -FILESYSTEM_DISK=local -QUEUE_CONNECTION=database - -CACHE_STORE=database -CACHE_PREFIX= - -MEMCACHED_HOST=127.0.0.1 - -REDIS_CLIENT=phpredis -REDIS_HOST=127.0.0.1 -REDIS_PASSWORD=null -REDIS_PORT=6379 - -MAIL_MAILER=smtp -MAIL_HOST=smtp.gmail.com -MAIL_PORT=587 -MAIL_USERNAME=reyfandi3008@gmail.com -MAIL_PASSWORD=vhwckujpwp -MAIL_ENCRYPTION=tls -MAIL_FROM_ADDRESS=reyfandi3008@gmail.com -MAIL_FROM_NAME="Green View" - -AWS_ACCESS_KEY_ID= -AWS_SECRET_ACCESS_KEY= -AWS_DEFAULT_REGION=us-east-1 -AWS_BUCKET= -AWS_USE_PATH_STYLE_ENDPOINT=false - -VITE_APP_NAME="${APP_NAME}" diff --git a/.history/.env_20260521115342 b/.history/.env_20260521115342 deleted file mode 100644 index 79b5ea5..0000000 --- a/.history/.env_20260521115342 +++ /dev/null @@ -1,66 +0,0 @@ -APP_NAME=Laravel -APP_ENV=local -APP_KEY=base64:iHPDeCnviINzk4hSncvHa8qFuz+iPW99xH+dHwxMhxQ= -APP_DEBUG=true -APP_TIMEZONE=UTC -APP_URL=http://localhost - -APP_LOCALE=en -APP_FALLBACK_LOCALE=en -APP_FAKER_LOCALE=en_US - -APP_MAINTENANCE_DRIVER=file -APP_MAINTENANCE_STORE=database - -BCRYPT_ROUNDS=12 - -LOG_CHANNEL=stack -LOG_STACK=single -LOG_DEPRECATIONS_CHANNEL=null -LOG_LEVEL=debug - -DB_CONNECTION=mysql -DB_HOST=127.0.0.1 -DB_PORT=3306 -DB_DATABASE=greenview -DB_USERNAME=root -DB_PASSWORD= - -FONNTE_TOKEN=CEAJquyLniASpRf76eT9 - -SESSION_DRIVER=file -SESSION_LIFETIME=120 -SESSION_ENCRYPT=false -SESSION_PATH=/ -SESSION_DOMAIN=null - -BROADCAST_CONNECTION=log -FILESYSTEM_DISK=local -QUEUE_CONNECTION=database - -CACHE_STORE=database -CACHE_PREFIX= - -MEMCACHED_HOST=127.0.0.1 - -REDIS_CLIENT=phpredis -REDIS_HOST=127.0.0.1 -REDIS_PASSWORD=null -REDIS_PORT=6379 - -MAIL_MAILER=smtp -MAIL_HOST=smtp.gmail.com -MAIL_PORT=587 -MAIL_USERNAME=reyfandi3008@gmail.com -MAIL_PASSWORD=vhwckujpwpjk -MAIL_ENCRYPTION=tls -MAIL_FROM_ADDRESS=reyfandi3008@gmail.com -MAIL_FROM_NAME="Green View" - -AWS_ACCESS_KEY_ID= -AWS_SECRET_ACCESS_KEY= -AWS_DEFAULT_REGION=us-east-1 -AWS_BUCKET= -AWS_USE_PATH_STYLE_ENDPOINT=false - -VITE_APP_NAME="${APP_NAME}" diff --git a/.history/.env_20260521115345 b/.history/.env_20260521115345 deleted file mode 100644 index 8a4d3b4..0000000 --- a/.history/.env_20260521115345 +++ /dev/null @@ -1,66 +0,0 @@ -APP_NAME=Laravel -APP_ENV=local -APP_KEY=base64:iHPDeCnviINzk4hSncvHa8qFuz+iPW99xH+dHwxMhxQ= -APP_DEBUG=true -APP_TIMEZONE=UTC -APP_URL=http://localhost - -APP_LOCALE=en -APP_FALLBACK_LOCALE=en -APP_FAKER_LOCALE=en_US - -APP_MAINTENANCE_DRIVER=file -APP_MAINTENANCE_STORE=database - -BCRYPT_ROUNDS=12 - -LOG_CHANNEL=stack -LOG_STACK=single -LOG_DEPRECATIONS_CHANNEL=null -LOG_LEVEL=debug - -DB_CONNECTION=mysql -DB_HOST=127.0.0.1 -DB_PORT=3306 -DB_DATABASE=greenview -DB_USERNAME=root -DB_PASSWORD= - -FONNTE_TOKEN=CEAJquyLniASpRf76eT9 - -SESSION_DRIVER=file -SESSION_LIFETIME=120 -SESSION_ENCRYPT=false -SESSION_PATH=/ -SESSION_DOMAIN=null - -BROADCAST_CONNECTION=log -FILESYSTEM_DISK=local -QUEUE_CONNECTION=database - -CACHE_STORE=database -CACHE_PREFIX= - -MEMCACHED_HOST=127.0.0.1 - -REDIS_CLIENT=phpredis -REDIS_HOST=127.0.0.1 -REDIS_PASSWORD=null -REDIS_PORT=6379 - -MAIL_MAILER=smtp -MAIL_HOST=smtp.gmail.com -MAIL_PORT=587 -MAIL_USERNAME=reyfandi3008@gmail.com -MAIL_PASSWORD=vhwckujpwpjkhdky -MAIL_ENCRYPTION=tls -MAIL_FROM_ADDRESS=reyfandi3008@gmail.com -MAIL_FROM_NAME="Green View" - -AWS_ACCESS_KEY_ID= -AWS_SECRET_ACCESS_KEY= -AWS_DEFAULT_REGION=us-east-1 -AWS_BUCKET= -AWS_USE_PATH_STYLE_ENDPOINT=false - -VITE_APP_NAME="${APP_NAME}" diff --git a/.history/.env_20260521115424 b/.history/.env_20260521115424 deleted file mode 100644 index 7f2186d..0000000 --- a/.history/.env_20260521115424 +++ /dev/null @@ -1,66 +0,0 @@ -APP_NAME=Laravel -APP_ENV=local -APP_KEY=base64:iHPDeCnviINzk4hSncvHa8qFuz+iPW99xH+dHwxMhxQ= -APP_DEBUG=true -APP_TIMEZONE=UTC -APP_URL=http://localhost - -APP_LOCALE=en -APP_FALLBACK_LOCALE=en -APP_FAKER_LOCALE=en_US - -APP_MAINTENANCE_DRIVER=file -APP_MAINTENANCE_STORE=database - -BCRYPT_ROUNDS=12 - -LOG_CHANNEL=stack -LOG_STACK=single -LOG_DEPRECATIONS_CHANNEL=null -LOG_LEVEL=debug - -DB_CONNECTION=mysql -DB_HOST=127.0.0.1 -DB_PORT=3306 -DB_DATABASE=greenview -DB_USERNAME=root -DB_PASSWORD= - -FONNTE_TOKEN=CEAJquyLniASpRf76eT9 - -SESSION_DRIVER=file -SESSION_LIFETIME=120 -SESSION_ENCRYPT=false -SESSION_PATH=/ -SESSION_DOMAIN=null - -BROADCAST_CONNECTION=log -FILESYSTEM_DISK=local -QUEUE_CONNECTION=database - -CACHE_STORE=database -CACHE_PREFIX= - -MEMCACHED_HOST=127.0.0.1 - -REDIS_CLIENT=phpredis -REDIS_HOST=127.0.0.1 -REDIS_PASSWORD=null -REDIS_PORT=6379 - -MAIL_MAILER=smtp -MAIL_HOST=smtp.gmail.com -MAIL_PORT=587 -MAIL_USERNAME=reyfandi -MAIL_PASSWORD=vhwckujpwpjkhdky -MAIL_ENCRYPTION=tls -MAIL_FROM_ADDRESS=reyfandi3008@gmail.com -MAIL_FROM_NAME="Green View" - -AWS_ACCESS_KEY_ID= -AWS_SECRET_ACCESS_KEY= -AWS_DEFAULT_REGION=us-east-1 -AWS_BUCKET= -AWS_USE_PATH_STYLE_ENDPOINT=false - -VITE_APP_NAME="${APP_NAME}" diff --git a/.history/.env_20260521115432 b/.history/.env_20260521115432 deleted file mode 100644 index 8a4d3b4..0000000 --- a/.history/.env_20260521115432 +++ /dev/null @@ -1,66 +0,0 @@ -APP_NAME=Laravel -APP_ENV=local -APP_KEY=base64:iHPDeCnviINzk4hSncvHa8qFuz+iPW99xH+dHwxMhxQ= -APP_DEBUG=true -APP_TIMEZONE=UTC -APP_URL=http://localhost - -APP_LOCALE=en -APP_FALLBACK_LOCALE=en -APP_FAKER_LOCALE=en_US - -APP_MAINTENANCE_DRIVER=file -APP_MAINTENANCE_STORE=database - -BCRYPT_ROUNDS=12 - -LOG_CHANNEL=stack -LOG_STACK=single -LOG_DEPRECATIONS_CHANNEL=null -LOG_LEVEL=debug - -DB_CONNECTION=mysql -DB_HOST=127.0.0.1 -DB_PORT=3306 -DB_DATABASE=greenview -DB_USERNAME=root -DB_PASSWORD= - -FONNTE_TOKEN=CEAJquyLniASpRf76eT9 - -SESSION_DRIVER=file -SESSION_LIFETIME=120 -SESSION_ENCRYPT=false -SESSION_PATH=/ -SESSION_DOMAIN=null - -BROADCAST_CONNECTION=log -FILESYSTEM_DISK=local -QUEUE_CONNECTION=database - -CACHE_STORE=database -CACHE_PREFIX= - -MEMCACHED_HOST=127.0.0.1 - -REDIS_CLIENT=phpredis -REDIS_HOST=127.0.0.1 -REDIS_PASSWORD=null -REDIS_PORT=6379 - -MAIL_MAILER=smtp -MAIL_HOST=smtp.gmail.com -MAIL_PORT=587 -MAIL_USERNAME=reyfandi3008@gmail.com -MAIL_PASSWORD=vhwckujpwpjkhdky -MAIL_ENCRYPTION=tls -MAIL_FROM_ADDRESS=reyfandi3008@gmail.com -MAIL_FROM_NAME="Green View" - -AWS_ACCESS_KEY_ID= -AWS_SECRET_ACCESS_KEY= -AWS_DEFAULT_REGION=us-east-1 -AWS_BUCKET= -AWS_USE_PATH_STYLE_ENDPOINT=false - -VITE_APP_NAME="${APP_NAME}" diff --git a/.history/.env_20260521115440 b/.history/.env_20260521115440 deleted file mode 100644 index 64bbe18..0000000 --- a/.history/.env_20260521115440 +++ /dev/null @@ -1,66 +0,0 @@ -APP_NAME=Laravel -APP_ENV=local -APP_KEY=base64:iHPDeCnviINzk4hSncvHa8qFuz+iPW99xH+dHwxMhxQ= -APP_DEBUG=true -APP_TIMEZONE=UTC -APP_URL=http://localhost - -APP_LOCALE=en -APP_FALLBACK_LOCALE=en -APP_FAKER_LOCALE=en_US - -APP_MAINTENANCE_DRIVER=file -APP_MAINTENANCE_STORE=database - -BCRYPT_ROUNDS=12 - -LOG_CHANNEL=stack -LOG_STACK=single -LOG_DEPRECATIONS_CHANNEL=null -LOG_LEVEL=debug - -DB_CONNECTION=mysql -DB_HOST=127.0.0.1 -DB_PORT=3306 -DB_DATABASE=greenview -DB_USERNAME=root -DB_PASSWORD= - -FONNTE_TOKEN=CEAJquyLniASpRf76eT9 - -SESSION_DRIVER=file -SESSION_LIFETIME=120 -SESSION_ENCRYPT=false -SESSION_PATH=/ -SESSION_DOMAIN=null - -BROADCAST_CONNECTION=log -FILESYSTEM_DISK=local -QUEUE_CONNECTION=database - -CACHE_STORE=database -CACHE_PREFIX= - -MEMCACHED_HOST=127.0.0.1 - -REDIS_CLIENT=phpredis -REDIS_HOST=127.0.0.1 -REDIS_PASSWORD=null -REDIS_PORT=6379 - -MAIL_MAILER=smtp -MAIL_HOST=smtp.gmail.com -MAIL_PORT=587 -MAIL_USERNAME=reyfandi3008@gmail.com -MAIL_PASSWORD=vhwckujpwpjkhdky -MAIL_ENCRYPTION=tls -MAIL_FROM_ADDRESS=reyfandi -MAIL_FROM_NAME="Green View" - -AWS_ACCESS_KEY_ID= -AWS_SECRET_ACCESS_KEY= -AWS_DEFAULT_REGION=us-east-1 -AWS_BUCKET= -AWS_USE_PATH_STYLE_ENDPOINT=false - -VITE_APP_NAME="${APP_NAME}" diff --git a/.history/.env_20260521115442 b/.history/.env_20260521115442 deleted file mode 100644 index 48b9e37..0000000 --- a/.history/.env_20260521115442 +++ /dev/null @@ -1,66 +0,0 @@ -APP_NAME=Laravel -APP_ENV=local -APP_KEY=base64:iHPDeCnviINzk4hSncvHa8qFuz+iPW99xH+dHwxMhxQ= -APP_DEBUG=true -APP_TIMEZONE=UTC -APP_URL=http://localhost - -APP_LOCALE=en -APP_FALLBACK_LOCALE=en -APP_FAKER_LOCALE=en_US - -APP_MAINTENANCE_DRIVER=file -APP_MAINTENANCE_STORE=database - -BCRYPT_ROUNDS=12 - -LOG_CHANNEL=stack -LOG_STACK=single -LOG_DEPRECATIONS_CHANNEL=null -LOG_LEVEL=debug - -DB_CONNECTION=mysql -DB_HOST=127.0.0.1 -DB_PORT=3306 -DB_DATABASE=greenview -DB_USERNAME=root -DB_PASSWORD= - -FONNTE_TOKEN=CEAJquyLniASpRf76eT9 - -SESSION_DRIVER=file -SESSION_LIFETIME=120 -SESSION_ENCRYPT=false -SESSION_PATH=/ -SESSION_DOMAIN=null - -BROADCAST_CONNECTION=log -FILESYSTEM_DISK=local -QUEUE_CONNECTION=database - -CACHE_STORE=database -CACHE_PREFIX= - -MEMCACHED_HOST=127.0.0.1 - -REDIS_CLIENT=phpredis -REDIS_HOST=127.0.0.1 -REDIS_PASSWORD=null -REDIS_PORT=6379 - -MAIL_MAILER=smtp -MAIL_HOST=smtp.gmail.com -MAIL_PORT=587 -MAIL_USERNAME=reyfandi3008@gmail.com -MAIL_PASSWORD=vhwckujpwpjkhdky -MAIL_ENCRYPTION=tls -MAIL_FROM_ADDRESS=reyfandi3008 -MAIL_FROM_NAME="Green View" - -AWS_ACCESS_KEY_ID= -AWS_SECRET_ACCESS_KEY= -AWS_DEFAULT_REGION=us-east-1 -AWS_BUCKET= -AWS_USE_PATH_STYLE_ENDPOINT=false - -VITE_APP_NAME="${APP_NAME}" diff --git a/.history/.env_20260521115446 b/.history/.env_20260521115446 deleted file mode 100644 index 8a4d3b4..0000000 --- a/.history/.env_20260521115446 +++ /dev/null @@ -1,66 +0,0 @@ -APP_NAME=Laravel -APP_ENV=local -APP_KEY=base64:iHPDeCnviINzk4hSncvHa8qFuz+iPW99xH+dHwxMhxQ= -APP_DEBUG=true -APP_TIMEZONE=UTC -APP_URL=http://localhost - -APP_LOCALE=en -APP_FALLBACK_LOCALE=en -APP_FAKER_LOCALE=en_US - -APP_MAINTENANCE_DRIVER=file -APP_MAINTENANCE_STORE=database - -BCRYPT_ROUNDS=12 - -LOG_CHANNEL=stack -LOG_STACK=single -LOG_DEPRECATIONS_CHANNEL=null -LOG_LEVEL=debug - -DB_CONNECTION=mysql -DB_HOST=127.0.0.1 -DB_PORT=3306 -DB_DATABASE=greenview -DB_USERNAME=root -DB_PASSWORD= - -FONNTE_TOKEN=CEAJquyLniASpRf76eT9 - -SESSION_DRIVER=file -SESSION_LIFETIME=120 -SESSION_ENCRYPT=false -SESSION_PATH=/ -SESSION_DOMAIN=null - -BROADCAST_CONNECTION=log -FILESYSTEM_DISK=local -QUEUE_CONNECTION=database - -CACHE_STORE=database -CACHE_PREFIX= - -MEMCACHED_HOST=127.0.0.1 - -REDIS_CLIENT=phpredis -REDIS_HOST=127.0.0.1 -REDIS_PASSWORD=null -REDIS_PORT=6379 - -MAIL_MAILER=smtp -MAIL_HOST=smtp.gmail.com -MAIL_PORT=587 -MAIL_USERNAME=reyfandi3008@gmail.com -MAIL_PASSWORD=vhwckujpwpjkhdky -MAIL_ENCRYPTION=tls -MAIL_FROM_ADDRESS=reyfandi3008@gmail.com -MAIL_FROM_NAME="Green View" - -AWS_ACCESS_KEY_ID= -AWS_SECRET_ACCESS_KEY= -AWS_DEFAULT_REGION=us-east-1 -AWS_BUCKET= -AWS_USE_PATH_STYLE_ENDPOINT=false - -VITE_APP_NAME="${APP_NAME}" diff --git a/.history/.env_20260521165900 b/.history/.env_20260521165900 deleted file mode 100644 index ef45741..0000000 --- a/.history/.env_20260521165900 +++ /dev/null @@ -1,66 +0,0 @@ -APP_NAME=Laravel -APP_ENV=local -APP_KEY=base64:iHPDeCnviINzk4hSncvHa8qFuz+iPW99xH+dHwxMhxQ= -APP_DEBUG=true -APP_TIMEZONE=UTC -APP_URL=http://localhost - -APP_LOCALE=en -APP_FALLBACK_LOCALE=en -APP_FAKER_LOCALE=en_US - -APP_MAINTENANCE_DRIVER=file -APP_MAINTENANCE_STORE=database - -BCRYPT_ROUNDS=12 - -LOG_CHANNEL=stack -LOG_STACK=single -LOG_DEPRECATIONS_CHANNEL=null -LOG_LEVEL=debug - -DB_CONNECTION=mysql -DB_HOST=127.0.0.1 -DB_PORT=3306 -DB_DATABASE=greenview -DB_USERNAME=root -DB_PASSWORD= - -FONNTE_TOKEN=CEAJquyLniASpRf76eT9 - -SESSION_DRIVER=file -SESSION_LIFETIME=120 -SESSION_ENCRYPT=false -SESSION_PATH=/ -SESSION_DOMAIN=null - -BROADCAST_CONNECTION=log -FILESYSTEM_DISK=local -QUEUE_CONNECTION=database - -CACHE_STORE=database -CACHE_PREFIX= - -MEMCACHED_HOST=127.0.0.1 - -REDIS_CLIENT=phpredis -REDIS_HOST=127.0.0.1 -REDIS_PASSWORD=null -REDIS_PORT=6379 - -MAIL_MAILER=smtp -MAIL_HOST=smtp.gmail.com -MAIL_PORT=587 -MAIL_USERNAME=reyfandi3008@gmail.com -MAIL_PASSWORD=hhre xxfh fcyj xlck -MAIL_ENCRYPTION=tls -MAIL_FROM_ADDRESS=reyfandi3008@gmail.com -MAIL_FROM_NAME="Green View" - -AWS_ACCESS_KEY_ID= -AWS_SECRET_ACCESS_KEY= -AWS_DEFAULT_REGION=us-east-1 -AWS_BUCKET= -AWS_USE_PATH_STYLE_ENDPOINT=false - -VITE_APP_NAME="${APP_NAME}" diff --git a/.history/.env_20260521165902 b/.history/.env_20260521165902 deleted file mode 100644 index 0a747a9..0000000 --- a/.history/.env_20260521165902 +++ /dev/null @@ -1,66 +0,0 @@ -APP_NAME=Laravel -APP_ENV=local -APP_KEY=base64:iHPDeCnviINzk4hSncvHa8qFuz+iPW99xH+dHwxMhxQ= -APP_DEBUG=true -APP_TIMEZONE=UTC -APP_URL=http://localhost - -APP_LOCALE=en -APP_FALLBACK_LOCALE=en -APP_FAKER_LOCALE=en_US - -APP_MAINTENANCE_DRIVER=file -APP_MAINTENANCE_STORE=database - -BCRYPT_ROUNDS=12 - -LOG_CHANNEL=stack -LOG_STACK=single -LOG_DEPRECATIONS_CHANNEL=null -LOG_LEVEL=debug - -DB_CONNECTION=mysql -DB_HOST=127.0.0.1 -DB_PORT=3306 -DB_DATABASE=greenview -DB_USERNAME=root -DB_PASSWORD= - -FONNTE_TOKEN=CEAJquyLniASpRf76eT9 - -SESSION_DRIVER=file -SESSION_LIFETIME=120 -SESSION_ENCRYPT=false -SESSION_PATH=/ -SESSION_DOMAIN=null - -BROADCAST_CONNECTION=log -FILESYSTEM_DISK=local -QUEUE_CONNECTION=database - -CACHE_STORE=database -CACHE_PREFIX= - -MEMCACHED_HOST=127.0.0.1 - -REDIS_CLIENT=phpredis -REDIS_HOST=127.0.0.1 -REDIS_PASSWORD=null -REDIS_PORT=6379 - -MAIL_MAILER=smtp -MAIL_HOST=smtp.gmail.com -MAIL_PORT=587 -MAIL_USERNAME=reyfandi3008@gmail.com -MAIL_PASSWORD=hhre xxfh fcyjxlck -MAIL_ENCRYPTION=tls -MAIL_FROM_ADDRESS=reyfandi3008@gmail.com -MAIL_FROM_NAME="Green View" - -AWS_ACCESS_KEY_ID= -AWS_SECRET_ACCESS_KEY= -AWS_DEFAULT_REGION=us-east-1 -AWS_BUCKET= -AWS_USE_PATH_STYLE_ENDPOINT=false - -VITE_APP_NAME="${APP_NAME}" diff --git a/.history/.env_20260521165904 b/.history/.env_20260521165904 deleted file mode 100644 index cd21b25..0000000 --- a/.history/.env_20260521165904 +++ /dev/null @@ -1,66 +0,0 @@ -APP_NAME=Laravel -APP_ENV=local -APP_KEY=base64:iHPDeCnviINzk4hSncvHa8qFuz+iPW99xH+dHwxMhxQ= -APP_DEBUG=true -APP_TIMEZONE=UTC -APP_URL=http://localhost - -APP_LOCALE=en -APP_FALLBACK_LOCALE=en -APP_FAKER_LOCALE=en_US - -APP_MAINTENANCE_DRIVER=file -APP_MAINTENANCE_STORE=database - -BCRYPT_ROUNDS=12 - -LOG_CHANNEL=stack -LOG_STACK=single -LOG_DEPRECATIONS_CHANNEL=null -LOG_LEVEL=debug - -DB_CONNECTION=mysql -DB_HOST=127.0.0.1 -DB_PORT=3306 -DB_DATABASE=greenview -DB_USERNAME=root -DB_PASSWORD= - -FONNTE_TOKEN=CEAJquyLniASpRf76eT9 - -SESSION_DRIVER=file -SESSION_LIFETIME=120 -SESSION_ENCRYPT=false -SESSION_PATH=/ -SESSION_DOMAIN=null - -BROADCAST_CONNECTION=log -FILESYSTEM_DISK=local -QUEUE_CONNECTION=database - -CACHE_STORE=database -CACHE_PREFIX= - -MEMCACHED_HOST=127.0.0.1 - -REDIS_CLIENT=phpredis -REDIS_HOST=127.0.0.1 -REDIS_PASSWORD=null -REDIS_PORT=6379 - -MAIL_MAILER=smtp -MAIL_HOST=smtp.gmail.com -MAIL_PORT=587 -MAIL_USERNAME=reyfandi3008@gmail.com -MAIL_PASSWORD=hhre xxfhfcyjxlck -MAIL_ENCRYPTION=tls -MAIL_FROM_ADDRESS=reyfandi3008@gmail.com -MAIL_FROM_NAME="Green View" - -AWS_ACCESS_KEY_ID= -AWS_SECRET_ACCESS_KEY= -AWS_DEFAULT_REGION=us-east-1 -AWS_BUCKET= -AWS_USE_PATH_STYLE_ENDPOINT=false - -VITE_APP_NAME="${APP_NAME}" diff --git a/.history/.env_20260521165916 b/.history/.env_20260521165916 deleted file mode 100644 index 3e128d7..0000000 --- a/.history/.env_20260521165916 +++ /dev/null @@ -1,66 +0,0 @@ -APP_NAME=Laravel -APP_ENV=local -APP_KEY=base64:iHPDeCnviINzk4hSncvHa8qFuz+iPW99xH+dHwxMhxQ= -APP_DEBUG=true -APP_TIMEZONE=UTC -APP_URL=http://localhost - -APP_LOCALE=en -APP_FALLBACK_LOCALE=en -APP_FAKER_LOCALE=en_US - -APP_MAINTENANCE_DRIVER=file -APP_MAINTENANCE_STORE=database - -BCRYPT_ROUNDS=12 - -LOG_CHANNEL=stack -LOG_STACK=single -LOG_DEPRECATIONS_CHANNEL=null -LOG_LEVEL=debug - -DB_CONNECTION=mysql -DB_HOST=127.0.0.1 -DB_PORT=3306 -DB_DATABASE=greenview -DB_USERNAME=root -DB_PASSWORD= - -FONNTE_TOKEN=CEAJquyLniASpRf76eT9 - -SESSION_DRIVER=file -SESSION_LIFETIME=120 -SESSION_ENCRYPT=false -SESSION_PATH=/ -SESSION_DOMAIN=null - -BROADCAST_CONNECTION=log -FILESYSTEM_DISK=local -QUEUE_CONNECTION=database - -CACHE_STORE=database -CACHE_PREFIX= - -MEMCACHED_HOST=127.0.0.1 - -REDIS_CLIENT=phpredis -REDIS_HOST=127.0.0.1 -REDIS_PASSWORD=null -REDIS_PORT=6379 - -MAIL_MAILER=smtp -MAIL_HOST=smtp.gmail.com -MAIL_PORT=587 -MAIL_USERNAME=rtgreenview@gmail.com@gmail.com -MAIL_PASSWORD=hhre xxfhfcyjxlck -MAIL_ENCRYPTION=tls -MAIL_FROM_ADDRESS=reyfandi3008@gmail.com -MAIL_FROM_NAME="Green View" - -AWS_ACCESS_KEY_ID= -AWS_SECRET_ACCESS_KEY= -AWS_DEFAULT_REGION=us-east-1 -AWS_BUCKET= -AWS_USE_PATH_STYLE_ENDPOINT=false - -VITE_APP_NAME="${APP_NAME}" diff --git a/.history/.env_20260521165925 b/.history/.env_20260521165925 deleted file mode 100644 index 66dda0f..0000000 --- a/.history/.env_20260521165925 +++ /dev/null @@ -1,66 +0,0 @@ -APP_NAME=Laravel -APP_ENV=local -APP_KEY=base64:iHPDeCnviINzk4hSncvHa8qFuz+iPW99xH+dHwxMhxQ= -APP_DEBUG=true -APP_TIMEZONE=UTC -APP_URL=http://localhost - -APP_LOCALE=en -APP_FALLBACK_LOCALE=en -APP_FAKER_LOCALE=en_US - -APP_MAINTENANCE_DRIVER=file -APP_MAINTENANCE_STORE=database - -BCRYPT_ROUNDS=12 - -LOG_CHANNEL=stack -LOG_STACK=single -LOG_DEPRECATIONS_CHANNEL=null -LOG_LEVEL=debug - -DB_CONNECTION=mysql -DB_HOST=127.0.0.1 -DB_PORT=3306 -DB_DATABASE=greenview -DB_USERNAME=root -DB_PASSWORD= - -FONNTE_TOKEN=CEAJquyLniASpRf76eT9 - -SESSION_DRIVER=file -SESSION_LIFETIME=120 -SESSION_ENCRYPT=false -SESSION_PATH=/ -SESSION_DOMAIN=null - -BROADCAST_CONNECTION=log -FILESYSTEM_DISK=local -QUEUE_CONNECTION=database - -CACHE_STORE=database -CACHE_PREFIX= - -MEMCACHED_HOST=127.0.0.1 - -REDIS_CLIENT=phpredis -REDIS_HOST=127.0.0.1 -REDIS_PASSWORD=null -REDIS_PORT=6379 - -MAIL_MAILER=smtp -MAIL_HOST=smtp.gmail.com -MAIL_PORT=587 -MAIL_USERNAME=rtgreenview@gmail.com@gmail.com -MAIL_PASSWORD=hhre xxfhfcyjxlck -MAIL_ENCRYPTION=tls -MAIL_FROM_ADDRESS=rtgreenview@gmail.com -MAIL_FROM_NAME="Green View" - -AWS_ACCESS_KEY_ID= -AWS_SECRET_ACCESS_KEY= -AWS_DEFAULT_REGION=us-east-1 -AWS_BUCKET= -AWS_USE_PATH_STYLE_ENDPOINT=false - -VITE_APP_NAME="${APP_NAME}" diff --git a/.history/.env_20260521165951 b/.history/.env_20260521165951 deleted file mode 100644 index dc41f05..0000000 --- a/.history/.env_20260521165951 +++ /dev/null @@ -1,66 +0,0 @@ -APP_NAME=Laravel -APP_ENV=local -APP_KEY=base64:iHPDeCnviINzk4hSncvHa8qFuz+iPW99xH+dHwxMhxQ= -APP_DEBUG=true -APP_TIMEZONE=UTC -APP_URL=http://localhost - -APP_LOCALE=en -APP_FALLBACK_LOCALE=en -APP_FAKER_LOCALE=en_US - -APP_MAINTENANCE_DRIVER=file -APP_MAINTENANCE_STORE=database - -BCRYPT_ROUNDS=12 - -LOG_CHANNEL=stack -LOG_STACK=single -LOG_DEPRECATIONS_CHANNEL=null -LOG_LEVEL=debug - -DB_CONNECTION=mysql -DB_HOST=127.0.0.1 -DB_PORT=3306 -DB_DATABASE=greenview -DB_USERNAME=root -DB_PASSWORD= - -FONNTE_TOKEN=CEAJquyLniASpRf76eT9 - -SESSION_DRIVER=file -SESSION_LIFETIME=120 -SESSION_ENCRYPT=false -SESSION_PATH=/ -SESSION_DOMAIN=null - -BROADCAST_CONNECTION=log -FILESYSTEM_DISK=local -QUEUE_CONNECTION=database - -CACHE_STORE=database -CACHE_PREFIX= - -MEMCACHED_HOST=127.0.0.1 - -REDIS_CLIENT=phpredis -REDIS_HOST=127.0.0.1 -REDIS_PASSWORD=null -REDIS_PORT=6379 - -MAIL_MAILER=smtp -MAIL_HOST=smtp.gmail.com -MAIL_PORT=587 -MAIL_USERNAME=rtgreenview@gmail.com@gmail.com -MAIL_PASSWORD=hhrexxfhfcyjxlck -MAIL_ENCRYPTION=tls -MAIL_FROM_ADDRESS=rtgreenview@gmail.com -MAIL_FROM_NAME="Green View" - -AWS_ACCESS_KEY_ID= -AWS_SECRET_ACCESS_KEY= -AWS_DEFAULT_REGION=us-east-1 -AWS_BUCKET= -AWS_USE_PATH_STYLE_ENDPOINT=false - -VITE_APP_NAME="${APP_NAME}" diff --git a/.history/.env_20260521170051 b/.history/.env_20260521170051 deleted file mode 100644 index 159ad79..0000000 --- a/.history/.env_20260521170051 +++ /dev/null @@ -1,66 +0,0 @@ -APP_NAME=Laravel -APP_ENV=local -APP_KEY=base64:iHPDeCnviINzk4hSncvHa8qFuz+iPW99xH+dHwxMhxQ= -APP_DEBUG=true -APP_TIMEZONE=UTC -APP_URL=http://localhost - -APP_LOCALE=en -APP_FALLBACK_LOCALE=en -APP_FAKER_LOCALE=en_US - -APP_MAINTENANCE_DRIVER=file -APP_MAINTENANCE_STORE=database - -BCRYPT_ROUNDS=12 - -LOG_CHANNEL=stack -LOG_STACK=single -LOG_DEPRECATIONS_CHANNEL=null -LOG_LEVEL=debug - -DB_CONNECTION=mysql -DB_HOST=127.0.0.1 -DB_PORT=3306 -DB_DATABASE=greenview -DB_USERNAME=root -DB_PASSWORD= - -FONNTE_TOKEN=CEAJquyLniASpRf76eT9 - -SESSION_DRIVER=file -SESSION_LIFETIME=120 -SESSION_ENCRYPT=false -SESSION_PATH=/ -SESSION_DOMAIN=null - -BROADCAST_CONNECTION=log -FILESYSTEM_DISK=local -QUEUE_CONNECTION=database - -CACHE_STORE=database -CACHE_PREFIX= - -MEMCACHED_HOST=127.0.0.1 - -REDIS_CLIENT=phpredis -REDIS_HOST=127.0.0.1 -REDIS_PASSWORD=null -REDIS_PORT=6379 - -MAIL_MAILER=smtp -MAIL_HOST=smtp.gmail.com -MAIL_PORT=587 -MAIL_USERNAME=rtgreenview@gmail.com@gmail.com -MAIL_PASSWORD=hhrexxfhfcyjxlck -MAIL_ENCRYPTION=tls -MAIL_FROM_ADDRESS=rtgreenview@gmail.com -MAIL_FROM_NAME="Green View" - -AWS_ACCESS_KEY_ID= -AWS_SECRET_ACCESS_KEY= -AWS_DEFAULT_REGION=us-east-1 -AWS_BUCKET= -AWS_USE_PATH_STYLE_ENDPOINT=false - -VITE_APP_NAME="${APP_NAME}" diff --git a/.history/.env_20260521170054 b/.history/.env_20260521170054 deleted file mode 100644 index 7293b68..0000000 --- a/.history/.env_20260521170054 +++ /dev/null @@ -1,66 +0,0 @@ -APP_NAME=Laravel -APP_ENV=local -APP_KEY=base64:iHPDeCnviINzk4hSncvHa8qFuz+iPW99xH+dHwxMhxQ= -APP_DEBUG=true -APP_TIMEZONE=UTC -APP_URL=http://localhost - -APP_LOCALE=en -APP_FALLBACK_LOCALE=en -APP_FAKER_LOCALE=en_US - -APP_MAINTENANCE_DRIVER=file -APP_MAINTENANCE_STORE=database - -BCRYPT_ROUNDS=12 - -LOG_CHANNEL=stack -LOG_STACK=single -LOG_DEPRECATIONS_CHANNEL=null -LOG_LEVEL=debug - -DB_CONNECTION=mysql -DB_HOST=127.0.0.1 -DB_PORT=3306 -DB_DATABASE=greenview -DB_USERNAME=root -DB_PASSWORD= - -FONNTE_TOKEN=CEAJquyLniASpRf76eT9 - -SESSION_DRIVER=file -SESSION_LIFETIME=120 -SESSION_ENCRYPT=false -SESSION_PATH=/ -SESSION_DOMAIN=null - -BROADCAST_CONNECTION=log -FILESYSTEM_DISK=local -QUEUE_CONNECTION=database - -CACHE_STORE=database -CACHE_PREFIX= - -MEMCACHED_HOST=127.0.0.1 - -REDIS_CLIENT=phpredis -REDIS_HOST=127.0.0.1 -REDIS_PASSWORD=null -REDIS_PORT=6379 - -MAIL_MAILER=smtp -MAIL_HOST=smtp.gmail.com -MAIL_PORT=587 -MAIL_USERNAME=rtgreenview@gmail.com@gmail.com -MAIL_PASSWORD=hhrexxfhfcyjxlck -MAIL_ENCRYPTION=tls -MAIL_FROM_ADDRESS=rtgreenview@gmail.com -MAIL_FROM_NAME="Green View" - -AWS_ACCESS_KEY_ID= -AWS_SECRET_ACCESS_KEY= -AWS_DEFAULT_REGION=us-east-1 -AWS_BUCKET= -AWS_USE_PATH_STYLE_ENDPOINT=false - -VITE_APP_NAME="${APP_NAME}" diff --git a/.history/.env_20260521170058 b/.history/.env_20260521170058 deleted file mode 100644 index c54f787..0000000 --- a/.history/.env_20260521170058 +++ /dev/null @@ -1,66 +0,0 @@ -APP_NAME=Laravel -APP_ENV=local -APP_KEY=base64:iHPDeCnviINzk4hSncvHa8qFuz+iPW99xH+dHwxMhxQ= -APP_DEBUG=true -APP_TIMEZONE=UTC -APP_URL=http://localhost - -APP_LOCALE=en -APP_FALLBACK_LOCALE=en -APP_FAKER_LOCALE=en_US - -APP_MAINTENANCE_DRIVER=file -APP_MAINTENANCE_STORE=database - -BCRYPT_ROUNDS=12 - -LOG_CHANNEL=stack -LOG_STACK=single -LOG_DEPRECATIONS_CHANNEL=null -LOG_LEVEL=debug - -DB_CONNECTION=mysql -DB_HOST=127.0.0.1 -DB_PORT=3306 -DB_DATABASE=greenview -DB_USERNAME=root -DB_PASSWORD= - -FONNTE_TOKEN=CEAJquyLniASpRf76eT9 - -SESSION_DRIVER=file -SESSION_LIFETIME=120 -SESSION_ENCRYPT=false -SESSION_PATH=/ -SESSION_DOMAIN=null - -BROADCAST_CONNECTION=log -FILESYSTEM_DISK=local -QUEUE_CONNECTION=database - -CACHE_STORE=database -CACHE_PREFIX= - -MEMCACHED_HOST=127.0.0.1 - -REDIS_CLIENT=phpredis -REDIS_HOST=127.0.0.1 -REDIS_PASSWORD=null -REDIS_PORT=6379 - -MAIL_MAILER=smtp -MAIL_HOST=smtp.gmail.com -MAIL_PORT=587 -MAIL_USERNAME=rtgreenview@gmail.com -MAIL_PASSWORD=hhrexxfhfcyjxlck -MAIL_ENCRYPTION=tls -MAIL_FROM_ADDRESS=rtgreenview@gmail.com -MAIL_FROM_NAME="Green View" - -AWS_ACCESS_KEY_ID= -AWS_SECRET_ACCESS_KEY= -AWS_DEFAULT_REGION=us-east-1 -AWS_BUCKET= -AWS_USE_PATH_STYLE_ENDPOINT=false - -VITE_APP_NAME="${APP_NAME}" diff --git a/.history/.env_20260520115245 b/.history/.env_20260625025301 similarity index 91% rename from .history/.env_20260520115245 rename to .history/.env_20260625025301 index 2562e55..5a263f8 100644 --- a/.history/.env_20260520115245 +++ b/.history/.env_20260625025301 @@ -19,6 +19,8 @@ LOG_STACK=single LOG_DEPRECATIONS_CHANNEL=null LOG_LEVEL=debug +FONNTE_TOKEN=CEAJquyLniASpRf76eT9 + DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 @@ -26,8 +28,6 @@ DB_DATABASE=greenview DB_USERNAME=root DB_PASSWORD= -FONNTE_TOKEN=CEAJquyLniASpRf76eT9 - SESSION_DRIVER=file SESSION_LIFETIME=120 SESSION_ENCRYPT=false @@ -51,10 +51,10 @@ REDIS_PORT=6379 MAIL_MAILER=smtp MAIL_HOST=smtp.gmail.com MAIL_PORT=587 -MAIL_USERNAME=mlnryan05@gmail.com -MAIL_PASSWORD=aqjmnueuxlgtfpej +MAIL_USERNAME=nexvara78@gmail.com +MAIL_PASSWORD=cmog towk lkmp qepk MAIL_ENCRYPTION=tls -MAIL_FROM_ADDRESS=mlnryan05@gmail.com +MAIL_FROM_ADDRESS=nexvara78@gmail.com MAIL_FROM_NAME="Green View" AWS_ACCESS_KEY_ID= diff --git a/.history/.env_20260520115241 b/.history/.env_20260625025304 similarity index 91% rename from .history/.env_20260520115241 rename to .history/.env_20260625025304 index b0ad04b..8b47a68 100644 --- a/.history/.env_20260520115241 +++ b/.history/.env_20260625025304 @@ -19,6 +19,8 @@ LOG_STACK=single LOG_DEPRECATIONS_CHANNEL=null LOG_LEVEL=debug +FONNTE_TOKEN=CEAJquyLniASpRf76eT9 + DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 @@ -26,8 +28,6 @@ DB_DATABASE=greenview DB_USERNAME=root DB_PASSWORD= -FONNTE_TOKEN=CEAJquyLniASpRf76eT9 - SESSION_DRIVER=file SESSION_LIFETIME=120 SESSION_ENCRYPT=false @@ -51,10 +51,10 @@ REDIS_PORT=6379 MAIL_MAILER=smtp MAIL_HOST=smtp.gmail.com MAIL_PORT=587 -MAIL_USERNAME=mlnryan05@gmail.com -MAIL_PASSWORD=aqjm nueu xlgtfpej +MAIL_USERNAME=nexvara78@gmail.com +MAIL_PASSWORD=cmog towk lkmpqepk MAIL_ENCRYPTION=tls -MAIL_FROM_ADDRESS=mlnryan05@gmail.com +MAIL_FROM_ADDRESS=nexvara78@gmail.com MAIL_FROM_NAME="Green View" AWS_ACCESS_KEY_ID= diff --git a/.history/.env_20260520115243 b/.history/.env_20260625025306 similarity index 91% rename from .history/.env_20260520115243 rename to .history/.env_20260625025306 index e29959b..01eb9df 100644 --- a/.history/.env_20260520115243 +++ b/.history/.env_20260625025306 @@ -19,6 +19,8 @@ LOG_STACK=single LOG_DEPRECATIONS_CHANNEL=null LOG_LEVEL=debug +FONNTE_TOKEN=CEAJquyLniASpRf76eT9 + DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 @@ -26,8 +28,6 @@ DB_DATABASE=greenview DB_USERNAME=root DB_PASSWORD= -FONNTE_TOKEN=CEAJquyLniASpRf76eT9 - SESSION_DRIVER=file SESSION_LIFETIME=120 SESSION_ENCRYPT=false @@ -51,10 +51,10 @@ REDIS_PORT=6379 MAIL_MAILER=smtp MAIL_HOST=smtp.gmail.com MAIL_PORT=587 -MAIL_USERNAME=mlnryan05@gmail.com -MAIL_PASSWORD=aqjm nueuxlgtfpej +MAIL_USERNAME=nexvara78@gmail.com +MAIL_PASSWORD=cmog towklkmpqepk MAIL_ENCRYPTION=tls -MAIL_FROM_ADDRESS=mlnryan05@gmail.com +MAIL_FROM_ADDRESS=nexvara78@gmail.com MAIL_FROM_NAME="Green View" AWS_ACCESS_KEY_ID= diff --git a/.history/.env_20260520115251 b/.history/.env_20260625025308 similarity index 91% rename from .history/.env_20260520115251 rename to .history/.env_20260625025308 index 2562e55..2e8b5f7 100644 --- a/.history/.env_20260520115251 +++ b/.history/.env_20260625025308 @@ -19,6 +19,8 @@ LOG_STACK=single LOG_DEPRECATIONS_CHANNEL=null LOG_LEVEL=debug +FONNTE_TOKEN=CEAJquyLniASpRf76eT9 + DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 @@ -26,8 +28,6 @@ DB_DATABASE=greenview DB_USERNAME=root DB_PASSWORD= -FONNTE_TOKEN=CEAJquyLniASpRf76eT9 - SESSION_DRIVER=file SESSION_LIFETIME=120 SESSION_ENCRYPT=false @@ -51,10 +51,10 @@ REDIS_PORT=6379 MAIL_MAILER=smtp MAIL_HOST=smtp.gmail.com MAIL_PORT=587 -MAIL_USERNAME=mlnryan05@gmail.com -MAIL_PASSWORD=aqjmnueuxlgtfpej +MAIL_USERNAME=nexvara78@gmail.com +MAIL_PASSWORD=cmogtowklkmpqepk MAIL_ENCRYPTION=tls -MAIL_FROM_ADDRESS=mlnryan05@gmail.com +MAIL_FROM_ADDRESS=nexvara78@gmail.com MAIL_FROM_NAME="Green View" AWS_ACCESS_KEY_ID= diff --git a/.history/.env_20260521115329 b/.history/.env_20260625025310 similarity index 92% rename from .history/.env_20260521115329 rename to .history/.env_20260625025310 index 046826c..48fc8aa 100644 --- a/.history/.env_20260521115329 +++ b/.history/.env_20260625025310 @@ -19,6 +19,8 @@ LOG_STACK=single LOG_DEPRECATIONS_CHANNEL=null LOG_LEVEL=debug +FONNTE_TOKEN=CEAJquyLniASpRf76eT9 + DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 @@ -26,8 +28,6 @@ DB_DATABASE=greenview DB_USERNAME=root DB_PASSWORD= -FONNTE_TOKEN=CEAJquyLniASpRf76eT9 - SESSION_DRIVER=file SESSION_LIFETIME=120 SESSION_ENCRYPT=false @@ -51,10 +51,10 @@ REDIS_PORT=6379 MAIL_MAILER=smtp MAIL_HOST=smtp.gmail.com MAIL_PORT=587 -MAIL_USERNAME=reyfandi3008@gmail.com -MAIL_PASSWORD= +MAIL_USERNAME=nexvara78 +MAIL_PASSWORD=cmogtowklkmpqepk MAIL_ENCRYPTION=tls -MAIL_FROM_ADDRESS=reyfandi3008@gmail.com +MAIL_FROM_ADDRESS=nexvara78@gmail.com MAIL_FROM_NAME="Green View" AWS_ACCESS_KEY_ID= diff --git a/.history/.env_20260520115422 b/.history/.env_20260625025319 similarity index 94% rename from .history/.env_20260520115422 rename to .history/.env_20260625025319 index 1ce56c4..fd4f588 100644 --- a/.history/.env_20260520115422 +++ b/.history/.env_20260625025319 @@ -19,6 +19,8 @@ LOG_STACK=single LOG_DEPRECATIONS_CHANNEL=null LOG_LEVEL=debug +FONNTE_TOKEN=CEAJquyLniASpRf76eT9 + DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 @@ -26,8 +28,6 @@ DB_DATABASE=greenview DB_USERNAME=root DB_PASSWORD= -FONNTE_TOKEN=CEAJquyLniASpRf76eT9 - SESSION_DRIVER=file SESSION_LIFETIME=120 SESSION_ENCRYPT=false @@ -52,9 +52,9 @@ MAIL_MAILER=smtp MAIL_HOST=smtp.gmail.com MAIL_PORT=587 MAIL_USERNAME=nunieiffel@gmail.com -MAIL_PASSWORD=aqjmnueuxlgtfpej +MAIL_PASSWORD=cmogtowklkmpqepk MAIL_ENCRYPTION=tls -MAIL_FROM_ADDRESS=mlnryan05@gmail.com +MAIL_FROM_ADDRESS=nexvara78@gmail.com MAIL_FROM_NAME="Green View" AWS_ACCESS_KEY_ID= diff --git a/.history/.env_20260625025325 b/.history/.env_20260625025325 new file mode 100644 index 0000000..a5c9032 --- /dev/null +++ b/.history/.env_20260625025325 @@ -0,0 +1,66 @@ +APP_NAME=Laravel +APP_ENV=local +APP_KEY=base64:iHPDeCnviINzk4hSncvHa8qFuz+iPW99xH+dHwxMhxQ= +APP_DEBUG=true +APP_TIMEZONE=UTC +APP_URL=http://localhost + +APP_LOCALE=en +APP_FALLBACK_LOCALE=en +APP_FAKER_LOCALE=en_US + +APP_MAINTENANCE_DRIVER=file +APP_MAINTENANCE_STORE=database + +BCRYPT_ROUNDS=12 + +LOG_CHANNEL=stack +LOG_STACK=single +LOG_DEPRECATIONS_CHANNEL=null +LOG_LEVEL=debug + +FONNTE_TOKEN=CEAJquyLniASpRf76eT9 + +DB_CONNECTION=mysql +DB_HOST=127.0.0.1 +DB_PORT=3306 +DB_DATABASE=greenview +DB_USERNAME=root +DB_PASSWORD= + +SESSION_DRIVER=file +SESSION_LIFETIME=120 +SESSION_ENCRYPT=false +SESSION_PATH=/ +SESSION_DOMAIN=null + +BROADCAST_CONNECTION=log +FILESYSTEM_DISK=local +QUEUE_CONNECTION=database + +CACHE_STORE=database +CACHE_PREFIX= + +MEMCACHED_HOST=127.0.0.1 + +REDIS_CLIENT=phpredis +REDIS_HOST=127.0.0.1 +REDIS_PASSWORD=null +REDIS_PORT=6379 + +MAIL_MAILER=smtp +MAIL_HOST=smtp.gmail.com +MAIL_PORT=587 +MAIL_USERNAME=nunieiffel@gmail.com +MAIL_PASSWORD=cmogtowklkmpqepk +MAIL_ENCRYPTION=tls +MAIL_FROM_ADDRESS=nunieiffel +MAIL_FROM_NAME="Green View" + +AWS_ACCESS_KEY_ID= +AWS_SECRET_ACCESS_KEY= +AWS_DEFAULT_REGION=us-east-1 +AWS_BUCKET= +AWS_USE_PATH_STYLE_ENDPOINT=false + +VITE_APP_NAME="${APP_NAME}" diff --git a/.history/.env_20260521115117 b/.history/.env_20260625025330 similarity index 97% rename from .history/.env_20260521115117 rename to .history/.env_20260625025330 index 6668c38..97bb179 100644 --- a/.history/.env_20260521115117 +++ b/.history/.env_20260625025330 @@ -19,6 +19,8 @@ LOG_STACK=single LOG_DEPRECATIONS_CHANNEL=null LOG_LEVEL=debug +FONNTE_TOKEN=CEAJquyLniASpRf76eT9 + DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 @@ -26,8 +28,6 @@ DB_DATABASE=greenview DB_USERNAME=root DB_PASSWORD= -FONNTE_TOKEN=CEAJquyLniASpRf76eT9 - SESSION_DRIVER=file SESSION_LIFETIME=120 SESSION_ENCRYPT=false @@ -52,7 +52,7 @@ MAIL_MAILER=smtp MAIL_HOST=smtp.gmail.com MAIL_PORT=587 MAIL_USERNAME=nunieiffel@gmail.com -MAIL_PASSWORD=aqjmnueuxlgtfpej +MAIL_PASSWORD=cmogtowklkmpqepk MAIL_ENCRYPTION=tls MAIL_FROM_ADDRESS=nunieiffel@gmail.com MAIL_FROM_NAME="Green View" diff --git a/.history/.env_20260520115432 b/.history/.env_20260625030808 similarity index 94% rename from .history/.env_20260520115432 rename to .history/.env_20260625030808 index 6668c38..2d2151a 100644 --- a/.history/.env_20260520115432 +++ b/.history/.env_20260625030808 @@ -19,6 +19,8 @@ LOG_STACK=single LOG_DEPRECATIONS_CHANNEL=null LOG_LEVEL=debug +FONNTE_TOKEN= + DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 @@ -26,8 +28,6 @@ DB_DATABASE=greenview DB_USERNAME=root DB_PASSWORD= -FONNTE_TOKEN=CEAJquyLniASpRf76eT9 - SESSION_DRIVER=file SESSION_LIFETIME=120 SESSION_ENCRYPT=false @@ -52,7 +52,7 @@ MAIL_MAILER=smtp MAIL_HOST=smtp.gmail.com MAIL_PORT=587 MAIL_USERNAME=nunieiffel@gmail.com -MAIL_PASSWORD=aqjmnueuxlgtfpej +MAIL_PASSWORD=cmogtowklkmpqepk MAIL_ENCRYPTION=tls MAIL_FROM_ADDRESS=nunieiffel@gmail.com MAIL_FROM_NAME="Green View" diff --git a/.history/.env_20260521114417 b/.history/.env_20260625030809 similarity index 94% rename from .history/.env_20260521114417 rename to .history/.env_20260625030809 index 2ad6c09..420d29e 100644 --- a/.history/.env_20260521114417 +++ b/.history/.env_20260625030809 @@ -19,6 +19,8 @@ LOG_STACK=single LOG_DEPRECATIONS_CHANNEL=null LOG_LEVEL=debug +FONNTE_TOKEN=chpBEnbbsP7BEZQnZ6jj + DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 @@ -26,8 +28,6 @@ DB_DATABASE=greenview DB_USERNAME=root DB_PASSWORD= -FONNTE_TOKEN=CEAJquyLniASpRf76eT9 - SESSION_DRIVER=file SESSION_LIFETIME=120 SESSION_ENCRYPT=false @@ -52,7 +52,7 @@ MAIL_MAILER=smtp MAIL_HOST=smtp.gmail.com MAIL_PORT=587 MAIL_USERNAME=nunieiffel@gmail.com -MAIL_PASSWORD=etvyujyiyrnmylil +MAIL_PASSWORD=cmogtowklkmpqepk MAIL_ENCRYPTION=tls MAIL_FROM_ADDRESS=nunieiffel@gmail.com MAIL_FROM_NAME="Green View" diff --git a/.history/.env_20260521114434 b/.history/.env_20260625115711 similarity index 91% rename from .history/.env_20260521114434 rename to .history/.env_20260625115711 index b44db0c..c2c2077 100644 --- a/.history/.env_20260521114434 +++ b/.history/.env_20260625115711 @@ -19,6 +19,8 @@ LOG_STACK=single LOG_DEPRECATIONS_CHANNEL=null LOG_LEVEL=debug +FONNTE_TOKEN=ehgnxKGVwxZKfGzsWVzH + DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 @@ -26,8 +28,6 @@ DB_DATABASE=greenview DB_USERNAME=root DB_PASSWORD= -FONNTE_TOKEN=CEAJquyLniASpRf76eT9 - SESSION_DRIVER=file SESSION_LIFETIME=120 SESSION_ENCRYPT=false @@ -51,8 +51,8 @@ REDIS_PORT=6379 MAIL_MAILER=smtp MAIL_HOST=smtp.gmail.com MAIL_PORT=587 -MAIL_USERNAME=reyfandi3008@gmail.com -MAIL_PASSWORD=etvyujyiyrnmylil +MAIL_USERNAME=nunieiffel@gmail.com +MAIL_PASSWORD=cmogtowklkmpqepk MAIL_ENCRYPTION=tls MAIL_FROM_ADDRESS=nunieiffel@gmail.com MAIL_FROM_NAME="Green View" diff --git a/.history/app/Http/Controllers/Admin/UserController_20260521201056.php b/.history/app/Http/Controllers/Admin/UserController_20260521201056.php new file mode 100644 index 0000000..a637b86 --- /dev/null +++ b/.history/app/Http/Controllers/Admin/UserController_20260521201056.php @@ -0,0 +1,96 @@ +role != 'admin'){ + abort(403); + } + + return view('admin.user.create'); + } + +// SIMPAN DATA + public function store(Request $request) + { + if(Auth::user()->role != 'admin'){ + abort(403); + } + + $request->validate([ + 'name' => 'required', + 'email' => 'required|email|unique:users,email', + 'password' => 'required|min:6', + 'role' => 'required|in:rt' // 🔥 hanya boleh RT + ]); + + // 🔥 VALIDASI TAMBAHAN (ANTI NAKAL) + if ($request->role != 'rt') { + return back()->with('error', 'Hanya boleh menambahkan role RT!'); + } + + User::create([ + 'name' => $request->name, + 'email' => $request->email, + 'username' => $request->email, // biar aman + 'password' => bcrypt($request->password), + 'role' => 'rt' + ]); + + return redirect()->route('admin.user.index') + ->with('success', 'User RT berhasil ditambahkan'); + } + + // 🔥 FORM EDIT + public function edit($id) + { + $user = \App\Models\User::findOrFail($id); + return view('admin.user.edit', compact('user')); + } + + // 🔥 UPDATE DATA + // 🔥 UPDATE DATA + public function update(Request $request, $id) + { + $user = \App\Models\User::findOrFail($id); + + $request->validate([ + 'name' => 'required|string|max:255', + 'role' => 'required|in:admin,rt,user', + 'username' => 'nullable|string|max:255|unique:users,username,' . $id, + ]); + + $user->update([ + 'name' => $request->name, + 'role' => $request->role, + 'username' => $request->username, + // ❌ email TIDAK diupdate karena field locked/disabled + ]); + + return redirect()->route('admin.user.index') + ->with('success', 'Data user berhasil diupdate!'); + } + + public function destroy($id) + { + $user = \App\Models\User::findOrFail($id); + $user->delete(); + + return redirect()->route('admin.user.index')->with('success', 'User berhasil dihapus'); + } +} diff --git a/.history/app/Http/Controllers/Admin/UserController_20260521201058.php b/.history/app/Http/Controllers/Admin/UserController_20260521201058.php new file mode 100644 index 0000000..a7ea820 --- /dev/null +++ b/.history/app/Http/Controllers/Admin/UserController_20260521201058.php @@ -0,0 +1,96 @@ +role != 'admin'){ + abort(403); + } + + return view('admin.user.create'); + } + +// SIMPAN DATA + public function store(Request $request) + { + if(Auth::user()->role != 'admin'){ + abort(403); + } + + $request->validate([ + 'name' => 'required', + 'email' => 'required|email|unique:users,email', + 'password' => 'required|min:6', + 'role' => 'required|in:rt' // 🔥 hanya boleh RT + ]); + + // 🔥 VALIDASI TAMBAHAN (ANTI NAKAL) + if ($request->role != 'rt') { + return back()->with('error', 'Hanya boleh menambahkan role RT!'); + } + + User::create([ + 'name' => $request->name, + 'email' => $request->email, + 'username' => $request->email, // biar aman + 'password' => bcrypt($request->password), + 'role' => 'rt' + ]); + + return redirect()->route('admin.user.index') + ->with('success', 'User RT berhasil ditambahkan'); + } + + // 🔥 FORM EDIT + public function edit($id) + { + $user = \App\Models\User::findOrFail($id); + return view('admin.user.edit', compact('user')); + } + + // 🔥 UPDATE DATA + // 🔥 UPDATE DATA + public function update(Request $request, $id) + { + $user = \App\Models\User::findOrFail($id); + + $request->validate([ + 'name' => 'required|string|max:255', + 'role' => 'required|in:admin,rt,user', + 'username' => 'nullable|string|max:255|unique:users,username,' . $id, + ]); + + $user->update([ + 'name' => $request->name, + 'role' => $request->role, + 'username' => $request->username, + // ❌ email TIDAK diupdate karena field locked/disabled + ]); + + return redirect()->route('admin.user.index') + ->with('success', 'Data user berhasil diupdate!'); + } + + public function destroy($id) + { + $user = \App\Models\User::findOrFail($id); + $user->delete(); + + return redirect()->route('admin.user.index')->with('success', 'User berhasil dihapus'); + } +} diff --git a/.history/app/Http/Controllers/AuthController_20260506180715.php b/.history/app/Http/Controllers/AuthController_20260506180715.php deleted file mode 100644 index ef5168c..0000000 --- a/.history/app/Http/Controllers/AuthController_20260506180715.php +++ /dev/null @@ -1,171 +0,0 @@ -validate([ - 'login' => 'required', - 'password' => 'required' - ]); - - $login = $request->login; - $field = filter_var($login, FILTER_VALIDATE_EMAIL) ? 'email' : 'username'; - - if (Auth::attempt([$field => $login, 'password' => $request->password])) { - $request->session()->regenerate(); - - /** @var \App\Models\User $user */ - $user = Auth::user(); - - return match($user->role) { - 'admin' => redirect('/admin/dashboard'), - 'rt' => redirect('/rt/iuran'), - default => redirect('/user/home'), - }; - } - - return back()->with('error', 'Login gagal!'); - } - - // ================= REGISTER ================= - - public function register() - { - return view('auth.register'); - } - - public function prosesRegister(Request $request) - { - $request->validate([ - 'name' => 'required', - 'username' => 'required|unique:users,username', - 'email' => 'required|email|unique:users,email', - 'password' => 'required|min:6', - ]); - - User::create([ - 'name' => $request->name, - 'username' => $request->username, - 'email' => $request->email, - 'password' => Hash::make($request->password), - 'role' => 'user' - ]); - - return redirect('/login')->with('success', 'Register berhasil'); - } - - // ================= LOGOUT ================= - - public function logout(Request $request) - { - Auth::logout(); - - $request->session()->invalidate(); - $request->session()->regenerateToken(); - - return redirect('/login'); - } - - // ================= FORGOT PASSWORD ================= - - public function forgotForm() - { - return view('auth.forgot'); - } - - public function sendOtp(Request $request) - { - $request->validate([ - 'email' => 'required|email' - ]); - - $user = User::where('email', $request->email)->first(); - - if (!$user) { - return back()->with('error', 'Email tidak ditemukan'); - } - - $otp = rand(100000, 999999); - - $user->otp_code = $otp; - $user->otp_expired = now()->addMinutes(5); - $user->save(); - - Mail::to($user->email)->send(new OtpMail($otp)); - - session(['reset_email' => $user->email]); - - return redirect()->route('password.otp')->with('success', 'OTP dikirim ke email'); - } - - public function otpForm() - { - return view('auth.otp'); - } - - public function verifyOtp(Request $request) - { - $request->validate([ - 'otp' => 'required' - ]); - - $user = User::where('email', session('reset_email'))->first(); - - if (!$user) { - return redirect()->route('password.forgot'); - } - - if ($user->otp_code != $request->otp) { - return back()->with('error', 'OTP salah'); - } - - if (Carbon::now()->gt($user->otp_expired)) { - return back()->with('error', 'OTP expired'); - } - - return redirect()->route('password.reset'); - } - - public function resetForm() - { - return view('auth.reset'); - } - - public function resetPassword(Request $request) - { - $request->validate([ - 'password' => 'required|min:6|confirmed' - ]); - - $user = User::where('email', session('reset_email'))->first(); - - if (!$user) { - return redirect()->route('password.forgot'); - } - - $user->password = Hash::make($request->password); - $user->otp_code = null; - $user->otp_expired = null; - $user->save(); - - return redirect('/login')->with('success', 'Password berhasil direset'); - } -} diff --git a/.history/app/Http/Controllers/AuthController_20260507083718.php b/.history/app/Http/Controllers/AuthController_20260507083718.php deleted file mode 100644 index ef5168c..0000000 --- a/.history/app/Http/Controllers/AuthController_20260507083718.php +++ /dev/null @@ -1,171 +0,0 @@ -validate([ - 'login' => 'required', - 'password' => 'required' - ]); - - $login = $request->login; - $field = filter_var($login, FILTER_VALIDATE_EMAIL) ? 'email' : 'username'; - - if (Auth::attempt([$field => $login, 'password' => $request->password])) { - $request->session()->regenerate(); - - /** @var \App\Models\User $user */ - $user = Auth::user(); - - return match($user->role) { - 'admin' => redirect('/admin/dashboard'), - 'rt' => redirect('/rt/iuran'), - default => redirect('/user/home'), - }; - } - - return back()->with('error', 'Login gagal!'); - } - - // ================= REGISTER ================= - - public function register() - { - return view('auth.register'); - } - - public function prosesRegister(Request $request) - { - $request->validate([ - 'name' => 'required', - 'username' => 'required|unique:users,username', - 'email' => 'required|email|unique:users,email', - 'password' => 'required|min:6', - ]); - - User::create([ - 'name' => $request->name, - 'username' => $request->username, - 'email' => $request->email, - 'password' => Hash::make($request->password), - 'role' => 'user' - ]); - - return redirect('/login')->with('success', 'Register berhasil'); - } - - // ================= LOGOUT ================= - - public function logout(Request $request) - { - Auth::logout(); - - $request->session()->invalidate(); - $request->session()->regenerateToken(); - - return redirect('/login'); - } - - // ================= FORGOT PASSWORD ================= - - public function forgotForm() - { - return view('auth.forgot'); - } - - public function sendOtp(Request $request) - { - $request->validate([ - 'email' => 'required|email' - ]); - - $user = User::where('email', $request->email)->first(); - - if (!$user) { - return back()->with('error', 'Email tidak ditemukan'); - } - - $otp = rand(100000, 999999); - - $user->otp_code = $otp; - $user->otp_expired = now()->addMinutes(5); - $user->save(); - - Mail::to($user->email)->send(new OtpMail($otp)); - - session(['reset_email' => $user->email]); - - return redirect()->route('password.otp')->with('success', 'OTP dikirim ke email'); - } - - public function otpForm() - { - return view('auth.otp'); - } - - public function verifyOtp(Request $request) - { - $request->validate([ - 'otp' => 'required' - ]); - - $user = User::where('email', session('reset_email'))->first(); - - if (!$user) { - return redirect()->route('password.forgot'); - } - - if ($user->otp_code != $request->otp) { - return back()->with('error', 'OTP salah'); - } - - if (Carbon::now()->gt($user->otp_expired)) { - return back()->with('error', 'OTP expired'); - } - - return redirect()->route('password.reset'); - } - - public function resetForm() - { - return view('auth.reset'); - } - - public function resetPassword(Request $request) - { - $request->validate([ - 'password' => 'required|min:6|confirmed' - ]); - - $user = User::where('email', session('reset_email'))->first(); - - if (!$user) { - return redirect()->route('password.forgot'); - } - - $user->password = Hash::make($request->password); - $user->otp_code = null; - $user->otp_expired = null; - $user->save(); - - return redirect('/login')->with('success', 'Password berhasil direset'); - } -} diff --git a/.history/app/Http/Controllers/AuthController_20260507083845.php b/.history/app/Http/Controllers/AuthController_20260507083845.php deleted file mode 100644 index 7729eb0..0000000 --- a/.history/app/Http/Controllers/AuthController_20260507083845.php +++ /dev/null @@ -1,171 +0,0 @@ -validate([ - 'login' => 'required', - 'password' => 'required' - ]); - - $login = $request->login; - $field = filter_var($login, FILTER_VALIDATE_EMAIL) ? 'email' : 'username'; - - if (Auth::attempt([$field => $login, 'password' => $request->password])) { - $request->session()->regenerate(); - - /** @var \App\Models\User $user */ - $user = Auth::user(); - - return match($user->role) { - 'admin' => redirect('/admin/dashboard'), - 'rt' => redirect('/rt/'), - default => redirect('/user/home'), - }; - } - - return back()->with('error', 'Login gagal!'); - } - - // ================= REGISTER ================= - - public function register() - { - return view('auth.register'); - } - - public function prosesRegister(Request $request) - { - $request->validate([ - 'name' => 'required', - 'username' => 'required|unique:users,username', - 'email' => 'required|email|unique:users,email', - 'password' => 'required|min:6', - ]); - - User::create([ - 'name' => $request->name, - 'username' => $request->username, - 'email' => $request->email, - 'password' => Hash::make($request->password), - 'role' => 'user' - ]); - - return redirect('/login')->with('success', 'Register berhasil'); - } - - // ================= LOGOUT ================= - - public function logout(Request $request) - { - Auth::logout(); - - $request->session()->invalidate(); - $request->session()->regenerateToken(); - - return redirect('/login'); - } - - // ================= FORGOT PASSWORD ================= - - public function forgotForm() - { - return view('auth.forgot'); - } - - public function sendOtp(Request $request) - { - $request->validate([ - 'email' => 'required|email' - ]); - - $user = User::where('email', $request->email)->first(); - - if (!$user) { - return back()->with('error', 'Email tidak ditemukan'); - } - - $otp = rand(100000, 999999); - - $user->otp_code = $otp; - $user->otp_expired = now()->addMinutes(5); - $user->save(); - - Mail::to($user->email)->send(new OtpMail($otp)); - - session(['reset_email' => $user->email]); - - return redirect()->route('password.otp')->with('success', 'OTP dikirim ke email'); - } - - public function otpForm() - { - return view('auth.otp'); - } - - public function verifyOtp(Request $request) - { - $request->validate([ - 'otp' => 'required' - ]); - - $user = User::where('email', session('reset_email'))->first(); - - if (!$user) { - return redirect()->route('password.forgot'); - } - - if ($user->otp_code != $request->otp) { - return back()->with('error', 'OTP salah'); - } - - if (Carbon::now()->gt($user->otp_expired)) { - return back()->with('error', 'OTP expired'); - } - - return redirect()->route('password.reset'); - } - - public function resetForm() - { - return view('auth.reset'); - } - - public function resetPassword(Request $request) - { - $request->validate([ - 'password' => 'required|min:6|confirmed' - ]); - - $user = User::where('email', session('reset_email'))->first(); - - if (!$user) { - return redirect()->route('password.forgot'); - } - - $user->password = Hash::make($request->password); - $user->otp_code = null; - $user->otp_expired = null; - $user->save(); - - return redirect('/login')->with('success', 'Password berhasil direset'); - } -} diff --git a/.history/app/Http/Controllers/AuthController_20260507083847.php b/.history/app/Http/Controllers/AuthController_20260507083847.php deleted file mode 100644 index a0e8d78..0000000 --- a/.history/app/Http/Controllers/AuthController_20260507083847.php +++ /dev/null @@ -1,171 +0,0 @@ -validate([ - 'login' => 'required', - 'password' => 'required' - ]); - - $login = $request->login; - $field = filter_var($login, FILTER_VALIDATE_EMAIL) ? 'email' : 'username'; - - if (Auth::attempt([$field => $login, 'password' => $request->password])) { - $request->session()->regenerate(); - - /** @var \App\Models\User $user */ - $user = Auth::user(); - - return match($user->role) { - 'admin' => redirect('/admin/dashboard'), - 'rt' => redirect('/rt/dashboard'), - default => redirect('/user/home'), - }; - } - - return back()->with('error', 'Login gagal!'); - } - - // ================= REGISTER ================= - - public function register() - { - return view('auth.register'); - } - - public function prosesRegister(Request $request) - { - $request->validate([ - 'name' => 'required', - 'username' => 'required|unique:users,username', - 'email' => 'required|email|unique:users,email', - 'password' => 'required|min:6', - ]); - - User::create([ - 'name' => $request->name, - 'username' => $request->username, - 'email' => $request->email, - 'password' => Hash::make($request->password), - 'role' => 'user' - ]); - - return redirect('/login')->with('success', 'Register berhasil'); - } - - // ================= LOGOUT ================= - - public function logout(Request $request) - { - Auth::logout(); - - $request->session()->invalidate(); - $request->session()->regenerateToken(); - - return redirect('/login'); - } - - // ================= FORGOT PASSWORD ================= - - public function forgotForm() - { - return view('auth.forgot'); - } - - public function sendOtp(Request $request) - { - $request->validate([ - 'email' => 'required|email' - ]); - - $user = User::where('email', $request->email)->first(); - - if (!$user) { - return back()->with('error', 'Email tidak ditemukan'); - } - - $otp = rand(100000, 999999); - - $user->otp_code = $otp; - $user->otp_expired = now()->addMinutes(5); - $user->save(); - - Mail::to($user->email)->send(new OtpMail($otp)); - - session(['reset_email' => $user->email]); - - return redirect()->route('password.otp')->with('success', 'OTP dikirim ke email'); - } - - public function otpForm() - { - return view('auth.otp'); - } - - public function verifyOtp(Request $request) - { - $request->validate([ - 'otp' => 'required' - ]); - - $user = User::where('email', session('reset_email'))->first(); - - if (!$user) { - return redirect()->route('password.forgot'); - } - - if ($user->otp_code != $request->otp) { - return back()->with('error', 'OTP salah'); - } - - if (Carbon::now()->gt($user->otp_expired)) { - return back()->with('error', 'OTP expired'); - } - - return redirect()->route('password.reset'); - } - - public function resetForm() - { - return view('auth.reset'); - } - - public function resetPassword(Request $request) - { - $request->validate([ - 'password' => 'required|min:6|confirmed' - ]); - - $user = User::where('email', session('reset_email'))->first(); - - if (!$user) { - return redirect()->route('password.forgot'); - } - - $user->password = Hash::make($request->password); - $user->otp_code = null; - $user->otp_expired = null; - $user->save(); - - return redirect('/login')->with('success', 'Password berhasil direset'); - } -} diff --git a/.history/app/Http/Controllers/AuthController_20260524190202.php b/.history/app/Http/Controllers/AuthController_20260524190202.php new file mode 100644 index 0000000..51af4c3 --- /dev/null +++ b/.history/app/Http/Controllers/AuthController_20260524190202.php @@ -0,0 +1,275 @@ +// app/Http/Controllers/AuthController.php +validate([ + 'login' => 'required', + 'password' => 'required' + ]); + + $login = $request->login; + $field = filter_var($login, FILTER_VALIDATE_EMAIL) ? 'email' : 'username'; + + if (Auth::attempt([$field => $login, 'password' => $request->password])) { + $request->session()->regenerate(); + + /** @var \App\Models\User $user */ + $user = Auth::user(); + + return match($user->role) { + 'admin' => redirect('/admin/dashboard'), + 'rt' => redirect('/rt/dashboard'), + default => redirect('/user/home'), + }; + } + + return back()->with('error', 'Login gagal!'); + } + + // ================= REGISTER ================= + + public function register() + { + return view('auth.register'); + } + + public function prosesRegister(Request $request) + { + $request->validate([ + 'name' => 'required', + 'username' => 'required|unique:users,username', + 'email' => 'required|email|unique:users,email', + 'phone' => 'nullable|string|max:20', + 'password' => 'required|min:6', + ]); + + User::create([ + 'name' => $request->name, + 'username' => $request->username, + 'email' => $request->email, + 'phone' => $request->phone, + 'password' => Hash::make($request->password), + 'role' => 'user' + ]); + + return redirect('/login')->with('success', 'Register berhasil'); + } + + // ================= LOGOUT ================= + + public function logout(Request $request) + { + Auth::logout(); + $request->session()->invalidate(); + $request->session()->regenerateToken(); + return redirect('/login'); + } + + // ================= FORGOT PASSWORD ================= + + public function forgotForm() + { + return view('auth.forgot'); + } + + /** + * Kirim OTP — user pilih via Email atau WhatsApp + */ + public function sendOtp(Request $request) + { + $request->validate([ + 'email' => 'required|email', + 'method' => 'required|in:email,whatsapp', + ]); + + $user = User::where('email', $request->email)->first(); + + if (!$user) { + return back()->with('error', 'Email tidak ditemukan.'); + } + + // Validasi WhatsApp — pastikan user punya nomor HP + if ($request->method === 'whatsapp') { + if (empty($user->phone)) { + return back()->with('error', 'Akun ini tidak memiliki nomor WhatsApp terdaftar. Gunakan metode Email.'); + } + } + + // Generate OTP 6 digit + $otp = rand(100000, 999999); + + $user->otp_code = $otp; + $user->otp_expired = now()->addMinutes(5); + $user->save(); + + session([ + 'reset_email' => $user->email, + 'otp_method' => $request->method, + ]); + + if ($request->method === 'whatsapp') { + // Kirim via WhatsApp + $message = "🔐 *GREEN VIEW - Reset Password*\n\n" + . "Kode OTP Anda: *{$otp}*\n\n" + . "Kode berlaku selama *5 menit*.\n" + . "Jangan bagikan kode ini kepada siapapun.\n\n" + . "_PT Tunggal Griya Sakinah_"; + + $sent = WhatsappService::send($user->phone, $message); + + if (!$sent) { + return back()->with('error', 'Gagal mengirim OTP via WhatsApp. Coba metode Email.'); + } + + $maskedPhone = $this->maskPhone($user->phone); + return redirect()->route('password.otp') + ->with('success', "OTP berhasil dikirim ke WhatsApp {$maskedPhone}"); + } else { + // Kirim via Email + Mail::to($user->email)->send(new OtpMail($otp)); + + $maskedEmail = $this->maskEmail($user->email); + return redirect()->route('password.otp') + ->with('success', "OTP berhasil dikirim ke email {$maskedEmail}"); + } + } + + // ================= OTP ================= + + public function otpForm() + { + if (!session('reset_email')) { + return redirect()->route('password.forgot'); + } + return view('auth.otp'); + } + + public function verifyOtp(Request $request) + { + $request->validate([ + 'otp' => 'required|digits:6' + ]); + + $user = User::where('email', session('reset_email'))->first(); + + if (!$user) { + return redirect()->route('password.forgot') + ->with('error', 'Sesi habis, silakan ulangi.'); + } + + if ($user->otp_code != $request->otp) { + return back()->with('error', 'Kode OTP salah.'); + } + + if (Carbon::now()->gt($user->otp_expired)) { + return back()->with('error', 'Kode OTP sudah expired. Minta ulang kode baru.'); + } + + session(['otp_verified' => true]); + + return redirect()->route('password.reset'); + } + + // Kirim ulang OTP + public function resendOtp(Request $request) + { + $email = session('reset_email'); + $method = session('otp_method', 'email'); + + if (!$email) { + return redirect()->route('password.forgot'); + } + + $user = User::where('email', $email)->first(); + if (!$user) { + return redirect()->route('password.forgot'); + } + + $otp = rand(100000, 999999); + $user->otp_code = $otp; + $user->otp_expired = now()->addMinutes(5); + $user->save(); + + if ($method === 'whatsapp' && $user->phone) { + $message = "🔐 *GREEN VIEW - Reset Password*\n\n" + . "Kode OTP baru Anda: *{$otp}*\n\n" + . "Kode berlaku selama *5 menit*.\n" + . "Jangan bagikan kode ini kepada siapapun.\n\n" + . "_PT Tunggal Griya Sakinah_"; + WhatsappService::send($user->phone, $message); + return back()->with('success', 'OTP baru dikirim via WhatsApp.'); + } else { + Mail::to($user->email)->send(new OtpMail($otp)); + return back()->with('success', 'OTP baru dikirim via Email.'); + } + } + + // ================= RESET PASSWORD ================= + + public function resetForm() + { + if (!session('reset_email') || !session('otp_verified')) { + return redirect()->route('password.forgot'); + } + return view('auth.reset'); + } + + public function resetPassword(Request $request) + { + $request->validate([ + 'password' => 'required|min:6|confirmed' + ]); + + $user = User::where('email', session('reset_email'))->first(); + + if (!$user) { + return redirect()->route('password.forgot'); + } + + $user->password = Hash::make($request->password); + $user->otp_code = null; + $user->otp_expired = null; + $user->save(); + + // Hapus session + session()->forget(['reset_email', 'otp_method', 'otp_verified']); + + return redirect('/login')->with('success', 'Password berhasil direset! Silakan login.'); + } + + // ================= HELPERS ================= + + private function maskEmail(string $email): string + { + [$local, $domain] = explode('@', $email); + $masked = substr($local, 0, 2) . str_repeat('*', max(strlen($local) - 2, 3)); + return $masked . '@' . $domain; + } + + private function maskPhone(string $phone): string + { + $phone = WhatsappService::normalizePhone($phone); + return substr($phone, 0, 4) . str_repeat('*', strlen($phone) - 7) . substr($phone, -3); + } +} diff --git a/.history/app/Http/Controllers/AuthController_20260524190210.php b/.history/app/Http/Controllers/AuthController_20260524190210.php new file mode 100644 index 0000000..9b8c482 --- /dev/null +++ b/.history/app/Http/Controllers/AuthController_20260524190210.php @@ -0,0 +1,275 @@ + +validate([ + 'login' => 'required', + 'password' => 'required' + ]); + + $login = $request->login; + $field = filter_var($login, FILTER_VALIDATE_EMAIL) ? 'email' : 'username'; + + if (Auth::attempt([$field => $login, 'password' => $request->password])) { + $request->session()->regenerate(); + + /** @var \App\Models\User $user */ + $user = Auth::user(); + + return match($user->role) { + 'admin' => redirect('/admin/dashboard'), + 'rt' => redirect('/rt/dashboard'), + default => redirect('/user/home'), + }; + } + + return back()->with('error', 'Login gagal!'); + } + + // ================= REGISTER ================= + + public function register() + { + return view('auth.register'); + } + + public function prosesRegister(Request $request) + { + $request->validate([ + 'name' => 'required', + 'username' => 'required|unique:users,username', + 'email' => 'required|email|unique:users,email', + 'phone' => 'nullable|string|max:20', + 'password' => 'required|min:6', + ]); + + User::create([ + 'name' => $request->name, + 'username' => $request->username, + 'email' => $request->email, + 'phone' => $request->phone, + 'password' => Hash::make($request->password), + 'role' => 'user' + ]); + + return redirect('/login')->with('success', 'Register berhasil'); + } + + // ================= LOGOUT ================= + + public function logout(Request $request) + { + Auth::logout(); + $request->session()->invalidate(); + $request->session()->regenerateToken(); + return redirect('/login'); + } + + // ================= FORGOT PASSWORD ================= + + public function forgotForm() + { + return view('auth.forgot'); + } + + /** + * Kirim OTP — user pilih via Email atau WhatsApp + */ + public function sendOtp(Request $request) + { + $request->validate([ + 'email' => 'required|email', + 'method' => 'required|in:email,whatsapp', + ]); + + $user = User::where('email', $request->email)->first(); + + if (!$user) { + return back()->with('error', 'Email tidak ditemukan.'); + } + + // Validasi WhatsApp — pastikan user punya nomor HP + if ($request->method === 'whatsapp') { + if (empty($user->phone)) { + return back()->with('error', 'Akun ini tidak memiliki nomor WhatsApp terdaftar. Gunakan metode Email.'); + } + } + + // Generate OTP 6 digit + $otp = rand(100000, 999999); + + $user->otp_code = $otp; + $user->otp_expired = now()->addMinutes(5); + $user->save(); + + session([ + 'reset_email' => $user->email, + 'otp_method' => $request->method, + ]); + + if ($request->method === 'whatsapp') { + // Kirim via WhatsApp + $message = "🔐 *GREEN VIEW - Reset Password*\n\n" + . "Kode OTP Anda: *{$otp}*\n\n" + . "Kode berlaku selama *5 menit*.\n" + . "Jangan bagikan kode ini kepada siapapun.\n\n" + . "_PT Tunggal Griya Sakinah_"; + + $sent = WhatsappService::send($user->phone, $message); + + if (!$sent) { + return back()->with('error', 'Gagal mengirim OTP via WhatsApp. Coba metode Email.'); + } + + $maskedPhone = $this->maskPhone($user->phone); + return redirect()->route('password.otp') + ->with('success', "OTP berhasil dikirim ke WhatsApp {$maskedPhone}"); + } else { + // Kirim via Email + Mail::to($user->email)->send(new OtpMail($otp)); + + $maskedEmail = $this->maskEmail($user->email); + return redirect()->route('password.otp') + ->with('success', "OTP berhasil dikirim ke email {$maskedEmail}"); + } + } + + // ================= OTP ================= + + public function otpForm() + { + if (!session('reset_email')) { + return redirect()->route('password.forgot'); + } + return view('auth.otp'); + } + + public function verifyOtp(Request $request) + { + $request->validate([ + 'otp' => 'required|digits:6' + ]); + + $user = User::where('email', session('reset_email'))->first(); + + if (!$user) { + return redirect()->route('password.forgot') + ->with('error', 'Sesi habis, silakan ulangi.'); + } + + if ($user->otp_code != $request->otp) { + return back()->with('error', 'Kode OTP salah.'); + } + + if (Carbon::now()->gt($user->otp_expired)) { + return back()->with('error', 'Kode OTP sudah expired. Minta ulang kode baru.'); + } + + session(['otp_verified' => true]); + + return redirect()->route('password.reset'); + } + + // Kirim ulang OTP + public function resendOtp(Request $request) + { + $email = session('reset_email'); + $method = session('otp_method', 'email'); + + if (!$email) { + return redirect()->route('password.forgot'); + } + + $user = User::where('email', $email)->first(); + if (!$user) { + return redirect()->route('password.forgot'); + } + + $otp = rand(100000, 999999); + $user->otp_code = $otp; + $user->otp_expired = now()->addMinutes(5); + $user->save(); + + if ($method === 'whatsapp' && $user->phone) { + $message = "🔐 *GREEN VIEW - Reset Password*\n\n" + . "Kode OTP baru Anda: *{$otp}*\n\n" + . "Kode berlaku selama *5 menit*.\n" + . "Jangan bagikan kode ini kepada siapapun.\n\n" + . "_PT Tunggal Griya Sakinah_"; + WhatsappService::send($user->phone, $message); + return back()->with('success', 'OTP baru dikirim via WhatsApp.'); + } else { + Mail::to($user->email)->send(new OtpMail($otp)); + return back()->with('success', 'OTP baru dikirim via Email.'); + } + } + + // ================= RESET PASSWORD ================= + + public function resetForm() + { + if (!session('reset_email') || !session('otp_verified')) { + return redirect()->route('password.forgot'); + } + return view('auth.reset'); + } + + public function resetPassword(Request $request) + { + $request->validate([ + 'password' => 'required|min:6|confirmed' + ]); + + $user = User::where('email', session('reset_email'))->first(); + + if (!$user) { + return redirect()->route('password.forgot'); + } + + $user->password = Hash::make($request->password); + $user->otp_code = null; + $user->otp_expired = null; + $user->save(); + + // Hapus session + session()->forget(['reset_email', 'otp_method', 'otp_verified']); + + return redirect('/login')->with('success', 'Password berhasil direset! Silakan login.'); + } + + // ================= HELPERS ================= + + private function maskEmail(string $email): string + { + [$local, $domain] = explode('@', $email); + $masked = substr($local, 0, 2) . str_repeat('*', max(strlen($local) - 2, 3)); + return $masked . '@' . $domain; + } + + private function maskPhone(string $phone): string + { + $phone = WhatsappService::normalizePhone($phone); + return substr($phone, 0, 4) . str_repeat('*', strlen($phone) - 7) . substr($phone, -3); + } +} diff --git a/.history/app/Http/Controllers/AuthController_20260524190212.php b/.history/app/Http/Controllers/AuthController_20260524190212.php new file mode 100644 index 0000000..ac721fd --- /dev/null +++ b/.history/app/Http/Controllers/AuthController_20260524190212.php @@ -0,0 +1,274 @@ +validate([ + 'login' => 'required', + 'password' => 'required' + ]); + + $login = $request->login; + $field = filter_var($login, FILTER_VALIDATE_EMAIL) ? 'email' : 'username'; + + if (Auth::attempt([$field => $login, 'password' => $request->password])) { + $request->session()->regenerate(); + + /** @var \App\Models\User $user */ + $user = Auth::user(); + + return match($user->role) { + 'admin' => redirect('/admin/dashboard'), + 'rt' => redirect('/rt/dashboard'), + default => redirect('/user/home'), + }; + } + + return back()->with('error', 'Login gagal!'); + } + + // ================= REGISTER ================= + + public function register() + { + return view('auth.register'); + } + + public function prosesRegister(Request $request) + { + $request->validate([ + 'name' => 'required', + 'username' => 'required|unique:users,username', + 'email' => 'required|email|unique:users,email', + 'phone' => 'nullable|string|max:20', + 'password' => 'required|min:6', + ]); + + User::create([ + 'name' => $request->name, + 'username' => $request->username, + 'email' => $request->email, + 'phone' => $request->phone, + 'password' => Hash::make($request->password), + 'role' => 'user' + ]); + + return redirect('/login')->with('success', 'Register berhasil'); + } + + // ================= LOGOUT ================= + + public function logout(Request $request) + { + Auth::logout(); + $request->session()->invalidate(); + $request->session()->regenerateToken(); + return redirect('/login'); + } + + // ================= FORGOT PASSWORD ================= + + public function forgotForm() + { + return view('auth.forgot'); + } + + /** + * Kirim OTP — user pilih via Email atau WhatsApp + */ + public function sendOtp(Request $request) + { + $request->validate([ + 'email' => 'required|email', + 'method' => 'required|in:email,whatsapp', + ]); + + $user = User::where('email', $request->email)->first(); + + if (!$user) { + return back()->with('error', 'Email tidak ditemukan.'); + } + + // Validasi WhatsApp — pastikan user punya nomor HP + if ($request->method === 'whatsapp') { + if (empty($user->phone)) { + return back()->with('error', 'Akun ini tidak memiliki nomor WhatsApp terdaftar. Gunakan metode Email.'); + } + } + + // Generate OTP 6 digit + $otp = rand(100000, 999999); + + $user->otp_code = $otp; + $user->otp_expired = now()->addMinutes(5); + $user->save(); + + session([ + 'reset_email' => $user->email, + 'otp_method' => $request->method, + ]); + + if ($request->method === 'whatsapp') { + // Kirim via WhatsApp + $message = "🔐 *GREEN VIEW - Reset Password*\n\n" + . "Kode OTP Anda: *{$otp}*\n\n" + . "Kode berlaku selama *5 menit*.\n" + . "Jangan bagikan kode ini kepada siapapun.\n\n" + . "_PT Tunggal Griya Sakinah_"; + + $sent = WhatsappService::send($user->phone, $message); + + if (!$sent) { + return back()->with('error', 'Gagal mengirim OTP via WhatsApp. Coba metode Email.'); + } + + $maskedPhone = $this->maskPhone($user->phone); + return redirect()->route('password.otp') + ->with('success', "OTP berhasil dikirim ke WhatsApp {$maskedPhone}"); + } else { + // Kirim via Email + Mail::to($user->email)->send(new OtpMail($otp)); + + $maskedEmail = $this->maskEmail($user->email); + return redirect()->route('password.otp') + ->with('success', "OTP berhasil dikirim ke email {$maskedEmail}"); + } + } + + // ================= OTP ================= + + public function otpForm() + { + if (!session('reset_email')) { + return redirect()->route('password.forgot'); + } + return view('auth.otp'); + } + + public function verifyOtp(Request $request) + { + $request->validate([ + 'otp' => 'required|digits:6' + ]); + + $user = User::where('email', session('reset_email'))->first(); + + if (!$user) { + return redirect()->route('password.forgot') + ->with('error', 'Sesi habis, silakan ulangi.'); + } + + if ($user->otp_code != $request->otp) { + return back()->with('error', 'Kode OTP salah.'); + } + + if (Carbon::now()->gt($user->otp_expired)) { + return back()->with('error', 'Kode OTP sudah expired. Minta ulang kode baru.'); + } + + session(['otp_verified' => true]); + + return redirect()->route('password.reset'); + } + + // Kirim ulang OTP + public function resendOtp(Request $request) + { + $email = session('reset_email'); + $method = session('otp_method', 'email'); + + if (!$email) { + return redirect()->route('password.forgot'); + } + + $user = User::where('email', $email)->first(); + if (!$user) { + return redirect()->route('password.forgot'); + } + + $otp = rand(100000, 999999); + $user->otp_code = $otp; + $user->otp_expired = now()->addMinutes(5); + $user->save(); + + if ($method === 'whatsapp' && $user->phone) { + $message = "🔐 *GREEN VIEW - Reset Password*\n\n" + . "Kode OTP baru Anda: *{$otp}*\n\n" + . "Kode berlaku selama *5 menit*.\n" + . "Jangan bagikan kode ini kepada siapapun.\n\n" + . "_PT Tunggal Griya Sakinah_"; + WhatsappService::send($user->phone, $message); + return back()->with('success', 'OTP baru dikirim via WhatsApp.'); + } else { + Mail::to($user->email)->send(new OtpMail($otp)); + return back()->with('success', 'OTP baru dikirim via Email.'); + } + } + + // ================= RESET PASSWORD ================= + + public function resetForm() + { + if (!session('reset_email') || !session('otp_verified')) { + return redirect()->route('password.forgot'); + } + return view('auth.reset'); + } + + public function resetPassword(Request $request) + { + $request->validate([ + 'password' => 'required|min:6|confirmed' + ]); + + $user = User::where('email', session('reset_email'))->first(); + + if (!$user) { + return redirect()->route('password.forgot'); + } + + $user->password = Hash::make($request->password); + $user->otp_code = null; + $user->otp_expired = null; + $user->save(); + + // Hapus session + session()->forget(['reset_email', 'otp_method', 'otp_verified']); + + return redirect('/login')->with('success', 'Password berhasil direset! Silakan login.'); + } + + // ================= HELPERS ================= + + private function maskEmail(string $email): string + { + [$local, $domain] = explode('@', $email); + $masked = substr($local, 0, 2) . str_repeat('*', max(strlen($local) - 2, 3)); + return $masked . '@' . $domain; + } + + private function maskPhone(string $phone): string + { + $phone = WhatsappService::normalizePhone($phone); + return substr($phone, 0, 4) . str_repeat('*', strlen($phone) - 7) . substr($phone, -3); + } +} diff --git a/.history/app/Http/Controllers/AuthController_20260524190233.php b/.history/app/Http/Controllers/AuthController_20260524190233.php new file mode 100644 index 0000000..9b8c482 --- /dev/null +++ b/.history/app/Http/Controllers/AuthController_20260524190233.php @@ -0,0 +1,275 @@ + +validate([ + 'login' => 'required', + 'password' => 'required' + ]); + + $login = $request->login; + $field = filter_var($login, FILTER_VALIDATE_EMAIL) ? 'email' : 'username'; + + if (Auth::attempt([$field => $login, 'password' => $request->password])) { + $request->session()->regenerate(); + + /** @var \App\Models\User $user */ + $user = Auth::user(); + + return match($user->role) { + 'admin' => redirect('/admin/dashboard'), + 'rt' => redirect('/rt/dashboard'), + default => redirect('/user/home'), + }; + } + + return back()->with('error', 'Login gagal!'); + } + + // ================= REGISTER ================= + + public function register() + { + return view('auth.register'); + } + + public function prosesRegister(Request $request) + { + $request->validate([ + 'name' => 'required', + 'username' => 'required|unique:users,username', + 'email' => 'required|email|unique:users,email', + 'phone' => 'nullable|string|max:20', + 'password' => 'required|min:6', + ]); + + User::create([ + 'name' => $request->name, + 'username' => $request->username, + 'email' => $request->email, + 'phone' => $request->phone, + 'password' => Hash::make($request->password), + 'role' => 'user' + ]); + + return redirect('/login')->with('success', 'Register berhasil'); + } + + // ================= LOGOUT ================= + + public function logout(Request $request) + { + Auth::logout(); + $request->session()->invalidate(); + $request->session()->regenerateToken(); + return redirect('/login'); + } + + // ================= FORGOT PASSWORD ================= + + public function forgotForm() + { + return view('auth.forgot'); + } + + /** + * Kirim OTP — user pilih via Email atau WhatsApp + */ + public function sendOtp(Request $request) + { + $request->validate([ + 'email' => 'required|email', + 'method' => 'required|in:email,whatsapp', + ]); + + $user = User::where('email', $request->email)->first(); + + if (!$user) { + return back()->with('error', 'Email tidak ditemukan.'); + } + + // Validasi WhatsApp — pastikan user punya nomor HP + if ($request->method === 'whatsapp') { + if (empty($user->phone)) { + return back()->with('error', 'Akun ini tidak memiliki nomor WhatsApp terdaftar. Gunakan metode Email.'); + } + } + + // Generate OTP 6 digit + $otp = rand(100000, 999999); + + $user->otp_code = $otp; + $user->otp_expired = now()->addMinutes(5); + $user->save(); + + session([ + 'reset_email' => $user->email, + 'otp_method' => $request->method, + ]); + + if ($request->method === 'whatsapp') { + // Kirim via WhatsApp + $message = "🔐 *GREEN VIEW - Reset Password*\n\n" + . "Kode OTP Anda: *{$otp}*\n\n" + . "Kode berlaku selama *5 menit*.\n" + . "Jangan bagikan kode ini kepada siapapun.\n\n" + . "_PT Tunggal Griya Sakinah_"; + + $sent = WhatsappService::send($user->phone, $message); + + if (!$sent) { + return back()->with('error', 'Gagal mengirim OTP via WhatsApp. Coba metode Email.'); + } + + $maskedPhone = $this->maskPhone($user->phone); + return redirect()->route('password.otp') + ->with('success', "OTP berhasil dikirim ke WhatsApp {$maskedPhone}"); + } else { + // Kirim via Email + Mail::to($user->email)->send(new OtpMail($otp)); + + $maskedEmail = $this->maskEmail($user->email); + return redirect()->route('password.otp') + ->with('success', "OTP berhasil dikirim ke email {$maskedEmail}"); + } + } + + // ================= OTP ================= + + public function otpForm() + { + if (!session('reset_email')) { + return redirect()->route('password.forgot'); + } + return view('auth.otp'); + } + + public function verifyOtp(Request $request) + { + $request->validate([ + 'otp' => 'required|digits:6' + ]); + + $user = User::where('email', session('reset_email'))->first(); + + if (!$user) { + return redirect()->route('password.forgot') + ->with('error', 'Sesi habis, silakan ulangi.'); + } + + if ($user->otp_code != $request->otp) { + return back()->with('error', 'Kode OTP salah.'); + } + + if (Carbon::now()->gt($user->otp_expired)) { + return back()->with('error', 'Kode OTP sudah expired. Minta ulang kode baru.'); + } + + session(['otp_verified' => true]); + + return redirect()->route('password.reset'); + } + + // Kirim ulang OTP + public function resendOtp(Request $request) + { + $email = session('reset_email'); + $method = session('otp_method', 'email'); + + if (!$email) { + return redirect()->route('password.forgot'); + } + + $user = User::where('email', $email)->first(); + if (!$user) { + return redirect()->route('password.forgot'); + } + + $otp = rand(100000, 999999); + $user->otp_code = $otp; + $user->otp_expired = now()->addMinutes(5); + $user->save(); + + if ($method === 'whatsapp' && $user->phone) { + $message = "🔐 *GREEN VIEW - Reset Password*\n\n" + . "Kode OTP baru Anda: *{$otp}*\n\n" + . "Kode berlaku selama *5 menit*.\n" + . "Jangan bagikan kode ini kepada siapapun.\n\n" + . "_PT Tunggal Griya Sakinah_"; + WhatsappService::send($user->phone, $message); + return back()->with('success', 'OTP baru dikirim via WhatsApp.'); + } else { + Mail::to($user->email)->send(new OtpMail($otp)); + return back()->with('success', 'OTP baru dikirim via Email.'); + } + } + + // ================= RESET PASSWORD ================= + + public function resetForm() + { + if (!session('reset_email') || !session('otp_verified')) { + return redirect()->route('password.forgot'); + } + return view('auth.reset'); + } + + public function resetPassword(Request $request) + { + $request->validate([ + 'password' => 'required|min:6|confirmed' + ]); + + $user = User::where('email', session('reset_email'))->first(); + + if (!$user) { + return redirect()->route('password.forgot'); + } + + $user->password = Hash::make($request->password); + $user->otp_code = null; + $user->otp_expired = null; + $user->save(); + + // Hapus session + session()->forget(['reset_email', 'otp_method', 'otp_verified']); + + return redirect('/login')->with('success', 'Password berhasil direset! Silakan login.'); + } + + // ================= HELPERS ================= + + private function maskEmail(string $email): string + { + [$local, $domain] = explode('@', $email); + $masked = substr($local, 0, 2) . str_repeat('*', max(strlen($local) - 2, 3)); + return $masked . '@' . $domain; + } + + private function maskPhone(string $phone): string + { + $phone = WhatsappService::normalizePhone($phone); + return substr($phone, 0, 4) . str_repeat('*', strlen($phone) - 7) . substr($phone, -3); + } +} diff --git a/.history/app/Http/Controllers/AuthController_20260524190234.php b/.history/app/Http/Controllers/AuthController_20260524190234.php new file mode 100644 index 0000000..51af4c3 --- /dev/null +++ b/.history/app/Http/Controllers/AuthController_20260524190234.php @@ -0,0 +1,275 @@ +// app/Http/Controllers/AuthController.php +validate([ + 'login' => 'required', + 'password' => 'required' + ]); + + $login = $request->login; + $field = filter_var($login, FILTER_VALIDATE_EMAIL) ? 'email' : 'username'; + + if (Auth::attempt([$field => $login, 'password' => $request->password])) { + $request->session()->regenerate(); + + /** @var \App\Models\User $user */ + $user = Auth::user(); + + return match($user->role) { + 'admin' => redirect('/admin/dashboard'), + 'rt' => redirect('/rt/dashboard'), + default => redirect('/user/home'), + }; + } + + return back()->with('error', 'Login gagal!'); + } + + // ================= REGISTER ================= + + public function register() + { + return view('auth.register'); + } + + public function prosesRegister(Request $request) + { + $request->validate([ + 'name' => 'required', + 'username' => 'required|unique:users,username', + 'email' => 'required|email|unique:users,email', + 'phone' => 'nullable|string|max:20', + 'password' => 'required|min:6', + ]); + + User::create([ + 'name' => $request->name, + 'username' => $request->username, + 'email' => $request->email, + 'phone' => $request->phone, + 'password' => Hash::make($request->password), + 'role' => 'user' + ]); + + return redirect('/login')->with('success', 'Register berhasil'); + } + + // ================= LOGOUT ================= + + public function logout(Request $request) + { + Auth::logout(); + $request->session()->invalidate(); + $request->session()->regenerateToken(); + return redirect('/login'); + } + + // ================= FORGOT PASSWORD ================= + + public function forgotForm() + { + return view('auth.forgot'); + } + + /** + * Kirim OTP — user pilih via Email atau WhatsApp + */ + public function sendOtp(Request $request) + { + $request->validate([ + 'email' => 'required|email', + 'method' => 'required|in:email,whatsapp', + ]); + + $user = User::where('email', $request->email)->first(); + + if (!$user) { + return back()->with('error', 'Email tidak ditemukan.'); + } + + // Validasi WhatsApp — pastikan user punya nomor HP + if ($request->method === 'whatsapp') { + if (empty($user->phone)) { + return back()->with('error', 'Akun ini tidak memiliki nomor WhatsApp terdaftar. Gunakan metode Email.'); + } + } + + // Generate OTP 6 digit + $otp = rand(100000, 999999); + + $user->otp_code = $otp; + $user->otp_expired = now()->addMinutes(5); + $user->save(); + + session([ + 'reset_email' => $user->email, + 'otp_method' => $request->method, + ]); + + if ($request->method === 'whatsapp') { + // Kirim via WhatsApp + $message = "🔐 *GREEN VIEW - Reset Password*\n\n" + . "Kode OTP Anda: *{$otp}*\n\n" + . "Kode berlaku selama *5 menit*.\n" + . "Jangan bagikan kode ini kepada siapapun.\n\n" + . "_PT Tunggal Griya Sakinah_"; + + $sent = WhatsappService::send($user->phone, $message); + + if (!$sent) { + return back()->with('error', 'Gagal mengirim OTP via WhatsApp. Coba metode Email.'); + } + + $maskedPhone = $this->maskPhone($user->phone); + return redirect()->route('password.otp') + ->with('success', "OTP berhasil dikirim ke WhatsApp {$maskedPhone}"); + } else { + // Kirim via Email + Mail::to($user->email)->send(new OtpMail($otp)); + + $maskedEmail = $this->maskEmail($user->email); + return redirect()->route('password.otp') + ->with('success', "OTP berhasil dikirim ke email {$maskedEmail}"); + } + } + + // ================= OTP ================= + + public function otpForm() + { + if (!session('reset_email')) { + return redirect()->route('password.forgot'); + } + return view('auth.otp'); + } + + public function verifyOtp(Request $request) + { + $request->validate([ + 'otp' => 'required|digits:6' + ]); + + $user = User::where('email', session('reset_email'))->first(); + + if (!$user) { + return redirect()->route('password.forgot') + ->with('error', 'Sesi habis, silakan ulangi.'); + } + + if ($user->otp_code != $request->otp) { + return back()->with('error', 'Kode OTP salah.'); + } + + if (Carbon::now()->gt($user->otp_expired)) { + return back()->with('error', 'Kode OTP sudah expired. Minta ulang kode baru.'); + } + + session(['otp_verified' => true]); + + return redirect()->route('password.reset'); + } + + // Kirim ulang OTP + public function resendOtp(Request $request) + { + $email = session('reset_email'); + $method = session('otp_method', 'email'); + + if (!$email) { + return redirect()->route('password.forgot'); + } + + $user = User::where('email', $email)->first(); + if (!$user) { + return redirect()->route('password.forgot'); + } + + $otp = rand(100000, 999999); + $user->otp_code = $otp; + $user->otp_expired = now()->addMinutes(5); + $user->save(); + + if ($method === 'whatsapp' && $user->phone) { + $message = "🔐 *GREEN VIEW - Reset Password*\n\n" + . "Kode OTP baru Anda: *{$otp}*\n\n" + . "Kode berlaku selama *5 menit*.\n" + . "Jangan bagikan kode ini kepada siapapun.\n\n" + . "_PT Tunggal Griya Sakinah_"; + WhatsappService::send($user->phone, $message); + return back()->with('success', 'OTP baru dikirim via WhatsApp.'); + } else { + Mail::to($user->email)->send(new OtpMail($otp)); + return back()->with('success', 'OTP baru dikirim via Email.'); + } + } + + // ================= RESET PASSWORD ================= + + public function resetForm() + { + if (!session('reset_email') || !session('otp_verified')) { + return redirect()->route('password.forgot'); + } + return view('auth.reset'); + } + + public function resetPassword(Request $request) + { + $request->validate([ + 'password' => 'required|min:6|confirmed' + ]); + + $user = User::where('email', session('reset_email'))->first(); + + if (!$user) { + return redirect()->route('password.forgot'); + } + + $user->password = Hash::make($request->password); + $user->otp_code = null; + $user->otp_expired = null; + $user->save(); + + // Hapus session + session()->forget(['reset_email', 'otp_method', 'otp_verified']); + + return redirect('/login')->with('success', 'Password berhasil direset! Silakan login.'); + } + + // ================= HELPERS ================= + + private function maskEmail(string $email): string + { + [$local, $domain] = explode('@', $email); + $masked = substr($local, 0, 2) . str_repeat('*', max(strlen($local) - 2, 3)); + return $masked . '@' . $domain; + } + + private function maskPhone(string $phone): string + { + $phone = WhatsappService::normalizePhone($phone); + return substr($phone, 0, 4) . str_repeat('*', strlen($phone) - 7) . substr($phone, -3); + } +} diff --git a/.history/app/Http/Controllers/AuthController_20260524190235.php b/.history/app/Http/Controllers/AuthController_20260524190235.php new file mode 100644 index 0000000..51af4c3 --- /dev/null +++ b/.history/app/Http/Controllers/AuthController_20260524190235.php @@ -0,0 +1,275 @@ +// app/Http/Controllers/AuthController.php +validate([ + 'login' => 'required', + 'password' => 'required' + ]); + + $login = $request->login; + $field = filter_var($login, FILTER_VALIDATE_EMAIL) ? 'email' : 'username'; + + if (Auth::attempt([$field => $login, 'password' => $request->password])) { + $request->session()->regenerate(); + + /** @var \App\Models\User $user */ + $user = Auth::user(); + + return match($user->role) { + 'admin' => redirect('/admin/dashboard'), + 'rt' => redirect('/rt/dashboard'), + default => redirect('/user/home'), + }; + } + + return back()->with('error', 'Login gagal!'); + } + + // ================= REGISTER ================= + + public function register() + { + return view('auth.register'); + } + + public function prosesRegister(Request $request) + { + $request->validate([ + 'name' => 'required', + 'username' => 'required|unique:users,username', + 'email' => 'required|email|unique:users,email', + 'phone' => 'nullable|string|max:20', + 'password' => 'required|min:6', + ]); + + User::create([ + 'name' => $request->name, + 'username' => $request->username, + 'email' => $request->email, + 'phone' => $request->phone, + 'password' => Hash::make($request->password), + 'role' => 'user' + ]); + + return redirect('/login')->with('success', 'Register berhasil'); + } + + // ================= LOGOUT ================= + + public function logout(Request $request) + { + Auth::logout(); + $request->session()->invalidate(); + $request->session()->regenerateToken(); + return redirect('/login'); + } + + // ================= FORGOT PASSWORD ================= + + public function forgotForm() + { + return view('auth.forgot'); + } + + /** + * Kirim OTP — user pilih via Email atau WhatsApp + */ + public function sendOtp(Request $request) + { + $request->validate([ + 'email' => 'required|email', + 'method' => 'required|in:email,whatsapp', + ]); + + $user = User::where('email', $request->email)->first(); + + if (!$user) { + return back()->with('error', 'Email tidak ditemukan.'); + } + + // Validasi WhatsApp — pastikan user punya nomor HP + if ($request->method === 'whatsapp') { + if (empty($user->phone)) { + return back()->with('error', 'Akun ini tidak memiliki nomor WhatsApp terdaftar. Gunakan metode Email.'); + } + } + + // Generate OTP 6 digit + $otp = rand(100000, 999999); + + $user->otp_code = $otp; + $user->otp_expired = now()->addMinutes(5); + $user->save(); + + session([ + 'reset_email' => $user->email, + 'otp_method' => $request->method, + ]); + + if ($request->method === 'whatsapp') { + // Kirim via WhatsApp + $message = "🔐 *GREEN VIEW - Reset Password*\n\n" + . "Kode OTP Anda: *{$otp}*\n\n" + . "Kode berlaku selama *5 menit*.\n" + . "Jangan bagikan kode ini kepada siapapun.\n\n" + . "_PT Tunggal Griya Sakinah_"; + + $sent = WhatsappService::send($user->phone, $message); + + if (!$sent) { + return back()->with('error', 'Gagal mengirim OTP via WhatsApp. Coba metode Email.'); + } + + $maskedPhone = $this->maskPhone($user->phone); + return redirect()->route('password.otp') + ->with('success', "OTP berhasil dikirim ke WhatsApp {$maskedPhone}"); + } else { + // Kirim via Email + Mail::to($user->email)->send(new OtpMail($otp)); + + $maskedEmail = $this->maskEmail($user->email); + return redirect()->route('password.otp') + ->with('success', "OTP berhasil dikirim ke email {$maskedEmail}"); + } + } + + // ================= OTP ================= + + public function otpForm() + { + if (!session('reset_email')) { + return redirect()->route('password.forgot'); + } + return view('auth.otp'); + } + + public function verifyOtp(Request $request) + { + $request->validate([ + 'otp' => 'required|digits:6' + ]); + + $user = User::where('email', session('reset_email'))->first(); + + if (!$user) { + return redirect()->route('password.forgot') + ->with('error', 'Sesi habis, silakan ulangi.'); + } + + if ($user->otp_code != $request->otp) { + return back()->with('error', 'Kode OTP salah.'); + } + + if (Carbon::now()->gt($user->otp_expired)) { + return back()->with('error', 'Kode OTP sudah expired. Minta ulang kode baru.'); + } + + session(['otp_verified' => true]); + + return redirect()->route('password.reset'); + } + + // Kirim ulang OTP + public function resendOtp(Request $request) + { + $email = session('reset_email'); + $method = session('otp_method', 'email'); + + if (!$email) { + return redirect()->route('password.forgot'); + } + + $user = User::where('email', $email)->first(); + if (!$user) { + return redirect()->route('password.forgot'); + } + + $otp = rand(100000, 999999); + $user->otp_code = $otp; + $user->otp_expired = now()->addMinutes(5); + $user->save(); + + if ($method === 'whatsapp' && $user->phone) { + $message = "🔐 *GREEN VIEW - Reset Password*\n\n" + . "Kode OTP baru Anda: *{$otp}*\n\n" + . "Kode berlaku selama *5 menit*.\n" + . "Jangan bagikan kode ini kepada siapapun.\n\n" + . "_PT Tunggal Griya Sakinah_"; + WhatsappService::send($user->phone, $message); + return back()->with('success', 'OTP baru dikirim via WhatsApp.'); + } else { + Mail::to($user->email)->send(new OtpMail($otp)); + return back()->with('success', 'OTP baru dikirim via Email.'); + } + } + + // ================= RESET PASSWORD ================= + + public function resetForm() + { + if (!session('reset_email') || !session('otp_verified')) { + return redirect()->route('password.forgot'); + } + return view('auth.reset'); + } + + public function resetPassword(Request $request) + { + $request->validate([ + 'password' => 'required|min:6|confirmed' + ]); + + $user = User::where('email', session('reset_email'))->first(); + + if (!$user) { + return redirect()->route('password.forgot'); + } + + $user->password = Hash::make($request->password); + $user->otp_code = null; + $user->otp_expired = null; + $user->save(); + + // Hapus session + session()->forget(['reset_email', 'otp_method', 'otp_verified']); + + return redirect('/login')->with('success', 'Password berhasil direset! Silakan login.'); + } + + // ================= HELPERS ================= + + private function maskEmail(string $email): string + { + [$local, $domain] = explode('@', $email); + $masked = substr($local, 0, 2) . str_repeat('*', max(strlen($local) - 2, 3)); + return $masked . '@' . $domain; + } + + private function maskPhone(string $phone): string + { + $phone = WhatsappService::normalizePhone($phone); + return substr($phone, 0, 4) . str_repeat('*', strlen($phone) - 7) . substr($phone, -3); + } +} diff --git a/.history/app/Http/Controllers/AuthController_20260507083619.php b/.history/app/Http/Controllers/AuthController_20260524190240.php similarity index 100% rename from .history/app/Http/Controllers/AuthController_20260507083619.php rename to .history/app/Http/Controllers/AuthController_20260524190240.php diff --git a/.history/app/Http/Controllers/AuthController_20260524190256.php b/.history/app/Http/Controllers/AuthController_20260524190256.php new file mode 100644 index 0000000..51af4c3 --- /dev/null +++ b/.history/app/Http/Controllers/AuthController_20260524190256.php @@ -0,0 +1,275 @@ +// app/Http/Controllers/AuthController.php +validate([ + 'login' => 'required', + 'password' => 'required' + ]); + + $login = $request->login; + $field = filter_var($login, FILTER_VALIDATE_EMAIL) ? 'email' : 'username'; + + if (Auth::attempt([$field => $login, 'password' => $request->password])) { + $request->session()->regenerate(); + + /** @var \App\Models\User $user */ + $user = Auth::user(); + + return match($user->role) { + 'admin' => redirect('/admin/dashboard'), + 'rt' => redirect('/rt/dashboard'), + default => redirect('/user/home'), + }; + } + + return back()->with('error', 'Login gagal!'); + } + + // ================= REGISTER ================= + + public function register() + { + return view('auth.register'); + } + + public function prosesRegister(Request $request) + { + $request->validate([ + 'name' => 'required', + 'username' => 'required|unique:users,username', + 'email' => 'required|email|unique:users,email', + 'phone' => 'nullable|string|max:20', + 'password' => 'required|min:6', + ]); + + User::create([ + 'name' => $request->name, + 'username' => $request->username, + 'email' => $request->email, + 'phone' => $request->phone, + 'password' => Hash::make($request->password), + 'role' => 'user' + ]); + + return redirect('/login')->with('success', 'Register berhasil'); + } + + // ================= LOGOUT ================= + + public function logout(Request $request) + { + Auth::logout(); + $request->session()->invalidate(); + $request->session()->regenerateToken(); + return redirect('/login'); + } + + // ================= FORGOT PASSWORD ================= + + public function forgotForm() + { + return view('auth.forgot'); + } + + /** + * Kirim OTP — user pilih via Email atau WhatsApp + */ + public function sendOtp(Request $request) + { + $request->validate([ + 'email' => 'required|email', + 'method' => 'required|in:email,whatsapp', + ]); + + $user = User::where('email', $request->email)->first(); + + if (!$user) { + return back()->with('error', 'Email tidak ditemukan.'); + } + + // Validasi WhatsApp — pastikan user punya nomor HP + if ($request->method === 'whatsapp') { + if (empty($user->phone)) { + return back()->with('error', 'Akun ini tidak memiliki nomor WhatsApp terdaftar. Gunakan metode Email.'); + } + } + + // Generate OTP 6 digit + $otp = rand(100000, 999999); + + $user->otp_code = $otp; + $user->otp_expired = now()->addMinutes(5); + $user->save(); + + session([ + 'reset_email' => $user->email, + 'otp_method' => $request->method, + ]); + + if ($request->method === 'whatsapp') { + // Kirim via WhatsApp + $message = "🔐 *GREEN VIEW - Reset Password*\n\n" + . "Kode OTP Anda: *{$otp}*\n\n" + . "Kode berlaku selama *5 menit*.\n" + . "Jangan bagikan kode ini kepada siapapun.\n\n" + . "_PT Tunggal Griya Sakinah_"; + + $sent = WhatsappService::send($user->phone, $message); + + if (!$sent) { + return back()->with('error', 'Gagal mengirim OTP via WhatsApp. Coba metode Email.'); + } + + $maskedPhone = $this->maskPhone($user->phone); + return redirect()->route('password.otp') + ->with('success', "OTP berhasil dikirim ke WhatsApp {$maskedPhone}"); + } else { + // Kirim via Email + Mail::to($user->email)->send(new OtpMail($otp)); + + $maskedEmail = $this->maskEmail($user->email); + return redirect()->route('password.otp') + ->with('success', "OTP berhasil dikirim ke email {$maskedEmail}"); + } + } + + // ================= OTP ================= + + public function otpForm() + { + if (!session('reset_email')) { + return redirect()->route('password.forgot'); + } + return view('auth.otp'); + } + + public function verifyOtp(Request $request) + { + $request->validate([ + 'otp' => 'required|digits:6' + ]); + + $user = User::where('email', session('reset_email'))->first(); + + if (!$user) { + return redirect()->route('password.forgot') + ->with('error', 'Sesi habis, silakan ulangi.'); + } + + if ($user->otp_code != $request->otp) { + return back()->with('error', 'Kode OTP salah.'); + } + + if (Carbon::now()->gt($user->otp_expired)) { + return back()->with('error', 'Kode OTP sudah expired. Minta ulang kode baru.'); + } + + session(['otp_verified' => true]); + + return redirect()->route('password.reset'); + } + + // Kirim ulang OTP + public function resendOtp(Request $request) + { + $email = session('reset_email'); + $method = session('otp_method', 'email'); + + if (!$email) { + return redirect()->route('password.forgot'); + } + + $user = User::where('email', $email)->first(); + if (!$user) { + return redirect()->route('password.forgot'); + } + + $otp = rand(100000, 999999); + $user->otp_code = $otp; + $user->otp_expired = now()->addMinutes(5); + $user->save(); + + if ($method === 'whatsapp' && $user->phone) { + $message = "🔐 *GREEN VIEW - Reset Password*\n\n" + . "Kode OTP baru Anda: *{$otp}*\n\n" + . "Kode berlaku selama *5 menit*.\n" + . "Jangan bagikan kode ini kepada siapapun.\n\n" + . "_PT Tunggal Griya Sakinah_"; + WhatsappService::send($user->phone, $message); + return back()->with('success', 'OTP baru dikirim via WhatsApp.'); + } else { + Mail::to($user->email)->send(new OtpMail($otp)); + return back()->with('success', 'OTP baru dikirim via Email.'); + } + } + + // ================= RESET PASSWORD ================= + + public function resetForm() + { + if (!session('reset_email') || !session('otp_verified')) { + return redirect()->route('password.forgot'); + } + return view('auth.reset'); + } + + public function resetPassword(Request $request) + { + $request->validate([ + 'password' => 'required|min:6|confirmed' + ]); + + $user = User::where('email', session('reset_email'))->first(); + + if (!$user) { + return redirect()->route('password.forgot'); + } + + $user->password = Hash::make($request->password); + $user->otp_code = null; + $user->otp_expired = null; + $user->save(); + + // Hapus session + session()->forget(['reset_email', 'otp_method', 'otp_verified']); + + return redirect('/login')->with('success', 'Password berhasil direset! Silakan login.'); + } + + // ================= HELPERS ================= + + private function maskEmail(string $email): string + { + [$local, $domain] = explode('@', $email); + $masked = substr($local, 0, 2) . str_repeat('*', max(strlen($local) - 2, 3)); + return $masked . '@' . $domain; + } + + private function maskPhone(string $phone): string + { + $phone = WhatsappService::normalizePhone($phone); + return substr($phone, 0, 4) . str_repeat('*', strlen($phone) - 7) . substr($phone, -3); + } +} diff --git a/.history/app/Http/Controllers/AuthController_20260524190306.php b/.history/app/Http/Controllers/AuthController_20260524190306.php new file mode 100644 index 0000000..ac721fd --- /dev/null +++ b/.history/app/Http/Controllers/AuthController_20260524190306.php @@ -0,0 +1,274 @@ +validate([ + 'login' => 'required', + 'password' => 'required' + ]); + + $login = $request->login; + $field = filter_var($login, FILTER_VALIDATE_EMAIL) ? 'email' : 'username'; + + if (Auth::attempt([$field => $login, 'password' => $request->password])) { + $request->session()->regenerate(); + + /** @var \App\Models\User $user */ + $user = Auth::user(); + + return match($user->role) { + 'admin' => redirect('/admin/dashboard'), + 'rt' => redirect('/rt/dashboard'), + default => redirect('/user/home'), + }; + } + + return back()->with('error', 'Login gagal!'); + } + + // ================= REGISTER ================= + + public function register() + { + return view('auth.register'); + } + + public function prosesRegister(Request $request) + { + $request->validate([ + 'name' => 'required', + 'username' => 'required|unique:users,username', + 'email' => 'required|email|unique:users,email', + 'phone' => 'nullable|string|max:20', + 'password' => 'required|min:6', + ]); + + User::create([ + 'name' => $request->name, + 'username' => $request->username, + 'email' => $request->email, + 'phone' => $request->phone, + 'password' => Hash::make($request->password), + 'role' => 'user' + ]); + + return redirect('/login')->with('success', 'Register berhasil'); + } + + // ================= LOGOUT ================= + + public function logout(Request $request) + { + Auth::logout(); + $request->session()->invalidate(); + $request->session()->regenerateToken(); + return redirect('/login'); + } + + // ================= FORGOT PASSWORD ================= + + public function forgotForm() + { + return view('auth.forgot'); + } + + /** + * Kirim OTP — user pilih via Email atau WhatsApp + */ + public function sendOtp(Request $request) + { + $request->validate([ + 'email' => 'required|email', + 'method' => 'required|in:email,whatsapp', + ]); + + $user = User::where('email', $request->email)->first(); + + if (!$user) { + return back()->with('error', 'Email tidak ditemukan.'); + } + + // Validasi WhatsApp — pastikan user punya nomor HP + if ($request->method === 'whatsapp') { + if (empty($user->phone)) { + return back()->with('error', 'Akun ini tidak memiliki nomor WhatsApp terdaftar. Gunakan metode Email.'); + } + } + + // Generate OTP 6 digit + $otp = rand(100000, 999999); + + $user->otp_code = $otp; + $user->otp_expired = now()->addMinutes(5); + $user->save(); + + session([ + 'reset_email' => $user->email, + 'otp_method' => $request->method, + ]); + + if ($request->method === 'whatsapp') { + // Kirim via WhatsApp + $message = "🔐 *GREEN VIEW - Reset Password*\n\n" + . "Kode OTP Anda: *{$otp}*\n\n" + . "Kode berlaku selama *5 menit*.\n" + . "Jangan bagikan kode ini kepada siapapun.\n\n" + . "_PT Tunggal Griya Sakinah_"; + + $sent = WhatsappService::send($user->phone, $message); + + if (!$sent) { + return back()->with('error', 'Gagal mengirim OTP via WhatsApp. Coba metode Email.'); + } + + $maskedPhone = $this->maskPhone($user->phone); + return redirect()->route('password.otp') + ->with('success', "OTP berhasil dikirim ke WhatsApp {$maskedPhone}"); + } else { + // Kirim via Email + Mail::to($user->email)->send(new OtpMail($otp)); + + $maskedEmail = $this->maskEmail($user->email); + return redirect()->route('password.otp') + ->with('success', "OTP berhasil dikirim ke email {$maskedEmail}"); + } + } + + // ================= OTP ================= + + public function otpForm() + { + if (!session('reset_email')) { + return redirect()->route('password.forgot'); + } + return view('auth.otp'); + } + + public function verifyOtp(Request $request) + { + $request->validate([ + 'otp' => 'required|digits:6' + ]); + + $user = User::where('email', session('reset_email'))->first(); + + if (!$user) { + return redirect()->route('password.forgot') + ->with('error', 'Sesi habis, silakan ulangi.'); + } + + if ($user->otp_code != $request->otp) { + return back()->with('error', 'Kode OTP salah.'); + } + + if (Carbon::now()->gt($user->otp_expired)) { + return back()->with('error', 'Kode OTP sudah expired. Minta ulang kode baru.'); + } + + session(['otp_verified' => true]); + + return redirect()->route('password.reset'); + } + + // Kirim ulang OTP + public function resendOtp(Request $request) + { + $email = session('reset_email'); + $method = session('otp_method', 'email'); + + if (!$email) { + return redirect()->route('password.forgot'); + } + + $user = User::where('email', $email)->first(); + if (!$user) { + return redirect()->route('password.forgot'); + } + + $otp = rand(100000, 999999); + $user->otp_code = $otp; + $user->otp_expired = now()->addMinutes(5); + $user->save(); + + if ($method === 'whatsapp' && $user->phone) { + $message = "🔐 *GREEN VIEW - Reset Password*\n\n" + . "Kode OTP baru Anda: *{$otp}*\n\n" + . "Kode berlaku selama *5 menit*.\n" + . "Jangan bagikan kode ini kepada siapapun.\n\n" + . "_PT Tunggal Griya Sakinah_"; + WhatsappService::send($user->phone, $message); + return back()->with('success', 'OTP baru dikirim via WhatsApp.'); + } else { + Mail::to($user->email)->send(new OtpMail($otp)); + return back()->with('success', 'OTP baru dikirim via Email.'); + } + } + + // ================= RESET PASSWORD ================= + + public function resetForm() + { + if (!session('reset_email') || !session('otp_verified')) { + return redirect()->route('password.forgot'); + } + return view('auth.reset'); + } + + public function resetPassword(Request $request) + { + $request->validate([ + 'password' => 'required|min:6|confirmed' + ]); + + $user = User::where('email', session('reset_email'))->first(); + + if (!$user) { + return redirect()->route('password.forgot'); + } + + $user->password = Hash::make($request->password); + $user->otp_code = null; + $user->otp_expired = null; + $user->save(); + + // Hapus session + session()->forget(['reset_email', 'otp_method', 'otp_verified']); + + return redirect('/login')->with('success', 'Password berhasil direset! Silakan login.'); + } + + // ================= HELPERS ================= + + private function maskEmail(string $email): string + { + [$local, $domain] = explode('@', $email); + $masked = substr($local, 0, 2) . str_repeat('*', max(strlen($local) - 2, 3)); + return $masked . '@' . $domain; + } + + private function maskPhone(string $phone): string + { + $phone = WhatsappService::normalizePhone($phone); + return substr($phone, 0, 4) . str_repeat('*', strlen($phone) - 7) . substr($phone, -3); + } +} diff --git a/.history/app/Http/Controllers/AuthController_20260524191313.php b/.history/app/Http/Controllers/AuthController_20260524191313.php new file mode 100644 index 0000000..b7ff0db --- /dev/null +++ b/.history/app/Http/Controllers/AuthController_20260524191313.php @@ -0,0 +1,270 @@ +validate([ + 'login' => 'required', + 'password' => 'required' + ]); + + $login = $request->login; + $field = filter_var($login, FILTER_VALIDATE_EMAIL) ? 'email' : 'username'; + + if (Auth::attempt([$field => $login, 'password' => $request->password])) { + $request->session()->regenerate(); + + /** @var \App\Models\User $user */ + $user = Auth::user(); + + return match($user->role) { + 'admin' => redirect('/admin/dashboard'), + 'rt' => redirect('/rt/dashboard'), + default => redirect('/user/home'), + }; + } + + return back()->with('error', 'Login gagal!'); + } + + // ================= REGISTER ================= + + public function register() + { + return view('auth.register'); + } + + public function prosesRegister(Request $request) + { + $request->validate([ + 'name' => 'required', + 'username' => 'required|unique:users,username', + 'email' => 'required|email|unique:users,email', + 'phone' => 'nullable|string|max:20', + 'password' => 'required|min:6', + ]); + + User::create([ + 'name' => $request->name, + 'username' => $request->username, + 'email' => $request->email, + 'phone' => $request->phone, + 'password' => Hash::make($request->password), + 'role' => 'user' + ]); + + return redirect('/login')->with('success', 'Register berhasil'); + } + + // ================= LOGOUT ================= + + public function logout(Request $request) + { + Auth::logout(); + $request->session()->invalidate(); + $request->session()->regenerateToken(); + return redirect('/login'); + } + + // ================= FORGOT PASSWORD ================= + + public function forgotForm() + { + return view('auth.forgot'); + } + + public function sendOtp(Request $request) + { + $request->validate([ + 'email' => 'required|email', + 'otp_via' => 'required|in:email,whatsapp', // ← ganti dari 'method' ke 'otp_via' + ]); + + $user = User::where('email', $request->email)->first(); + + if (!$user) { + return back()->with('error', 'Email tidak ditemukan.'); + } + + $otpVia = $request->input('otp_via'); // ← pakai input() bukan ->method + + // Validasi WhatsApp + if ($otpVia === 'whatsapp') { + if (empty($user->phone)) { + return back()->with('error', 'Akun ini tidak memiliki nomor WhatsApp terdaftar. Gunakan metode Email.'); + } + } + + // Generate OTP 6 digit + $otp = rand(100000, 999999); + + $user->otp_code = $otp; + $user->otp_expired = now()->addMinutes(5); + $user->save(); + + session([ + 'reset_email' => $user->email, + 'otp_method' => $otpVia, + ]); + + if ($otpVia === 'whatsapp') { + $message = "🔐 *GREEN VIEW - Reset Password*\n\n" + . "Kode OTP Anda: *{$otp}*\n\n" + . "Kode berlaku selama *5 menit*.\n" + . "Jangan bagikan kode ini kepada siapapun.\n\n" + . "_PT Tunggal Griya Sakinah_"; + + $sent = WhatsappService::send($user->phone, $message); + + if (!$sent) { + return back()->with('error', 'Gagal mengirim OTP via WhatsApp. Coba metode Email.'); + } + + $maskedPhone = $this->maskPhone($user->phone); + return redirect()->route('password.otp') + ->with('success', "OTP berhasil dikirim ke WhatsApp {$maskedPhone}"); + } else { + Mail::to($user->email)->send(new OtpMail($otp)); + + $maskedEmail = $this->maskEmail($user->email); + return redirect()->route('password.otp') + ->with('success', "OTP berhasil dikirim ke email {$maskedEmail}"); + } + } + + // ================= OTP ================= + + public function otpForm() + { + if (!session('reset_email')) { + return redirect()->route('password.forgot'); + } + return view('auth.otp'); + } + + public function verifyOtp(Request $request) + { + $request->validate([ + 'otp' => 'required|digits:6' + ]); + + $user = User::where('email', session('reset_email'))->first(); + + if (!$user) { + return redirect()->route('password.forgot') + ->with('error', 'Sesi habis, silakan ulangi.'); + } + + if ($user->otp_code != $request->otp) { + return back()->with('error', 'Kode OTP salah.'); + } + + if (Carbon::now()->gt($user->otp_expired)) { + return back()->with('error', 'Kode OTP sudah expired. Minta ulang kode baru.'); + } + + session(['otp_verified' => true]); + + return redirect()->route('password.reset'); + } + + // Kirim ulang OTP + public function resendOtp(Request $request) + { + $email = session('reset_email'); + $method = session('otp_method', 'email'); + + if (!$email) { + return redirect()->route('password.forgot'); + } + + $user = User::where('email', $email)->first(); + if (!$user) { + return redirect()->route('password.forgot'); + } + + $otp = rand(100000, 999999); + $user->otp_code = $otp; + $user->otp_expired = now()->addMinutes(5); + $user->save(); + + if ($method === 'whatsapp' && $user->phone) { + $message = "🔐 *GREEN VIEW - Reset Password*\n\n" + . "Kode OTP baru Anda: *{$otp}*\n\n" + . "Kode berlaku selama *5 menit*.\n" + . "Jangan bagikan kode ini kepada siapapun.\n\n" + . "_PT Tunggal Griya Sakinah_"; + WhatsappService::send($user->phone, $message); + return back()->with('success', 'OTP baru dikirim via WhatsApp.'); + } else { + Mail::to($user->email)->send(new OtpMail($otp)); + return back()->with('success', 'OTP baru dikirim via Email.'); + } + } + + // ================= RESET PASSWORD ================= + + public function resetForm() + { + if (!session('reset_email') || !session('otp_verified')) { + return redirect()->route('password.forgot'); + } + return view('auth.reset'); + } + + public function resetPassword(Request $request) + { + $request->validate([ + 'password' => 'required|min:6|confirmed' + ]); + + $user = User::where('email', session('reset_email'))->first(); + + if (!$user) { + return redirect()->route('password.forgot'); + } + + $user->password = Hash::make($request->password); + $user->otp_code = null; + $user->otp_expired = null; + $user->save(); + + session()->forget(['reset_email', 'otp_method', 'otp_verified']); + + return redirect('/login')->with('success', 'Password berhasil direset! Silakan login.'); + } + + // ================= HELPERS ================= + + private function maskEmail(string $email): string + { + [$local, $domain] = explode('@', $email); + $masked = substr($local, 0, 2) . str_repeat('*', max(strlen($local) - 2, 3)); + return $masked . '@' . $domain; + } + + private function maskPhone(string $phone): string + { + $phone = WhatsappService::normalizePhone($phone); + return substr($phone, 0, 4) . str_repeat('*', strlen($phone) - 7) . substr($phone, -3); + } +} diff --git a/.history/app/Http/Controllers/AuthController_20260524192503.php b/.history/app/Http/Controllers/AuthController_20260524192503.php new file mode 100644 index 0000000..42345ba --- /dev/null +++ b/.history/app/Http/Controllers/AuthController_20260524192503.php @@ -0,0 +1,291 @@ +validate([ + 'login' => 'required', + 'password' => 'required' + ]); + + $login = $request->login; + $field = filter_var($login, FILTER_VALIDATE_EMAIL) ? 'email' : 'username'; + + if (Auth::attempt([$field => $login, 'password' => $request->password])) { + $request->session()->regenerate(); + + /** @var \App\Models\User $user */ + $user = Auth::user(); + + return match($user->role) { + 'admin' => redirect('/admin/dashboard'), + 'rt' => redirect('/rt/dashboard'), + default => redirect('/user/home'), + }; + } + + return back()->with('error', 'Login gagal!'); + } + + // ================= REGISTER ================= + + public function register() + { + return view('auth.register'); + } + + public function prosesRegister(Request $request) + { + $request->validate([ + 'name' => 'required', + 'username' => 'required|unique:users,username', + 'email' => 'required|email|unique:users,email', + 'password' => 'required|min:6', + ]); + + User::create([ + 'name' => $request->name, + 'username' => $request->username, + 'email' => $request->email, + 'password' => Hash::make($request->password), + 'role' => 'user' + ]); + + return redirect('/login')->with('success', 'Register berhasil'); + } + + // ================= LOGOUT ================= + + public function logout(Request $request) + { + Auth::logout(); + $request->session()->invalidate(); + $request->session()->regenerateToken(); + return redirect('/login'); + } + + // ================= FORGOT PASSWORD ================= + + public function forgotForm() + { + return view('auth.forgot'); + } + + public function sendOtp(Request $request) + { + $request->validate([ + 'email' => 'required|email', + 'otp_via' => 'required|in:email,whatsapp', + ]); + + $user = User::where('email', $request->email)->first(); + + if (!$user) { + return back() + ->withInput() + ->with('error', 'Email tidak ditemukan.'); + } + + $otpVia = $request->input('otp_via'); + $telepon = null; + + // Ambil nomor telepon dari tabel penghuni (kolom: telepon) + if ($otpVia === 'whatsapp') { + $penghuni = Penghuni::where('user_id', $user->id)->first(); + + if (!$penghuni || empty($penghuni->telepon)) { + return back() + ->withInput() + ->with('error', 'Akun ini tidak memiliki nomor WhatsApp terdaftar di data penghuni. Gunakan metode Email.'); + } + + $telepon = $penghuni->telepon; + } + + // Generate OTP 6 digit + $otp = rand(100000, 999999); + + $user->otp_code = $otp; + $user->otp_expired = now()->addMinutes(5); + $user->save(); + + session([ + 'reset_email' => $user->email, + 'otp_method' => $otpVia, + ]); + + if ($otpVia === 'whatsapp') { + $message = "🔐 *GREEN VIEW - Reset Password*\n\n" + . "Kode OTP Anda: *{$otp}*\n\n" + . "Kode berlaku selama *5 menit*.\n" + . "Jangan bagikan kode ini kepada siapapun.\n\n" + . "_PT Tunggal Griya Sakinah_"; + + $sent = WhatsappService::send($telepon, $message); + + if (!$sent) { + return back() + ->withInput() + ->with('error', 'Gagal mengirim OTP via WhatsApp. Coba metode Email.'); + } + + $maskedPhone = $this->maskPhone($telepon); + return redirect()->route('password.otp') + ->with('success', "OTP berhasil dikirim ke WhatsApp {$maskedPhone}"); + } else { + Mail::to($user->email)->send(new OtpMail($otp)); + + $maskedEmail = $this->maskEmail($user->email); + return redirect()->route('password.otp') + ->with('success', "OTP berhasil dikirim ke email {$maskedEmail}"); + } + } + + // ================= OTP ================= + + public function otpForm() + { + if (!session('reset_email')) { + return redirect()->route('password.forgot'); + } + return view('auth.otp'); + } + + public function verifyOtp(Request $request) + { + $request->validate([ + 'otp' => 'required|digits:6' + ]); + + $user = User::where('email', session('reset_email'))->first(); + + if (!$user) { + return redirect()->route('password.forgot') + ->with('error', 'Sesi habis, silakan ulangi.'); + } + + if ($user->otp_code != $request->otp) { + return back()->with('error', 'Kode OTP salah.'); + } + + if (Carbon::now()->gt($user->otp_expired)) { + return back()->with('error', 'Kode OTP sudah expired. Minta ulang kode baru.'); + } + + session(['otp_verified' => true]); + + return redirect()->route('password.reset'); + } + + // Kirim ulang OTP + public function resendOtp(Request $request) + { + $email = session('reset_email'); + $method = session('otp_method', 'email'); + + if (!$email) { + return redirect()->route('password.forgot'); + } + + $user = User::where('email', $email)->first(); + if (!$user) { + return redirect()->route('password.forgot'); + } + + $otp = rand(100000, 999999); + $user->otp_code = $otp; + $user->otp_expired = now()->addMinutes(5); + $user->save(); + + if ($method === 'whatsapp') { + // Ambil telepon dari tabel penghuni + $penghuni = Penghuni::where('user_id', $user->id)->first(); + $telepon = $penghuni ? $penghuni->telepon : null; + + if ($telepon) { + $message = "🔐 *GREEN VIEW - Reset Password*\n\n" + . "Kode OTP baru Anda: *{$otp}*\n\n" + . "Kode berlaku selama *5 menit*.\n" + . "Jangan bagikan kode ini kepada siapapun.\n\n" + . "_PT Tunggal Griya Sakinah_"; + + WhatsappService::send($telepon, $message); + return back()->with('success', 'OTP baru dikirim via WhatsApp.'); + } + + // Fallback ke email jika telepon tidak ada + Mail::to($user->email)->send(new OtpMail($otp)); + return back()->with('success', 'Nomor WA tidak ditemukan, OTP dikirim via Email.'); + } else { + Mail::to($user->email)->send(new OtpMail($otp)); + return back()->with('success', 'OTP baru dikirim via Email.'); + } + } + + // ================= RESET PASSWORD ================= + + public function resetForm() + { + if (!session('reset_email') || !session('otp_verified')) { + return redirect()->route('password.forgot'); + } + return view('auth.reset'); + } + + public function resetPassword(Request $request) + { + $request->validate([ + 'password' => 'required|min:6|confirmed' + ]); + + $user = User::where('email', session('reset_email'))->first(); + + if (!$user) { + return redirect()->route('password.forgot'); + } + + $user->password = Hash::make($request->password); + $user->otp_code = null; + $user->otp_expired = null; + $user->save(); + + session()->forget(['reset_email', 'otp_method', 'otp_verified']); + + return redirect('/login')->with('success', 'Password berhasil direset! Silakan login.'); + } + + // ================= HELPERS ================= + + private function maskEmail(string $email): string + { + [$local, $domain] = explode('@', $email); + $masked = substr($local, 0, 2) . str_repeat('*', max(strlen($local) - 2, 3)); + return $masked . '@' . $domain; + } + + private function maskPhone(string $phone): string + { + $phone = WhatsappService::normalizePhone($phone); + return substr($phone, 0, 4) . str_repeat('*', strlen($phone) - 7) . substr($phone, -3); + } +} diff --git a/.history/app/Http/Controllers/AuthController_20260524200654.php b/.history/app/Http/Controllers/AuthController_20260524200654.php new file mode 100644 index 0000000..3c2dac0 --- /dev/null +++ b/.history/app/Http/Controllers/AuthController_20260524200654.php @@ -0,0 +1,302 @@ +validate([ + 'login' => 'required', + 'password' => 'required' + ]); + + $login = $request->login; + $field = filter_var($login, FILTER_VALIDATE_EMAIL) ? 'email' : 'username'; + + if (Auth::attempt([$field => $login, 'password' => $request->password])) { + $request->session()->regenerate(); + + /** @var \App\Models\User $user */ + $user = Auth::user(); + + return match($user->role) { + 'admin' => redirect('/admin/dashboard'), + 'rt' => redirect('/rt/dashboard'), + default => redirect('/user/home'), + }; + } + + return back()->with('error', 'Login gagal!'); + } + + // ================= REGISTER ================= + + public function register() + { + return view('auth.register'); + } + + public function prosesRegister(Request $request) + { + $request->validate([ + 'name' => 'required', + 'username' => 'required|unique:users,username', + 'email' => 'required|email|unique:users,email', + 'password' => 'required|min:6', + ]); + + User::create([ + 'name' => $request->name, + 'username' => $request->username, + 'email' => $request->email, + 'password' => Hash::make($request->password), + 'role' => 'user' + ]); + + return redirect('/login')->with('success', 'Register berhasil'); + } + + // ================= LOGOUT ================= + + public function logout(Request $request) + { + Auth::logout(); + $request->session()->invalidate(); + $request->session()->regenerateToken(); + return redirect('/login'); + } + + // ================= FORGOT PASSWORD ================= + + public function forgotForm() + { + return view('auth.forgot'); + } + + public function sendOtp(Request $request) + { + // Validasi dasar + $request->validate([ + 'email' => 'required|email', + 'otp_via' => 'required|in:email,whatsapp', + ]); + + $user = User::where('email', $request->email)->first(); + + if (!$user) { + return back() + ->withInput() + ->with('error', 'Email tidak ditemukan.'); + } + + $otpVia = $request->input('otp_via'); + $telepon = null; + + // Jika pilih WhatsApp, ambil nomor dari input form dulu, + // fallback ke tabel penghuni jika kosong + if ($otpVia === 'whatsapp') { + $phoneInput = trim($request->input('phone', '')); + + if (!empty($phoneInput)) { + // Pakai nomor yang diinput user di form + $telepon = $phoneInput; + } else { + // Fallback: cari di tabel penghuni + $penghuni = Penghuni::where('user_id', $user->id)->first(); + if ($penghuni && !empty($penghuni->telepon)) { + $telepon = $penghuni->telepon; + } + } + + if (empty($telepon)) { + return back() + ->withInput() + ->with('error', 'Masukkan nomor WhatsApp Anda di kolom yang tersedia.'); + } + } + + // Generate OTP 6 digit + $otp = rand(100000, 999999); + + $user->otp_code = $otp; + $user->otp_expired = now()->addMinutes(5); + $user->save(); + + // Simpan di session (telepon disimpan untuk resend) + session([ + 'reset_email' => $user->email, + 'otp_method' => $otpVia, + 'reset_telepon' => $telepon, + ]); + + if ($otpVia === 'whatsapp') { + $message = "🔐 *GREEN VIEW - Reset Password*\n\n" + . "Kode OTP Anda: *{$otp}*\n\n" + . "Kode berlaku selama *5 menit*.\n" + . "Jangan bagikan kode ini kepada siapapun.\n\n" + . "_PT Tunggal Griya Sakinah_"; + + $sent = WhatsappService::send($telepon, $message); + + if (!$sent) { + return back() + ->withInput() + ->with('error', 'Gagal mengirim OTP via WhatsApp. Pastikan nomor benar atau coba metode Email.'); + } + + $maskedPhone = $this->maskPhone($telepon); + return redirect()->route('password.otp') + ->with('success', "OTP berhasil dikirim ke WhatsApp {$maskedPhone}"); + } else { + Mail::to($user->email)->send(new OtpMail($otp)); + + $maskedEmail = $this->maskEmail($user->email); + return redirect()->route('password.otp') + ->with('success', "OTP berhasil dikirim ke email {$maskedEmail}"); + } + } + + // ================= OTP ================= + + public function otpForm() + { + if (!session('reset_email')) { + return redirect()->route('password.forgot'); + } + return view('auth.otp'); + } + + public function verifyOtp(Request $request) + { + $request->validate([ + 'otp' => 'required|digits:6' + ]); + + $user = User::where('email', session('reset_email'))->first(); + + if (!$user) { + return redirect()->route('password.forgot') + ->with('error', 'Sesi habis, silakan ulangi.'); + } + + if ($user->otp_code != $request->otp) { + return back()->with('error', 'Kode OTP salah.'); + } + + if (Carbon::now()->gt($user->otp_expired)) { + return back()->with('error', 'Kode OTP sudah expired. Minta ulang kode baru.'); + } + + session(['otp_verified' => true]); + + return redirect()->route('password.reset'); + } + + // Kirim ulang OTP + public function resendOtp(Request $request) + { + $email = session('reset_email'); + $method = session('otp_method', 'email'); + $telepon = session('reset_telepon'); + + if (!$email) { + return redirect()->route('password.forgot'); + } + + $user = User::where('email', $email)->first(); + if (!$user) { + return redirect()->route('password.forgot'); + } + + $otp = rand(100000, 999999); + $user->otp_code = $otp; + $user->otp_expired = now()->addMinutes(5); + $user->save(); + + if ($method === 'whatsapp' && !empty($telepon)) { + $message = "🔐 *GREEN VIEW - Reset Password*\n\n" + . "Kode OTP baru Anda: *{$otp}*\n\n" + . "Kode berlaku selama *5 menit*.\n" + . "Jangan bagikan kode ini kepada siapapun.\n\n" + . "_PT Tunggal Griya Sakinah_"; + + $sent = WhatsappService::send($telepon, $message); + + if ($sent) { + return back()->with('success', 'OTP baru dikirim via WhatsApp.'); + } + + // Fallback ke email jika WA gagal + Mail::to($user->email)->send(new OtpMail($otp)); + return back()->with('success', 'WhatsApp gagal, OTP dikirim via Email.'); + } else { + Mail::to($user->email)->send(new OtpMail($otp)); + return back()->with('success', 'OTP baru dikirim via Email.'); + } + } + + // ================= RESET PASSWORD ================= + + public function resetForm() + { + if (!session('reset_email') || !session('otp_verified')) { + return redirect()->route('password.forgot'); + } + return view('auth.reset'); + } + + public function resetPassword(Request $request) + { + $request->validate([ + 'password' => 'required|min:6|confirmed' + ]); + + $user = User::where('email', session('reset_email'))->first(); + + if (!$user) { + return redirect()->route('password.forgot'); + } + + $user->password = Hash::make($request->password); + $user->otp_code = null; + $user->otp_expired = null; + $user->save(); + + session()->forget(['reset_email', 'otp_method', 'otp_verified', 'reset_telepon']); + + return redirect('/login')->with('success', 'Password berhasil direset! Silakan login.'); + } + + // ================= HELPERS ================= + + private function maskEmail(string $email): string + { + [$local, $domain] = explode('@', $email); + $masked = substr($local, 0, 2) . str_repeat('*', max(strlen($local) - 2, 3)); + return $masked . '@' . $domain; + } + + private function maskPhone(string $phone): string + { + $phone = WhatsappService::normalizePhone($phone); + return substr($phone, 0, 4) . str_repeat('*', strlen($phone) - 7) . substr($phone, -3); + } +} diff --git a/.history/app/Http/Controllers/AuthController_20260524201955.php b/.history/app/Http/Controllers/AuthController_20260524201955.php new file mode 100644 index 0000000..d07ef09 --- /dev/null +++ b/.history/app/Http/Controllers/AuthController_20260524201955.php @@ -0,0 +1,290 @@ +validate([ + 'login' => 'required', + 'password' => 'required' + ]); + + $login = $request->login; + $field = filter_var($login, FILTER_VALIDATE_EMAIL) ? 'email' : 'username'; + + if (Auth::attempt([$field => $login, 'password' => $request->password])) { + $request->session()->regenerate(); + + /** @var \App\Models\User $user */ + $user = Auth::user(); + + return match($user->role) { + 'admin' => redirect('/admin/dashboard'), + 'rt' => redirect('/rt/dashboard'), + default => redirect('/user/home'), + }; + } + + return back()->with('error', 'Login gagal!'); + } + + // ================= REGISTER ================= + + public function register() + { + return view('auth.register'); + } + + public function prosesRegister(Request $request) + { + $request->validate([ + 'name' => 'required', + 'username' => 'required|unique:users,username', + 'email' => 'required|email|unique:users,email', + 'password' => 'required|min:6', + ]); + + User::create([ + 'name' => $request->name, + 'username' => $request->username, + 'email' => $request->email, + 'password' => Hash::make($request->password), + 'role' => 'user' + ]); + + return redirect('/login')->with('success', 'Register berhasil'); + } + + // ================= LOGOUT ================= + + public function logout(Request $request) + { + Auth::logout(); + $request->session()->invalidate(); + $request->session()->regenerateToken(); + return redirect('/login'); + } + + // ================= FORGOT PASSWORD ================= + + public function forgotForm() + { + return view('auth.forgot'); + } + + public function sendOtp(Request $request) + { + $request->validate([ + 'email' => 'required|email', + 'otp_via' => 'required|in:email,whatsapp', + ]); + + $user = User::where('email', $request->email)->first(); + + if (!$user) { + return back() + ->withInput() + ->with('error', 'Email tidak ditemukan.'); + } + + $otpVia = $request->input('otp_via'); + $telepon = null; + + // Ambil nomor dari tabel penghuni berdasarkan user_id + if ($otpVia === 'whatsapp') { + $penghuni = Penghuni::where('user_id', $user->id)->first(); + + if (!$penghuni || empty($penghuni->telepon)) { + return back() + ->withInput() + ->with('error', 'Nomor WhatsApp tidak ditemukan di data penghuni. Silakan gunakan metode Email.'); + } + + $telepon = $penghuni->telepon; + } + + // Generate OTP 6 digit + $otp = rand(100000, 999999); + + $user->otp_code = $otp; + $user->otp_expired = now()->addMinutes(5); + $user->save(); + + session([ + 'reset_email' => $user->email, + 'otp_method' => $otpVia, + 'reset_telepon' => $telepon, + ]); + + if ($otpVia === 'whatsapp') { + $message = "🔐 *GREEN VIEW - Reset Password*\n\n" + . "Kode OTP Anda: *{$otp}*\n\n" + . "Kode berlaku selama *5 menit*.\n" + . "Jangan bagikan kode ini kepada siapapun.\n\n" + . "_PT Tunggal Griya Sakinah_"; + + $sent = WhatsappService::send($telepon, $message); + + if (!$sent) { + return back() + ->withInput() + ->with('error', 'Gagal mengirim OTP via WhatsApp. Coba metode Email.'); + } + + $maskedPhone = $this->maskPhone($telepon); + return redirect()->route('password.otp') + ->with('success', "OTP berhasil dikirim ke WhatsApp {$maskedPhone}"); + } else { + Mail::to($user->email)->send(new OtpMail($otp)); + + $maskedEmail = $this->maskEmail($user->email); + return redirect()->route('password.otp') + ->with('success', "OTP berhasil dikirim ke email {$maskedEmail}"); + } + } + + // ================= OTP ================= + + public function otpForm() + { + if (!session('reset_email')) { + return redirect()->route('password.forgot'); + } + return view('auth.otp'); + } + + public function verifyOtp(Request $request) + { + $request->validate([ + 'otp' => 'required|digits:6' + ]); + + $user = User::where('email', session('reset_email'))->first(); + + if (!$user) { + return redirect()->route('password.forgot') + ->with('error', 'Sesi habis, silakan ulangi.'); + } + + if ($user->otp_code != $request->otp) { + return back()->with('error', 'Kode OTP salah.'); + } + + if (Carbon::now()->gt($user->otp_expired)) { + return back()->with('error', 'Kode OTP sudah expired. Minta ulang kode baru.'); + } + + session(['otp_verified' => true]); + + return redirect()->route('password.reset'); + } + + // Kirim ulang OTP + public function resendOtp(Request $request) + { + $email = session('reset_email'); + $method = session('otp_method', 'email'); + $telepon = session('reset_telepon'); + + if (!$email) { + return redirect()->route('password.forgot'); + } + + $user = User::where('email', $email)->first(); + if (!$user) { + return redirect()->route('password.forgot'); + } + + $otp = rand(100000, 999999); + $user->otp_code = $otp; + $user->otp_expired = now()->addMinutes(5); + $user->save(); + + if ($method === 'whatsapp' && !empty($telepon)) { + $message = "🔐 *GREEN VIEW - Reset Password*\n\n" + . "Kode OTP baru Anda: *{$otp}*\n\n" + . "Kode berlaku selama *5 menit*.\n" + . "Jangan bagikan kode ini kepada siapapun.\n\n" + . "_PT Tunggal Griya Sakinah_"; + + $sent = WhatsappService::send($telepon, $message); + + if ($sent) { + return back()->with('success', 'OTP baru dikirim via WhatsApp.'); + } + + // Fallback ke email jika WA gagal + Mail::to($user->email)->send(new OtpMail($otp)); + return back()->with('success', 'WhatsApp gagal, OTP dikirim via Email.'); + } else { + Mail::to($user->email)->send(new OtpMail($otp)); + return back()->with('success', 'OTP baru dikirim via Email.'); + } + } + + // ================= RESET PASSWORD ================= + + public function resetForm() + { + if (!session('reset_email') || !session('otp_verified')) { + return redirect()->route('password.forgot'); + } + return view('auth.reset'); + } + + public function resetPassword(Request $request) + { + $request->validate([ + 'password' => 'required|min:6|confirmed' + ]); + + $user = User::where('email', session('reset_email'))->first(); + + if (!$user) { + return redirect()->route('password.forgot'); + } + + $user->password = Hash::make($request->password); + $user->otp_code = null; + $user->otp_expired = null; + $user->save(); + + session()->forget(['reset_email', 'otp_method', 'otp_verified', 'reset_telepon']); + + return redirect('/login')->with('success', 'Password berhasil direset! Silakan login.'); + } + + // ================= HELPERS ================= + + private function maskEmail(string $email): string + { + [$local, $domain] = explode('@', $email); + $masked = substr($local, 0, 2) . str_repeat('*', max(strlen($local) - 2, 3)); + return $masked . '@' . $domain; + } + + private function maskPhone(string $phone): string + { + $phone = WhatsappService::normalizePhone($phone); + return substr($phone, 0, 4) . str_repeat('*', strlen($phone) - 7) . substr($phone, -3); + } +} diff --git a/.history/app/Http/Controllers/AuthController_20260524202342.php b/.history/app/Http/Controllers/AuthController_20260524202342.php new file mode 100644 index 0000000..06347b9 --- /dev/null +++ b/.history/app/Http/Controllers/AuthController_20260524202342.php @@ -0,0 +1,287 @@ +validate([ + 'login' => 'required', + 'password' => 'required' + ]); + + $login = $request->login; + $field = filter_var($login, FILTER_VALIDATE_EMAIL) ? 'email' : 'username'; + + if (Auth::attempt([$field => $login, 'password' => $request->password])) { + $request->session()->regenerate(); + + /** @var \App\Models\User $user */ + $user = Auth::user(); + + return match($user->role) { + 'admin' => redirect('/admin/dashboard'), + 'rt' => redirect('/rt/dashboard'), + default => redirect('/user/home'), + }; + } + + return back()->with('error', 'Login gagal!'); + } + + // ================= REGISTER ================= + + public function register() + { + return view('auth.register'); + } + + public function prosesRegister(Request $request) + { + $request->validate([ + 'name' => 'required', + 'username' => 'required|unique:users,username', + 'email' => 'required|email|unique:users,email', + 'password' => 'required|min:6', + ]); + + User::create([ + 'name' => $request->name, + 'username' => $request->username, + 'email' => $request->email, + 'password' => Hash::make($request->password), + 'role' => 'user' + ]); + + return redirect('/login')->with('success', 'Register berhasil'); + } + + // ================= LOGOUT ================= + + public function logout(Request $request) + { + Auth::logout(); + $request->session()->invalidate(); + $request->session()->regenerateToken(); + return redirect('/login'); + } + + // ================= FORGOT PASSWORD ================= + + public function forgotForm() + { + return view('auth.forgot'); + } + + public function sendOtp(Request $request) + { + $request->validate([ + 'email' => 'required|email', + 'otp_via' => 'required|in:email,whatsapp', + ]); + + $user = User::where('email', $request->email)->first(); + + if (!$user) { + return back() + ->withInput() + ->with('error', 'Email tidak ditemukan.'); + } + + $otpVia = $request->input('otp_via'); + $telepon = null; + + // ✅ Ambil nomor langsung dari kolom `phone` di tabel users + if ($otpVia === 'whatsapp') { + if (empty($user->phone)) { + return back() + ->withInput() + ->with('error', 'Nomor WhatsApp belum terdaftar di akun ini. Silakan gunakan metode Email.'); + } + + $telepon = $user->phone; + } + + // Generate OTP 6 digit + $otp = rand(100000, 999999); + + $user->otp_code = $otp; + $user->otp_expired = now()->addMinutes(5); + $user->save(); + + session([ + 'reset_email' => $user->email, + 'otp_method' => $otpVia, + 'reset_telepon' => $telepon, + ]); + + if ($otpVia === 'whatsapp') { + $message = "🔐 *GREEN VIEW - Reset Password*\n\n" + . "Kode OTP Anda: *{$otp}*\n\n" + . "Kode berlaku selama *5 menit*.\n" + . "Jangan bagikan kode ini kepada siapapun.\n\n" + . "_PT Tunggal Griya Sakinah_"; + + $sent = WhatsappService::send($telepon, $message); + + if (!$sent) { + return back() + ->withInput() + ->with('error', 'Gagal mengirim OTP via WhatsApp. Coba metode Email.'); + } + + $maskedPhone = $this->maskPhone($telepon); + return redirect()->route('password.otp') + ->with('success', "OTP berhasil dikirim ke WhatsApp {$maskedPhone}"); + } else { + Mail::to($user->email)->send(new OtpMail($otp)); + + $maskedEmail = $this->maskEmail($user->email); + return redirect()->route('password.otp') + ->with('success', "OTP berhasil dikirim ke email {$maskedEmail}"); + } + } + + // ================= OTP ================= + + public function otpForm() + { + if (!session('reset_email')) { + return redirect()->route('password.forgot'); + } + return view('auth.otp'); + } + + public function verifyOtp(Request $request) + { + $request->validate([ + 'otp' => 'required|digits:6' + ]); + + $user = User::where('email', session('reset_email'))->first(); + + if (!$user) { + return redirect()->route('password.forgot') + ->with('error', 'Sesi habis, silakan ulangi.'); + } + + if ($user->otp_code != $request->otp) { + return back()->with('error', 'Kode OTP salah.'); + } + + if (Carbon::now()->gt($user->otp_expired)) { + return back()->with('error', 'Kode OTP sudah expired. Minta ulang kode baru.'); + } + + session(['otp_verified' => true]); + + return redirect()->route('password.reset'); + } + + // Kirim ulang OTP + public function resendOtp(Request $request) + { + $email = session('reset_email'); + $method = session('otp_method', 'email'); + $telepon = session('reset_telepon'); + + if (!$email) { + return redirect()->route('password.forgot'); + } + + $user = User::where('email', $email)->first(); + if (!$user) { + return redirect()->route('password.forgot'); + } + + $otp = rand(100000, 999999); + $user->otp_code = $otp; + $user->otp_expired = now()->addMinutes(5); + $user->save(); + + if ($method === 'whatsapp' && !empty($telepon)) { + $message = "🔐 *GREEN VIEW - Reset Password*\n\n" + . "Kode OTP baru Anda: *{$otp}*\n\n" + . "Kode berlaku selama *5 menit*.\n" + . "Jangan bagikan kode ini kepada siapapun.\n\n" + . "_PT Tunggal Griya Sakinah_"; + + $sent = WhatsappService::send($telepon, $message); + + if ($sent) { + return back()->with('success', 'OTP baru dikirim via WhatsApp.'); + } + + Mail::to($user->email)->send(new OtpMail($otp)); + return back()->with('success', 'WhatsApp gagal, OTP dikirim via Email.'); + } else { + Mail::to($user->email)->send(new OtpMail($otp)); + return back()->with('success', 'OTP baru dikirim via Email.'); + } + } + + // ================= RESET PASSWORD ================= + + public function resetForm() + { + if (!session('reset_email') || !session('otp_verified')) { + return redirect()->route('password.forgot'); + } + return view('auth.reset'); + } + + public function resetPassword(Request $request) + { + $request->validate([ + 'password' => 'required|min:6|confirmed' + ]); + + $user = User::where('email', session('reset_email'))->first(); + + if (!$user) { + return redirect()->route('password.forgot'); + } + + $user->password = Hash::make($request->password); + $user->otp_code = null; + $user->otp_expired = null; + $user->save(); + + session()->forget(['reset_email', 'otp_method', 'otp_verified', 'reset_telepon']); + + return redirect('/login')->with('success', 'Password berhasil direset! Silakan login.'); + } + + // ================= HELPERS ================= + + private function maskEmail(string $email): string + { + [$local, $domain] = explode('@', $email); + $masked = substr($local, 0, 2) . str_repeat('*', max(strlen($local) - 2, 3)); + return $masked . '@' . $domain; + } + + private function maskPhone(string $phone): string + { + $phone = WhatsappService::normalizePhone($phone); + return substr($phone, 0, 4) . str_repeat('*', strlen($phone) - 7) . substr($phone, -3); + } +} diff --git a/.history/app/Http/Controllers/AuthController_20260524212628.php b/.history/app/Http/Controllers/AuthController_20260524212628.php new file mode 100644 index 0000000..2df09fe --- /dev/null +++ b/.history/app/Http/Controllers/AuthController_20260524212628.php @@ -0,0 +1,71 @@ +public function sendOtp(Request $request) +{ + $request->validate([ + 'email' => 'required|email', + 'otp_via' => 'required|in:email,whatsapp', + // ✅ Wajib isi nomor jika pilih WhatsApp + 'phone' => 'required_if:otp_via,whatsapp', + ], [ + 'phone.required_if' => 'Nomor WhatsApp wajib diisi jika memilih metode WhatsApp.', + ]); + + $user = User::where('email', $request->email)->first(); + + if (!$user) { + return back() + ->withInput() + ->with('error', 'Email tidak ditemukan.'); + } + + $otpVia = $request->input('otp_via'); + + // Generate OTP 6 digit + $otp = rand(100000, 999999); + $user->otp_code = $otp; + $user->otp_expired = now()->addMinutes(5); + $user->save(); + + if ($otpVia === 'whatsapp') { + // ✅ Gunakan nomor dari input form, bukan dari DB + $telepon = $request->input('phone'); + $telepon = WhatsappService::normalizePhone($telepon); + + $message = "🔐 *GREEN VIEW - Reset Password*\n\n" + . "Kode OTP Anda: *{$otp}*\n\n" + . "Kode berlaku selama *5 menit*.\n" + . "Jangan bagikan kode ini kepada siapapun.\n\n" + . "_PT Tunggal Griya Sakinah_"; + + $sent = WhatsappService::send($telepon, $message); + + if (!$sent) { + return back() + ->withInput() + ->with('error', 'Gagal mengirim OTP via WhatsApp. Pastikan nomor aktif & coba lagi.'); + } + + session([ + 'reset_email' => $user->email, + 'otp_method' => 'whatsapp', + 'reset_telepon' => $telepon, + ]); + + $maskedPhone = $this->maskPhone($telepon); + return redirect()->route('password.otp') + ->with('success', "OTP berhasil dikirim ke WhatsApp {$maskedPhone}"); + + } else { + // Kirim via Email + Mail::to($user->email)->send(new OtpMail($otp)); + + session([ + 'reset_email' => $user->email, + 'otp_method' => 'email', + 'reset_telepon' => null, + ]); + + $maskedEmail = $this->maskEmail($user->email); + return redirect()->route('password.otp') + ->with('success', "OTP berhasil dikirim ke email {$maskedEmail}"); + } +} diff --git a/.history/app/Http/Controllers/AuthController_20260524212631.php b/.history/app/Http/Controllers/AuthController_20260524212631.php new file mode 100644 index 0000000..06347b9 --- /dev/null +++ b/.history/app/Http/Controllers/AuthController_20260524212631.php @@ -0,0 +1,287 @@ +validate([ + 'login' => 'required', + 'password' => 'required' + ]); + + $login = $request->login; + $field = filter_var($login, FILTER_VALIDATE_EMAIL) ? 'email' : 'username'; + + if (Auth::attempt([$field => $login, 'password' => $request->password])) { + $request->session()->regenerate(); + + /** @var \App\Models\User $user */ + $user = Auth::user(); + + return match($user->role) { + 'admin' => redirect('/admin/dashboard'), + 'rt' => redirect('/rt/dashboard'), + default => redirect('/user/home'), + }; + } + + return back()->with('error', 'Login gagal!'); + } + + // ================= REGISTER ================= + + public function register() + { + return view('auth.register'); + } + + public function prosesRegister(Request $request) + { + $request->validate([ + 'name' => 'required', + 'username' => 'required|unique:users,username', + 'email' => 'required|email|unique:users,email', + 'password' => 'required|min:6', + ]); + + User::create([ + 'name' => $request->name, + 'username' => $request->username, + 'email' => $request->email, + 'password' => Hash::make($request->password), + 'role' => 'user' + ]); + + return redirect('/login')->with('success', 'Register berhasil'); + } + + // ================= LOGOUT ================= + + public function logout(Request $request) + { + Auth::logout(); + $request->session()->invalidate(); + $request->session()->regenerateToken(); + return redirect('/login'); + } + + // ================= FORGOT PASSWORD ================= + + public function forgotForm() + { + return view('auth.forgot'); + } + + public function sendOtp(Request $request) + { + $request->validate([ + 'email' => 'required|email', + 'otp_via' => 'required|in:email,whatsapp', + ]); + + $user = User::where('email', $request->email)->first(); + + if (!$user) { + return back() + ->withInput() + ->with('error', 'Email tidak ditemukan.'); + } + + $otpVia = $request->input('otp_via'); + $telepon = null; + + // ✅ Ambil nomor langsung dari kolom `phone` di tabel users + if ($otpVia === 'whatsapp') { + if (empty($user->phone)) { + return back() + ->withInput() + ->with('error', 'Nomor WhatsApp belum terdaftar di akun ini. Silakan gunakan metode Email.'); + } + + $telepon = $user->phone; + } + + // Generate OTP 6 digit + $otp = rand(100000, 999999); + + $user->otp_code = $otp; + $user->otp_expired = now()->addMinutes(5); + $user->save(); + + session([ + 'reset_email' => $user->email, + 'otp_method' => $otpVia, + 'reset_telepon' => $telepon, + ]); + + if ($otpVia === 'whatsapp') { + $message = "🔐 *GREEN VIEW - Reset Password*\n\n" + . "Kode OTP Anda: *{$otp}*\n\n" + . "Kode berlaku selama *5 menit*.\n" + . "Jangan bagikan kode ini kepada siapapun.\n\n" + . "_PT Tunggal Griya Sakinah_"; + + $sent = WhatsappService::send($telepon, $message); + + if (!$sent) { + return back() + ->withInput() + ->with('error', 'Gagal mengirim OTP via WhatsApp. Coba metode Email.'); + } + + $maskedPhone = $this->maskPhone($telepon); + return redirect()->route('password.otp') + ->with('success', "OTP berhasil dikirim ke WhatsApp {$maskedPhone}"); + } else { + Mail::to($user->email)->send(new OtpMail($otp)); + + $maskedEmail = $this->maskEmail($user->email); + return redirect()->route('password.otp') + ->with('success', "OTP berhasil dikirim ke email {$maskedEmail}"); + } + } + + // ================= OTP ================= + + public function otpForm() + { + if (!session('reset_email')) { + return redirect()->route('password.forgot'); + } + return view('auth.otp'); + } + + public function verifyOtp(Request $request) + { + $request->validate([ + 'otp' => 'required|digits:6' + ]); + + $user = User::where('email', session('reset_email'))->first(); + + if (!$user) { + return redirect()->route('password.forgot') + ->with('error', 'Sesi habis, silakan ulangi.'); + } + + if ($user->otp_code != $request->otp) { + return back()->with('error', 'Kode OTP salah.'); + } + + if (Carbon::now()->gt($user->otp_expired)) { + return back()->with('error', 'Kode OTP sudah expired. Minta ulang kode baru.'); + } + + session(['otp_verified' => true]); + + return redirect()->route('password.reset'); + } + + // Kirim ulang OTP + public function resendOtp(Request $request) + { + $email = session('reset_email'); + $method = session('otp_method', 'email'); + $telepon = session('reset_telepon'); + + if (!$email) { + return redirect()->route('password.forgot'); + } + + $user = User::where('email', $email)->first(); + if (!$user) { + return redirect()->route('password.forgot'); + } + + $otp = rand(100000, 999999); + $user->otp_code = $otp; + $user->otp_expired = now()->addMinutes(5); + $user->save(); + + if ($method === 'whatsapp' && !empty($telepon)) { + $message = "🔐 *GREEN VIEW - Reset Password*\n\n" + . "Kode OTP baru Anda: *{$otp}*\n\n" + . "Kode berlaku selama *5 menit*.\n" + . "Jangan bagikan kode ini kepada siapapun.\n\n" + . "_PT Tunggal Griya Sakinah_"; + + $sent = WhatsappService::send($telepon, $message); + + if ($sent) { + return back()->with('success', 'OTP baru dikirim via WhatsApp.'); + } + + Mail::to($user->email)->send(new OtpMail($otp)); + return back()->with('success', 'WhatsApp gagal, OTP dikirim via Email.'); + } else { + Mail::to($user->email)->send(new OtpMail($otp)); + return back()->with('success', 'OTP baru dikirim via Email.'); + } + } + + // ================= RESET PASSWORD ================= + + public function resetForm() + { + if (!session('reset_email') || !session('otp_verified')) { + return redirect()->route('password.forgot'); + } + return view('auth.reset'); + } + + public function resetPassword(Request $request) + { + $request->validate([ + 'password' => 'required|min:6|confirmed' + ]); + + $user = User::where('email', session('reset_email'))->first(); + + if (!$user) { + return redirect()->route('password.forgot'); + } + + $user->password = Hash::make($request->password); + $user->otp_code = null; + $user->otp_expired = null; + $user->save(); + + session()->forget(['reset_email', 'otp_method', 'otp_verified', 'reset_telepon']); + + return redirect('/login')->with('success', 'Password berhasil direset! Silakan login.'); + } + + // ================= HELPERS ================= + + private function maskEmail(string $email): string + { + [$local, $domain] = explode('@', $email); + $masked = substr($local, 0, 2) . str_repeat('*', max(strlen($local) - 2, 3)); + return $masked . '@' . $domain; + } + + private function maskPhone(string $phone): string + { + $phone = WhatsappService::normalizePhone($phone); + return substr($phone, 0, 4) . str_repeat('*', strlen($phone) - 7) . substr($phone, -3); + } +} diff --git a/.history/app/Http/Controllers/AuthController_20260524212644.php b/.history/app/Http/Controllers/AuthController_20260524212644.php new file mode 100644 index 0000000..06347b9 --- /dev/null +++ b/.history/app/Http/Controllers/AuthController_20260524212644.php @@ -0,0 +1,287 @@ +validate([ + 'login' => 'required', + 'password' => 'required' + ]); + + $login = $request->login; + $field = filter_var($login, FILTER_VALIDATE_EMAIL) ? 'email' : 'username'; + + if (Auth::attempt([$field => $login, 'password' => $request->password])) { + $request->session()->regenerate(); + + /** @var \App\Models\User $user */ + $user = Auth::user(); + + return match($user->role) { + 'admin' => redirect('/admin/dashboard'), + 'rt' => redirect('/rt/dashboard'), + default => redirect('/user/home'), + }; + } + + return back()->with('error', 'Login gagal!'); + } + + // ================= REGISTER ================= + + public function register() + { + return view('auth.register'); + } + + public function prosesRegister(Request $request) + { + $request->validate([ + 'name' => 'required', + 'username' => 'required|unique:users,username', + 'email' => 'required|email|unique:users,email', + 'password' => 'required|min:6', + ]); + + User::create([ + 'name' => $request->name, + 'username' => $request->username, + 'email' => $request->email, + 'password' => Hash::make($request->password), + 'role' => 'user' + ]); + + return redirect('/login')->with('success', 'Register berhasil'); + } + + // ================= LOGOUT ================= + + public function logout(Request $request) + { + Auth::logout(); + $request->session()->invalidate(); + $request->session()->regenerateToken(); + return redirect('/login'); + } + + // ================= FORGOT PASSWORD ================= + + public function forgotForm() + { + return view('auth.forgot'); + } + + public function sendOtp(Request $request) + { + $request->validate([ + 'email' => 'required|email', + 'otp_via' => 'required|in:email,whatsapp', + ]); + + $user = User::where('email', $request->email)->first(); + + if (!$user) { + return back() + ->withInput() + ->with('error', 'Email tidak ditemukan.'); + } + + $otpVia = $request->input('otp_via'); + $telepon = null; + + // ✅ Ambil nomor langsung dari kolom `phone` di tabel users + if ($otpVia === 'whatsapp') { + if (empty($user->phone)) { + return back() + ->withInput() + ->with('error', 'Nomor WhatsApp belum terdaftar di akun ini. Silakan gunakan metode Email.'); + } + + $telepon = $user->phone; + } + + // Generate OTP 6 digit + $otp = rand(100000, 999999); + + $user->otp_code = $otp; + $user->otp_expired = now()->addMinutes(5); + $user->save(); + + session([ + 'reset_email' => $user->email, + 'otp_method' => $otpVia, + 'reset_telepon' => $telepon, + ]); + + if ($otpVia === 'whatsapp') { + $message = "🔐 *GREEN VIEW - Reset Password*\n\n" + . "Kode OTP Anda: *{$otp}*\n\n" + . "Kode berlaku selama *5 menit*.\n" + . "Jangan bagikan kode ini kepada siapapun.\n\n" + . "_PT Tunggal Griya Sakinah_"; + + $sent = WhatsappService::send($telepon, $message); + + if (!$sent) { + return back() + ->withInput() + ->with('error', 'Gagal mengirim OTP via WhatsApp. Coba metode Email.'); + } + + $maskedPhone = $this->maskPhone($telepon); + return redirect()->route('password.otp') + ->with('success', "OTP berhasil dikirim ke WhatsApp {$maskedPhone}"); + } else { + Mail::to($user->email)->send(new OtpMail($otp)); + + $maskedEmail = $this->maskEmail($user->email); + return redirect()->route('password.otp') + ->with('success', "OTP berhasil dikirim ke email {$maskedEmail}"); + } + } + + // ================= OTP ================= + + public function otpForm() + { + if (!session('reset_email')) { + return redirect()->route('password.forgot'); + } + return view('auth.otp'); + } + + public function verifyOtp(Request $request) + { + $request->validate([ + 'otp' => 'required|digits:6' + ]); + + $user = User::where('email', session('reset_email'))->first(); + + if (!$user) { + return redirect()->route('password.forgot') + ->with('error', 'Sesi habis, silakan ulangi.'); + } + + if ($user->otp_code != $request->otp) { + return back()->with('error', 'Kode OTP salah.'); + } + + if (Carbon::now()->gt($user->otp_expired)) { + return back()->with('error', 'Kode OTP sudah expired. Minta ulang kode baru.'); + } + + session(['otp_verified' => true]); + + return redirect()->route('password.reset'); + } + + // Kirim ulang OTP + public function resendOtp(Request $request) + { + $email = session('reset_email'); + $method = session('otp_method', 'email'); + $telepon = session('reset_telepon'); + + if (!$email) { + return redirect()->route('password.forgot'); + } + + $user = User::where('email', $email)->first(); + if (!$user) { + return redirect()->route('password.forgot'); + } + + $otp = rand(100000, 999999); + $user->otp_code = $otp; + $user->otp_expired = now()->addMinutes(5); + $user->save(); + + if ($method === 'whatsapp' && !empty($telepon)) { + $message = "🔐 *GREEN VIEW - Reset Password*\n\n" + . "Kode OTP baru Anda: *{$otp}*\n\n" + . "Kode berlaku selama *5 menit*.\n" + . "Jangan bagikan kode ini kepada siapapun.\n\n" + . "_PT Tunggal Griya Sakinah_"; + + $sent = WhatsappService::send($telepon, $message); + + if ($sent) { + return back()->with('success', 'OTP baru dikirim via WhatsApp.'); + } + + Mail::to($user->email)->send(new OtpMail($otp)); + return back()->with('success', 'WhatsApp gagal, OTP dikirim via Email.'); + } else { + Mail::to($user->email)->send(new OtpMail($otp)); + return back()->with('success', 'OTP baru dikirim via Email.'); + } + } + + // ================= RESET PASSWORD ================= + + public function resetForm() + { + if (!session('reset_email') || !session('otp_verified')) { + return redirect()->route('password.forgot'); + } + return view('auth.reset'); + } + + public function resetPassword(Request $request) + { + $request->validate([ + 'password' => 'required|min:6|confirmed' + ]); + + $user = User::where('email', session('reset_email'))->first(); + + if (!$user) { + return redirect()->route('password.forgot'); + } + + $user->password = Hash::make($request->password); + $user->otp_code = null; + $user->otp_expired = null; + $user->save(); + + session()->forget(['reset_email', 'otp_method', 'otp_verified', 'reset_telepon']); + + return redirect('/login')->with('success', 'Password berhasil direset! Silakan login.'); + } + + // ================= HELPERS ================= + + private function maskEmail(string $email): string + { + [$local, $domain] = explode('@', $email); + $masked = substr($local, 0, 2) . str_repeat('*', max(strlen($local) - 2, 3)); + return $masked . '@' . $domain; + } + + private function maskPhone(string $phone): string + { + $phone = WhatsappService::normalizePhone($phone); + return substr($phone, 0, 4) . str_repeat('*', strlen($phone) - 7) . substr($phone, -3); + } +} diff --git a/.history/app/Http/Controllers/AuthController_20260524212651.php b/.history/app/Http/Controllers/AuthController_20260524212651.php new file mode 100644 index 0000000..d07ef09 --- /dev/null +++ b/.history/app/Http/Controllers/AuthController_20260524212651.php @@ -0,0 +1,290 @@ +validate([ + 'login' => 'required', + 'password' => 'required' + ]); + + $login = $request->login; + $field = filter_var($login, FILTER_VALIDATE_EMAIL) ? 'email' : 'username'; + + if (Auth::attempt([$field => $login, 'password' => $request->password])) { + $request->session()->regenerate(); + + /** @var \App\Models\User $user */ + $user = Auth::user(); + + return match($user->role) { + 'admin' => redirect('/admin/dashboard'), + 'rt' => redirect('/rt/dashboard'), + default => redirect('/user/home'), + }; + } + + return back()->with('error', 'Login gagal!'); + } + + // ================= REGISTER ================= + + public function register() + { + return view('auth.register'); + } + + public function prosesRegister(Request $request) + { + $request->validate([ + 'name' => 'required', + 'username' => 'required|unique:users,username', + 'email' => 'required|email|unique:users,email', + 'password' => 'required|min:6', + ]); + + User::create([ + 'name' => $request->name, + 'username' => $request->username, + 'email' => $request->email, + 'password' => Hash::make($request->password), + 'role' => 'user' + ]); + + return redirect('/login')->with('success', 'Register berhasil'); + } + + // ================= LOGOUT ================= + + public function logout(Request $request) + { + Auth::logout(); + $request->session()->invalidate(); + $request->session()->regenerateToken(); + return redirect('/login'); + } + + // ================= FORGOT PASSWORD ================= + + public function forgotForm() + { + return view('auth.forgot'); + } + + public function sendOtp(Request $request) + { + $request->validate([ + 'email' => 'required|email', + 'otp_via' => 'required|in:email,whatsapp', + ]); + + $user = User::where('email', $request->email)->first(); + + if (!$user) { + return back() + ->withInput() + ->with('error', 'Email tidak ditemukan.'); + } + + $otpVia = $request->input('otp_via'); + $telepon = null; + + // Ambil nomor dari tabel penghuni berdasarkan user_id + if ($otpVia === 'whatsapp') { + $penghuni = Penghuni::where('user_id', $user->id)->first(); + + if (!$penghuni || empty($penghuni->telepon)) { + return back() + ->withInput() + ->with('error', 'Nomor WhatsApp tidak ditemukan di data penghuni. Silakan gunakan metode Email.'); + } + + $telepon = $penghuni->telepon; + } + + // Generate OTP 6 digit + $otp = rand(100000, 999999); + + $user->otp_code = $otp; + $user->otp_expired = now()->addMinutes(5); + $user->save(); + + session([ + 'reset_email' => $user->email, + 'otp_method' => $otpVia, + 'reset_telepon' => $telepon, + ]); + + if ($otpVia === 'whatsapp') { + $message = "🔐 *GREEN VIEW - Reset Password*\n\n" + . "Kode OTP Anda: *{$otp}*\n\n" + . "Kode berlaku selama *5 menit*.\n" + . "Jangan bagikan kode ini kepada siapapun.\n\n" + . "_PT Tunggal Griya Sakinah_"; + + $sent = WhatsappService::send($telepon, $message); + + if (!$sent) { + return back() + ->withInput() + ->with('error', 'Gagal mengirim OTP via WhatsApp. Coba metode Email.'); + } + + $maskedPhone = $this->maskPhone($telepon); + return redirect()->route('password.otp') + ->with('success', "OTP berhasil dikirim ke WhatsApp {$maskedPhone}"); + } else { + Mail::to($user->email)->send(new OtpMail($otp)); + + $maskedEmail = $this->maskEmail($user->email); + return redirect()->route('password.otp') + ->with('success', "OTP berhasil dikirim ke email {$maskedEmail}"); + } + } + + // ================= OTP ================= + + public function otpForm() + { + if (!session('reset_email')) { + return redirect()->route('password.forgot'); + } + return view('auth.otp'); + } + + public function verifyOtp(Request $request) + { + $request->validate([ + 'otp' => 'required|digits:6' + ]); + + $user = User::where('email', session('reset_email'))->first(); + + if (!$user) { + return redirect()->route('password.forgot') + ->with('error', 'Sesi habis, silakan ulangi.'); + } + + if ($user->otp_code != $request->otp) { + return back()->with('error', 'Kode OTP salah.'); + } + + if (Carbon::now()->gt($user->otp_expired)) { + return back()->with('error', 'Kode OTP sudah expired. Minta ulang kode baru.'); + } + + session(['otp_verified' => true]); + + return redirect()->route('password.reset'); + } + + // Kirim ulang OTP + public function resendOtp(Request $request) + { + $email = session('reset_email'); + $method = session('otp_method', 'email'); + $telepon = session('reset_telepon'); + + if (!$email) { + return redirect()->route('password.forgot'); + } + + $user = User::where('email', $email)->first(); + if (!$user) { + return redirect()->route('password.forgot'); + } + + $otp = rand(100000, 999999); + $user->otp_code = $otp; + $user->otp_expired = now()->addMinutes(5); + $user->save(); + + if ($method === 'whatsapp' && !empty($telepon)) { + $message = "🔐 *GREEN VIEW - Reset Password*\n\n" + . "Kode OTP baru Anda: *{$otp}*\n\n" + . "Kode berlaku selama *5 menit*.\n" + . "Jangan bagikan kode ini kepada siapapun.\n\n" + . "_PT Tunggal Griya Sakinah_"; + + $sent = WhatsappService::send($telepon, $message); + + if ($sent) { + return back()->with('success', 'OTP baru dikirim via WhatsApp.'); + } + + // Fallback ke email jika WA gagal + Mail::to($user->email)->send(new OtpMail($otp)); + return back()->with('success', 'WhatsApp gagal, OTP dikirim via Email.'); + } else { + Mail::to($user->email)->send(new OtpMail($otp)); + return back()->with('success', 'OTP baru dikirim via Email.'); + } + } + + // ================= RESET PASSWORD ================= + + public function resetForm() + { + if (!session('reset_email') || !session('otp_verified')) { + return redirect()->route('password.forgot'); + } + return view('auth.reset'); + } + + public function resetPassword(Request $request) + { + $request->validate([ + 'password' => 'required|min:6|confirmed' + ]); + + $user = User::where('email', session('reset_email'))->first(); + + if (!$user) { + return redirect()->route('password.forgot'); + } + + $user->password = Hash::make($request->password); + $user->otp_code = null; + $user->otp_expired = null; + $user->save(); + + session()->forget(['reset_email', 'otp_method', 'otp_verified', 'reset_telepon']); + + return redirect('/login')->with('success', 'Password berhasil direset! Silakan login.'); + } + + // ================= HELPERS ================= + + private function maskEmail(string $email): string + { + [$local, $domain] = explode('@', $email); + $masked = substr($local, 0, 2) . str_repeat('*', max(strlen($local) - 2, 3)); + return $masked . '@' . $domain; + } + + private function maskPhone(string $phone): string + { + $phone = WhatsappService::normalizePhone($phone); + return substr($phone, 0, 4) . str_repeat('*', strlen($phone) - 7) . substr($phone, -3); + } +} diff --git a/.history/app/Http/Controllers/AuthController_20260524212653.php b/.history/app/Http/Controllers/AuthController_20260524212653.php new file mode 100644 index 0000000..06347b9 --- /dev/null +++ b/.history/app/Http/Controllers/AuthController_20260524212653.php @@ -0,0 +1,287 @@ +validate([ + 'login' => 'required', + 'password' => 'required' + ]); + + $login = $request->login; + $field = filter_var($login, FILTER_VALIDATE_EMAIL) ? 'email' : 'username'; + + if (Auth::attempt([$field => $login, 'password' => $request->password])) { + $request->session()->regenerate(); + + /** @var \App\Models\User $user */ + $user = Auth::user(); + + return match($user->role) { + 'admin' => redirect('/admin/dashboard'), + 'rt' => redirect('/rt/dashboard'), + default => redirect('/user/home'), + }; + } + + return back()->with('error', 'Login gagal!'); + } + + // ================= REGISTER ================= + + public function register() + { + return view('auth.register'); + } + + public function prosesRegister(Request $request) + { + $request->validate([ + 'name' => 'required', + 'username' => 'required|unique:users,username', + 'email' => 'required|email|unique:users,email', + 'password' => 'required|min:6', + ]); + + User::create([ + 'name' => $request->name, + 'username' => $request->username, + 'email' => $request->email, + 'password' => Hash::make($request->password), + 'role' => 'user' + ]); + + return redirect('/login')->with('success', 'Register berhasil'); + } + + // ================= LOGOUT ================= + + public function logout(Request $request) + { + Auth::logout(); + $request->session()->invalidate(); + $request->session()->regenerateToken(); + return redirect('/login'); + } + + // ================= FORGOT PASSWORD ================= + + public function forgotForm() + { + return view('auth.forgot'); + } + + public function sendOtp(Request $request) + { + $request->validate([ + 'email' => 'required|email', + 'otp_via' => 'required|in:email,whatsapp', + ]); + + $user = User::where('email', $request->email)->first(); + + if (!$user) { + return back() + ->withInput() + ->with('error', 'Email tidak ditemukan.'); + } + + $otpVia = $request->input('otp_via'); + $telepon = null; + + // ✅ Ambil nomor langsung dari kolom `phone` di tabel users + if ($otpVia === 'whatsapp') { + if (empty($user->phone)) { + return back() + ->withInput() + ->with('error', 'Nomor WhatsApp belum terdaftar di akun ini. Silakan gunakan metode Email.'); + } + + $telepon = $user->phone; + } + + // Generate OTP 6 digit + $otp = rand(100000, 999999); + + $user->otp_code = $otp; + $user->otp_expired = now()->addMinutes(5); + $user->save(); + + session([ + 'reset_email' => $user->email, + 'otp_method' => $otpVia, + 'reset_telepon' => $telepon, + ]); + + if ($otpVia === 'whatsapp') { + $message = "🔐 *GREEN VIEW - Reset Password*\n\n" + . "Kode OTP Anda: *{$otp}*\n\n" + . "Kode berlaku selama *5 menit*.\n" + . "Jangan bagikan kode ini kepada siapapun.\n\n" + . "_PT Tunggal Griya Sakinah_"; + + $sent = WhatsappService::send($telepon, $message); + + if (!$sent) { + return back() + ->withInput() + ->with('error', 'Gagal mengirim OTP via WhatsApp. Coba metode Email.'); + } + + $maskedPhone = $this->maskPhone($telepon); + return redirect()->route('password.otp') + ->with('success', "OTP berhasil dikirim ke WhatsApp {$maskedPhone}"); + } else { + Mail::to($user->email)->send(new OtpMail($otp)); + + $maskedEmail = $this->maskEmail($user->email); + return redirect()->route('password.otp') + ->with('success', "OTP berhasil dikirim ke email {$maskedEmail}"); + } + } + + // ================= OTP ================= + + public function otpForm() + { + if (!session('reset_email')) { + return redirect()->route('password.forgot'); + } + return view('auth.otp'); + } + + public function verifyOtp(Request $request) + { + $request->validate([ + 'otp' => 'required|digits:6' + ]); + + $user = User::where('email', session('reset_email'))->first(); + + if (!$user) { + return redirect()->route('password.forgot') + ->with('error', 'Sesi habis, silakan ulangi.'); + } + + if ($user->otp_code != $request->otp) { + return back()->with('error', 'Kode OTP salah.'); + } + + if (Carbon::now()->gt($user->otp_expired)) { + return back()->with('error', 'Kode OTP sudah expired. Minta ulang kode baru.'); + } + + session(['otp_verified' => true]); + + return redirect()->route('password.reset'); + } + + // Kirim ulang OTP + public function resendOtp(Request $request) + { + $email = session('reset_email'); + $method = session('otp_method', 'email'); + $telepon = session('reset_telepon'); + + if (!$email) { + return redirect()->route('password.forgot'); + } + + $user = User::where('email', $email)->first(); + if (!$user) { + return redirect()->route('password.forgot'); + } + + $otp = rand(100000, 999999); + $user->otp_code = $otp; + $user->otp_expired = now()->addMinutes(5); + $user->save(); + + if ($method === 'whatsapp' && !empty($telepon)) { + $message = "🔐 *GREEN VIEW - Reset Password*\n\n" + . "Kode OTP baru Anda: *{$otp}*\n\n" + . "Kode berlaku selama *5 menit*.\n" + . "Jangan bagikan kode ini kepada siapapun.\n\n" + . "_PT Tunggal Griya Sakinah_"; + + $sent = WhatsappService::send($telepon, $message); + + if ($sent) { + return back()->with('success', 'OTP baru dikirim via WhatsApp.'); + } + + Mail::to($user->email)->send(new OtpMail($otp)); + return back()->with('success', 'WhatsApp gagal, OTP dikirim via Email.'); + } else { + Mail::to($user->email)->send(new OtpMail($otp)); + return back()->with('success', 'OTP baru dikirim via Email.'); + } + } + + // ================= RESET PASSWORD ================= + + public function resetForm() + { + if (!session('reset_email') || !session('otp_verified')) { + return redirect()->route('password.forgot'); + } + return view('auth.reset'); + } + + public function resetPassword(Request $request) + { + $request->validate([ + 'password' => 'required|min:6|confirmed' + ]); + + $user = User::where('email', session('reset_email'))->first(); + + if (!$user) { + return redirect()->route('password.forgot'); + } + + $user->password = Hash::make($request->password); + $user->otp_code = null; + $user->otp_expired = null; + $user->save(); + + session()->forget(['reset_email', 'otp_method', 'otp_verified', 'reset_telepon']); + + return redirect('/login')->with('success', 'Password berhasil direset! Silakan login.'); + } + + // ================= HELPERS ================= + + private function maskEmail(string $email): string + { + [$local, $domain] = explode('@', $email); + $masked = substr($local, 0, 2) . str_repeat('*', max(strlen($local) - 2, 3)); + return $masked . '@' . $domain; + } + + private function maskPhone(string $phone): string + { + $phone = WhatsappService::normalizePhone($phone); + return substr($phone, 0, 4) . str_repeat('*', strlen($phone) - 7) . substr($phone, -3); + } +} diff --git a/.history/app/Http/Controllers/AuthController_20260524212713.php b/.history/app/Http/Controllers/AuthController_20260524212713.php new file mode 100644 index 0000000..2a2000c --- /dev/null +++ b/.history/app/Http/Controllers/AuthController_20260524212713.php @@ -0,0 +1,290 @@ +validate([ + 'login' => 'required', + 'password' => 'required' + ]); + + $login = $request->login; + $field = filter_var($login, FILTER_VALIDATE_EMAIL) ? 'email' : 'username'; + + if (Auth::attempt([$field => $login, 'password' => $request->password])) { + $request->session()->regenerate(); + + /** @var \App\Models\User $user */ + $user = Auth::user(); + + return match($user->role) { + 'admin' => redirect('/admin/dashboard'), + 'rt' => redirect('/rt/dashboard'), + default => redirect('/user/home'), + }; + } + + return back()->with('error', 'Login gagal!'); + } + + // ================= REGISTER ================= + + public function register() + { + return view('auth.register'); + } + + public function prosesRegister(Request $request) + { + $request->validate([ + 'name' => 'required', + 'username' => 'required|unique:users,username', + 'email' => 'required|email|unique:users,email', + 'password' => 'required|min:6', + ]); + + User::create([ + 'name' => $request->name, + 'username' => $request->username, + 'email' => $request->email, + 'password' => Hash::make($request->password), + 'role' => 'user' + ]); + + return redirect('/login')->with('success', 'Register berhasil'); + } + + // ================= LOGOUT ================= + + public function logout(Request $request) + { + Auth::logout(); + $request->session()->invalidate(); + $request->session()->regenerateToken(); + return redirect('/login'); + } + + // ================= FORGOT PASSWORD ================= + + public function forgotForm() + { + return view('auth.forgot'); + } + + public function sendOtp(Request $request) +{ + $request->validate([ + 'email' => 'required|email', + 'otp_via' => 'required|in:email,whatsapp', + // ✅ Wajib isi nomor jika pilih WhatsApp + 'phone' => 'required_if:otp_via,whatsapp', + ], [ + 'phone.required_if' => 'Nomor WhatsApp wajib diisi jika memilih metode WhatsApp.', + ]); + + $user = User::where('email', $request->email)->first(); + + if (!$user) { + return back() + ->withInput() + ->with('error', 'Email tidak ditemukan.'); + } + + $otpVia = $request->input('otp_via'); + + // Generate OTP 6 digit + $otp = rand(100000, 999999); + $user->otp_code = $otp; + $user->otp_expired = now()->addMinutes(5); + $user->save(); + + if ($otpVia === 'whatsapp') { + // ✅ Gunakan nomor dari input form, bukan dari DB + $telepon = $request->input('phone'); + $telepon = WhatsappService::normalizePhone($telepon); + + $message = "🔐 *GREEN VIEW - Reset Password*\n\n" + . "Kode OTP Anda: *{$otp}*\n\n" + . "Kode berlaku selama *5 menit*.\n" + . "Jangan bagikan kode ini kepada siapapun.\n\n" + . "_PT Tunggal Griya Sakinah_"; + + $sent = WhatsappService::send($telepon, $message); + + if (!$sent) { + return back() + ->withInput() + ->with('error', 'Gagal mengirim OTP via WhatsApp. Pastikan nomor aktif & coba lagi.'); + } + + session([ + 'reset_email' => $user->email, + 'otp_method' => 'whatsapp', + 'reset_telepon' => $telepon, + ]); + + $maskedPhone = $this->maskPhone($telepon); + return redirect()->route('password.otp') + ->with('success', "OTP berhasil dikirim ke WhatsApp {$maskedPhone}"); + + } else { + // Kirim via Email + Mail::to($user->email)->send(new OtpMail($otp)); + + session([ + 'reset_email' => $user->email, + 'otp_method' => 'email', + 'reset_telepon' => null, + ]); + + $maskedEmail = $this->maskEmail($user->email); + return redirect()->route('password.otp') + ->with('success', "OTP berhasil dikirim ke email {$maskedEmail}"); + } +} + + // ================= OTP ================= + + public function otpForm() + { + if (!session('reset_email')) { + return redirect()->route('password.forgot'); + } + return view('auth.otp'); + } + + public function verifyOtp(Request $request) + { + $request->validate([ + 'otp' => 'required|digits:6' + ]); + + $user = User::where('email', session('reset_email'))->first(); + + if (!$user) { + return redirect()->route('password.forgot') + ->with('error', 'Sesi habis, silakan ulangi.'); + } + + if ($user->otp_code != $request->otp) { + return back()->with('error', 'Kode OTP salah.'); + } + + if (Carbon::now()->gt($user->otp_expired)) { + return back()->with('error', 'Kode OTP sudah expired. Minta ulang kode baru.'); + } + + session(['otp_verified' => true]); + + return redirect()->route('password.reset'); + } + + // Kirim ulang OTP + public function resendOtp(Request $request) + { + $email = session('reset_email'); + $method = session('otp_method', 'email'); + $telepon = session('reset_telepon'); + + if (!$email) { + return redirect()->route('password.forgot'); + } + + $user = User::where('email', $email)->first(); + if (!$user) { + return redirect()->route('password.forgot'); + } + + $otp = rand(100000, 999999); + $user->otp_code = $otp; + $user->otp_expired = now()->addMinutes(5); + $user->save(); + + if ($method === 'whatsapp' && !empty($telepon)) { + $message = "🔐 *GREEN VIEW - Reset Password*\n\n" + . "Kode OTP baru Anda: *{$otp}*\n\n" + . "Kode berlaku selama *5 menit*.\n" + . "Jangan bagikan kode ini kepada siapapun.\n\n" + . "_PT Tunggal Griya Sakinah_"; + + $sent = WhatsappService::send($telepon, $message); + + if ($sent) { + return back()->with('success', 'OTP baru dikirim via WhatsApp.'); + } + + Mail::to($user->email)->send(new OtpMail($otp)); + return back()->with('success', 'WhatsApp gagal, OTP dikirim via Email.'); + } else { + Mail::to($user->email)->send(new OtpMail($otp)); + return back()->with('success', 'OTP baru dikirim via Email.'); + } + } + + // ================= RESET PASSWORD ================= + + public function resetForm() + { + if (!session('reset_email') || !session('otp_verified')) { + return redirect()->route('password.forgot'); + } + return view('auth.reset'); + } + + public function resetPassword(Request $request) + { + $request->validate([ + 'password' => 'required|min:6|confirmed' + ]); + + $user = User::where('email', session('reset_email'))->first(); + + if (!$user) { + return redirect()->route('password.forgot'); + } + + $user->password = Hash::make($request->password); + $user->otp_code = null; + $user->otp_expired = null; + $user->save(); + + session()->forget(['reset_email', 'otp_method', 'otp_verified', 'reset_telepon']); + + return redirect('/login')->with('success', 'Password berhasil direset! Silakan login.'); + } + + // ================= HELPERS ================= + + private function maskEmail(string $email): string + { + [$local, $domain] = explode('@', $email); + $masked = substr($local, 0, 2) . str_repeat('*', max(strlen($local) - 2, 3)); + return $masked . '@' . $domain; + } + + private function maskPhone(string $phone): string + { + $phone = WhatsappService::normalizePhone($phone); + return substr($phone, 0, 4) . str_repeat('*', strlen($phone) - 7) . substr($phone, -3); + } +} diff --git a/.history/app/Http/Controllers/AuthController_20260619112926.php b/.history/app/Http/Controllers/AuthController_20260619112926.php new file mode 100644 index 0000000..8729666 --- /dev/null +++ b/.history/app/Http/Controllers/AuthController_20260619112926.php @@ -0,0 +1,291 @@ +validate([ + 'login' => 'required', + 'password' => 'required' + ]); + + $login = $request->login; + $field = filter_var($login, FILTER_VALIDATE_EMAIL) ? 'email' : 'username'; + + if (Auth::attempt([$field => $login, 'password' => $request->password])) { + $request->session()->regenerate(); + + /** @var \App\Models\User $user */ + $user = Auth::user(); + + return match($user->role) { + 'admin' => redirect('/admin/dashboard'), + 'rt' => redirect('/rt/dashboard'), + 'bendahara' => redirect('/bendahara/iuran'), + default => redirect('/user/home'), + }; + } + + return back()->with('error', 'Login gagal!'); + } + + // ================= REGISTER ================= + + public function register() + { + return view('auth.register'); + } + + public function prosesRegister(Request $request) + { + $request->validate([ + 'name' => 'required', + 'username' => 'required|unique:users,username', + 'email' => 'required|email|unique:users,email', + 'password' => 'required|min:6', + ]); + + User::create([ + 'name' => $request->name, + 'username' => $request->username, + 'email' => $request->email, + 'password' => Hash::make($request->password), + 'role' => 'user' + ]); + + return redirect('/login')->with('success', 'Register berhasil'); + } + + // ================= LOGOUT ================= + + public function logout(Request $request) + { + Auth::logout(); + $request->session()->invalidate(); + $request->session()->regenerateToken(); + return redirect('/login'); + } + + // ================= FORGOT PASSWORD ================= + + public function forgotForm() + { + return view('auth.forgot'); + } + + public function sendOtp(Request $request) +{ + $request->validate([ + 'email' => 'required|email', + 'otp_via' => 'required|in:email,whatsapp', + // ✅ Wajib isi nomor jika pilih WhatsApp + 'phone' => 'required_if:otp_via,whatsapp', + ], [ + 'phone.required_if' => 'Nomor WhatsApp wajib diisi jika memilih metode WhatsApp.', + ]); + + $user = User::where('email', $request->email)->first(); + + if (!$user) { + return back() + ->withInput() + ->with('error', 'Email tidak ditemukan.'); + } + + $otpVia = $request->input('otp_via'); + + // Generate OTP 6 digit + $otp = rand(100000, 999999); + $user->otp_code = $otp; + $user->otp_expired = now()->addMinutes(5); + $user->save(); + + if ($otpVia === 'whatsapp') { + // ✅ Gunakan nomor dari input form, bukan dari DB + $telepon = $request->input('phone'); + $telepon = WhatsappService::normalizePhone($telepon); + + $message = "🔐 *GREEN VIEW - Reset Password*\n\n" + . "Kode OTP Anda: *{$otp}*\n\n" + . "Kode berlaku selama *5 menit*.\n" + . "Jangan bagikan kode ini kepada siapapun.\n\n" + . "_PT Tunggal Griya Sakinah_"; + + $sent = WhatsappService::send($telepon, $message); + + if (!$sent) { + return back() + ->withInput() + ->with('error', 'Gagal mengirim OTP via WhatsApp. Pastikan nomor aktif & coba lagi.'); + } + + session([ + 'reset_email' => $user->email, + 'otp_method' => 'whatsapp', + 'reset_telepon' => $telepon, + ]); + + $maskedPhone = $this->maskPhone($telepon); + return redirect()->route('password.otp') + ->with('success', "OTP berhasil dikirim ke WhatsApp {$maskedPhone}"); + + } else { + // Kirim via Email + Mail::to($user->email)->send(new OtpMail($otp)); + + session([ + 'reset_email' => $user->email, + 'otp_method' => 'email', + 'reset_telepon' => null, + ]); + + $maskedEmail = $this->maskEmail($user->email); + return redirect()->route('password.otp') + ->with('success', "OTP berhasil dikirim ke email {$maskedEmail}"); + } +} + + // ================= OTP ================= + + public function otpForm() + { + if (!session('reset_email')) { + return redirect()->route('password.forgot'); + } + return view('auth.otp'); + } + + public function verifyOtp(Request $request) + { + $request->validate([ + 'otp' => 'required|digits:6' + ]); + + $user = User::where('email', session('reset_email'))->first(); + + if (!$user) { + return redirect()->route('password.forgot') + ->with('error', 'Sesi habis, silakan ulangi.'); + } + + if ($user->otp_code != $request->otp) { + return back()->with('error', 'Kode OTP salah.'); + } + + if (Carbon::now()->gt($user->otp_expired)) { + return back()->with('error', 'Kode OTP sudah expired. Minta ulang kode baru.'); + } + + session(['otp_verified' => true]); + + return redirect()->route('password.reset'); + } + + // Kirim ulang OTP + public function resendOtp(Request $request) + { + $email = session('reset_email'); + $method = session('otp_method', 'email'); + $telepon = session('reset_telepon'); + + if (!$email) { + return redirect()->route('password.forgot'); + } + + $user = User::where('email', $email)->first(); + if (!$user) { + return redirect()->route('password.forgot'); + } + + $otp = rand(100000, 999999); + $user->otp_code = $otp; + $user->otp_expired = now()->addMinutes(5); + $user->save(); + + if ($method === 'whatsapp' && !empty($telepon)) { + $message = "🔐 *GREEN VIEW - Reset Password*\n\n" + . "Kode OTP baru Anda: *{$otp}*\n\n" + . "Kode berlaku selama *5 menit*.\n" + . "Jangan bagikan kode ini kepada siapapun.\n\n" + . "_PT Tunggal Griya Sakinah_"; + + $sent = WhatsappService::send($telepon, $message); + + if ($sent) { + return back()->with('success', 'OTP baru dikirim via WhatsApp.'); + } + + Mail::to($user->email)->send(new OtpMail($otp)); + return back()->with('success', 'WhatsApp gagal, OTP dikirim via Email.'); + } else { + Mail::to($user->email)->send(new OtpMail($otp)); + return back()->with('success', 'OTP baru dikirim via Email.'); + } + } + + // ================= RESET PASSWORD ================= + + public function resetForm() + { + if (!session('reset_email') || !session('otp_verified')) { + return redirect()->route('password.forgot'); + } + return view('auth.reset'); + } + + public function resetPassword(Request $request) + { + $request->validate([ + 'password' => 'required|min:6|confirmed' + ]); + + $user = User::where('email', session('reset_email'))->first(); + + if (!$user) { + return redirect()->route('password.forgot'); + } + + $user->password = Hash::make($request->password); + $user->otp_code = null; + $user->otp_expired = null; + $user->save(); + + session()->forget(['reset_email', 'otp_method', 'otp_verified', 'reset_telepon']); + + return redirect('/login')->with('success', 'Password berhasil direset! Silakan login.'); + } + + // ================= HELPERS ================= + + private function maskEmail(string $email): string + { + [$local, $domain] = explode('@', $email); + $masked = substr($local, 0, 2) . str_repeat('*', max(strlen($local) - 2, 3)); + return $masked . '@' . $domain; + } + + private function maskPhone(string $phone): string + { + $phone = WhatsappService::normalizePhone($phone); + return substr($phone, 0, 4) . str_repeat('*', strlen($phone) - 7) . substr($phone, -3); + } +} diff --git a/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619110719.php b/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619110719.php new file mode 100644 index 0000000..e69de29 diff --git a/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619110726.php b/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619110726.php new file mode 100644 index 0000000..3032455 --- /dev/null +++ b/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619110726.php @@ -0,0 +1,46 @@ +wajib_ganti_password) { + return redirect()->route('bendahara.iuran.index'); + } + + return view('bendahara.ganti-password.form'); + } + + // Proses simpan password baru + public function update(Request $request) + { + $user = Auth::user(); + + $request->validate([ + 'password' => 'required|min:6|confirmed', + ]); + + // Wajib beda dari password default + if (Hash::check($request->password, Hash::make('12345678')) || $request->password === '12345678') { + return back()->withErrors(['password' => 'Password baru tidak boleh sama dengan password default (12345678).']); + } + + $user->update([ + 'password' => Hash::make($request->password), + 'wajib_ganti_password' => false, + ]); + + return redirect()->route('bendahara.iuran.index')->with('success', 'Password berhasil diganti. Selamat datang!'); + } +} diff --git a/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111038.php b/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111038.php new file mode 100644 index 0000000..8951333 --- /dev/null +++ b/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111038.php @@ -0,0 +1,46 @@ +wajib_ganti_password) { + return redirect()->route('bendahara.iuran.index'); + } + + return view('bendahara.ganti-password.form'); + } + + // Proses simpan password baru + public function update(Request $request) + { + $user = Auth::user(); + + $request->validate([ + 'password' => 'required|min:6|confirmed', + ]); + + // Wajib beda dari password default + if ($request->password === '12345678') { + return back()->withErrors(['password' => 'Password baru tidak boleh sama dengan password default (12345678).']); + } + + $user->update([ + 'password' => Hash::make($request->password), + 'wajib_ganti_password' => false, + ]); + + return redirect()->route('bendahara.iuran.index')->with('success', 'Password berhasil diganti. Selamat datang!'); + } +} diff --git a/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111040.php b/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111040.php new file mode 100644 index 0000000..0096dd2 --- /dev/null +++ b/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111040.php @@ -0,0 +1,46 @@ +wajib_ganti_password) { + return redirect()->route('bendahara.iuran.index'); + } + + return view('bendahara.ganti-password.form'); + } + + // Proses simpan password baru + public function update(Request $request) + { + $user = Auth::user(); + + $request->validate([ + 'password' => 'required|min:6|confirmed', + ]); + + // Wajib beda dari password default + if ($request->password === '12345678') { + return back()->withErrors(['password' => 'Password baru tidak boleh sama dengan password default (12345678).']); + } + + $user->update([ + 'password' => Hash::make($request->password), + 'wajib_ganti_password' => false, + ]); + + return redirect()->route('bendahara.iuran.index')->with('success', 'Password berhasil diganti. Selamat datang!'); + } +} diff --git a/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111537.php b/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111537.php new file mode 100644 index 0000000..0096dd2 --- /dev/null +++ b/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111537.php @@ -0,0 +1,46 @@ +wajib_ganti_password) { + return redirect()->route('bendahara.iuran.index'); + } + + return view('bendahara.ganti-password.form'); + } + + // Proses simpan password baru + public function update(Request $request) + { + $user = Auth::user(); + + $request->validate([ + 'password' => 'required|min:6|confirmed', + ]); + + // Wajib beda dari password default + if ($request->password === '12345678') { + return back()->withErrors(['password' => 'Password baru tidak boleh sama dengan password default (12345678).']); + } + + $user->update([ + 'password' => Hash::make($request->password), + 'wajib_ganti_password' => false, + ]); + + return redirect()->route('bendahara.iuran.index')->with('success', 'Password berhasil diganti. Selamat datang!'); + } +} diff --git a/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111552.php b/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111552.php new file mode 100644 index 0000000..2bb4775 --- /dev/null +++ b/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111552.php @@ -0,0 +1,46 @@ +wajib_ganti_password) { + return redirect()->route('bendahara.iuran.index'); + } + + return view('bendahara.ganti-password.form'); + } + + // Proses simpan password baru + public function update(Request $request) + { + $user = Auth::user(); + + $request->validate([ + 'password' => 'required|min:6|confirmed', + ]); + + // Wajib beda dari password default + if ($request->password === '12345678') { + return back()->withErrors(['password' => 'Password baru tidak boleh sama dengan password default (12345678).']); + } + + $user->update([ + 'password' => Hash::make($request->password), + 'wajib_ganti_password' => false, + ]); + + return redirect()->route('bendahara.iuran.index')->with('success', 'Password berhasil diganti. Selamat datang!'); + } +} diff --git a/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111555.php b/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111555.php new file mode 100644 index 0000000..92d1afd --- /dev/null +++ b/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111555.php @@ -0,0 +1,47 @@ +wajib_ganti_password) { + return redirect()->route('bendahara.iuran.index'); + } + + return view('bendahara.ganti-password.form'); + } + + // Proses simpan password baru + public function update(Request $request) + { + $user = Auth::user(); + + $request->validate([ + 'password' => 'required|min:6|confirmed', + ]); + + // Wajib beda dari password default + if ($request->password === '12345678') { + return back()->withErrors(['password' => 'Password baru tidak boleh sama dengan password default (12345678).']); + } + + $user->update([ + 'password' => Hash::make($request->password), + 'wajib_ganti_password' => false, + ]); + + return redirect()->route('bendahara.iuran.index')->with('success', 'Password berhasil diganti. Selamat datang!'); + } +} +kk diff --git a/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111557.php b/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111557.php new file mode 100644 index 0000000..2bb4775 --- /dev/null +++ b/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111557.php @@ -0,0 +1,46 @@ +wajib_ganti_password) { + return redirect()->route('bendahara.iuran.index'); + } + + return view('bendahara.ganti-password.form'); + } + + // Proses simpan password baru + public function update(Request $request) + { + $user = Auth::user(); + + $request->validate([ + 'password' => 'required|min:6|confirmed', + ]); + + // Wajib beda dari password default + if ($request->password === '12345678') { + return back()->withErrors(['password' => 'Password baru tidak boleh sama dengan password default (12345678).']); + } + + $user->update([ + 'password' => Hash::make($request->password), + 'wajib_ganti_password' => false, + ]); + + return redirect()->route('bendahara.iuran.index')->with('success', 'Password berhasil diganti. Selamat datang!'); + } +} diff --git a/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111559.php b/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111559.php new file mode 100644 index 0000000..6879f86 --- /dev/null +++ b/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111559.php @@ -0,0 +1,47 @@ +wajib_ganti_password) { + return redirect()->route('bendahara.iuran.index'); + } + + return view('bendahara.ganti-password.form'); + } + + // Proses simpan password baru + public function update(Request $request) + { + $user = Auth::user(); + + $request->validate([ + 'password' => 'required|min:6|confirmed', + ]); + + // Wajib beda dari password default + if ($request->password === '12345678') { + return back()->withErrors(['password' => 'Password baru tidak boleh sama dengan password default (12345678).']); + } + + $user->update([ + 'password' => Hash::make($request->password), + 'wajib_ganti_password' => false, + ]); + + return redirect()->route('bendahara.iuran.index')->with('success', 'Password berhasil diganti. Selamat datang!'); + } +} + diff --git a/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111601.php b/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111601.php new file mode 100644 index 0000000..2bb4775 --- /dev/null +++ b/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111601.php @@ -0,0 +1,46 @@ +wajib_ganti_password) { + return redirect()->route('bendahara.iuran.index'); + } + + return view('bendahara.ganti-password.form'); + } + + // Proses simpan password baru + public function update(Request $request) + { + $user = Auth::user(); + + $request->validate([ + 'password' => 'required|min:6|confirmed', + ]); + + // Wajib beda dari password default + if ($request->password === '12345678') { + return back()->withErrors(['password' => 'Password baru tidak boleh sama dengan password default (12345678).']); + } + + $user->update([ + 'password' => Hash::make($request->password), + 'wajib_ganti_password' => false, + ]); + + return redirect()->route('bendahara.iuran.index')->with('success', 'Password berhasil diganti. Selamat datang!'); + } +} diff --git a/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111602.php b/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111602.php new file mode 100644 index 0000000..3be8464 --- /dev/null +++ b/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111602.php @@ -0,0 +1,46 @@ +wajib_ganti_password) { + return redirect()->route('bendahara.iuran.index'); + } + + return view('bendahara.ganti-password.form'); + } + + // Proses simpan password baru + public function update(Request $request) + { + $user = Auth::user(); + + $request->validate([ + 'password' => 'required|min:6|confirmed', + ]); + + // Wajib beda dari password default + if ($request->password === '12345678') { + return back()->withErrors(['password' => 'Password baru tidak boleh sama dengan password default (12345678).']); + } + + $user->update([ + 'password' => Hash::make($request->password), + 'wajib_ganti_password' => false, + ]); + + return redirect()->route('bendahara.iuran.index')->with('success', 'Password berhasil diganti. Selamat datang!'); + } +}h diff --git a/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111605.php b/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111605.php new file mode 100644 index 0000000..2bb4775 --- /dev/null +++ b/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111605.php @@ -0,0 +1,46 @@ +wajib_ganti_password) { + return redirect()->route('bendahara.iuran.index'); + } + + return view('bendahara.ganti-password.form'); + } + + // Proses simpan password baru + public function update(Request $request) + { + $user = Auth::user(); + + $request->validate([ + 'password' => 'required|min:6|confirmed', + ]); + + // Wajib beda dari password default + if ($request->password === '12345678') { + return back()->withErrors(['password' => 'Password baru tidak boleh sama dengan password default (12345678).']); + } + + $user->update([ + 'password' => Hash::make($request->password), + 'wajib_ganti_password' => false, + ]); + + return redirect()->route('bendahara.iuran.index')->with('success', 'Password berhasil diganti. Selamat datang!'); + } +} diff --git a/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111613.php b/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111613.php new file mode 100644 index 0000000..fc05d53 --- /dev/null +++ b/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111613.php @@ -0,0 +1,47 @@ +wajib_ganti_password) { + return redirect()->route('bendahara.iuran.index'); + } + + return view('bendahara.ganti-password.form'); + } + + // Proses simpan password baru + public function update(Request $request) + { + $user = Auth::user(); + + $request->validate([ + 'password' => 'required|min:6|confirmed', + ]); + + // Wajib beda dari password default + if ($request->password === '12345678') { + return back()->withErrors(['password' => 'Password baru tidak boleh sama dengan password default (12345678).']); + } + + $user->update([ + 'password' => Hash::make($request->password), + 'wajib_ganti_password' => false, + ]); + + return redirect()->route('bendahara.iuran.index')->with('success', 'Password berhasil diganti. Selamat datang!'); + } +} diff --git a/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111616.php b/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111616.php new file mode 100644 index 0000000..f50eef8 --- /dev/null +++ b/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111616.php @@ -0,0 +1,47 @@ +wajib_ganti_password) { + return redirect()->route('bendahara.iuran.index'); + } + + return view('bendahara.ganti-password.form'); + } + + // Proses simpan password baru + public function update(Request $request) + { + $user = Auth::user(); + + $request->validate([ + 'password' => 'required|min:6|confirmed', + ]); + + // Wajib beda dari password default + if ($request->password === '12345678') { + return back()->withErrors(['password' => 'Password baru tidak boleh sama dengan password default (12345678).']); + } + + $user->update([ + 'password' => Hash::make($request->password), + 'wajib_ganti_password' => false, + ]); + + return redirect()->route('bendahara.iuran.index')->with('success', 'Password berhasil diganti. Selamat datang!'); + } +} diff --git a/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111619.php b/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111619.php new file mode 100644 index 0000000..2bb4775 --- /dev/null +++ b/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111619.php @@ -0,0 +1,46 @@ +wajib_ganti_password) { + return redirect()->route('bendahara.iuran.index'); + } + + return view('bendahara.ganti-password.form'); + } + + // Proses simpan password baru + public function update(Request $request) + { + $user = Auth::user(); + + $request->validate([ + 'password' => 'required|min:6|confirmed', + ]); + + // Wajib beda dari password default + if ($request->password === '12345678') { + return back()->withErrors(['password' => 'Password baru tidak boleh sama dengan password default (12345678).']); + } + + $user->update([ + 'password' => Hash::make($request->password), + 'wajib_ganti_password' => false, + ]); + + return redirect()->route('bendahara.iuran.index')->with('success', 'Password berhasil diganti. Selamat datang!'); + } +} diff --git a/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111624.php b/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111624.php new file mode 100644 index 0000000..c848321 --- /dev/null +++ b/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111624.php @@ -0,0 +1,46 @@ +wajib_ganti_password) { + return redirect()->route('bendahara.iuran.index'); + } + + return view('bendahara.ganti-password.form'); + } + + // Proses simpan password baru + public function update(Request $request) + { + $user = Auth::user(); + + $request->validate([ + 'password' => 'required|min:6|confirmed', + ]); + + // Wajib beda dari password default + if ($request->password === '12345678') { + return back()->withErrors(['password' => 'Password baru tidak boleh sama dengan password default (12345678).']); + } + + $user->update([ + 'password' => Hash::make($request->password), + 'wajib_ganti_password' => false, + ]); + + return redirect()->route('bendahara.iuran.index')->with('success', 'Password berhasil diganti. Selamat datang!'); + } +} diff --git a/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111626.php b/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111626.php new file mode 100644 index 0000000..916e415 --- /dev/null +++ b/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111626.php @@ -0,0 +1,46 @@ +wajib_ganti_password) { + return redirect()->route('bendahara.iuran.index'); + } + + return view('bendahara.ganti-password.form'); + } + + // Proses simpan password baru + public function update(Request $request) + { + $user = Auth::user(); + + $request->validate([ + 'password' => 'required|min:6|confirmed', + ]); + + // Wajib beda dari password default + if ($request->password === '12345678') { + return back()->withErrors(['password' => 'Password baru tidak boleh sama dengan password default (12345678).']); + } + + $user->update([ + 'password' => Hash::make($request->password), + 'wajib_ganti_password' => false, + ]); + + return redirect()->route('bendahara.iuran.index')->with('success', 'Password berhasil diganti. Selamat datang!'); + } +} diff --git a/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111911.php b/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111911.php new file mode 100644 index 0000000..8f44557 --- /dev/null +++ b/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111911.php @@ -0,0 +1,46 @@ +wajib_ganti_password) { + return redirect()->route('bendahara.iuran.index'); + } + + return view('bendahara.ganti-password.form'); + } + + // Proses simpan password baru + public function update(Request $request) + { + $user = Auth::user(); + + $request->validate([ + 'password' => 'required|min:6|confirmed', + ]); + + // Wajib beda dari password default + if ($request->password === '12345678') { + return back()->withErrors(['password' => 'Password baru tidak boleh sama dengan password default (12345678).']); + } + + $user->update([ + 'password' => Hash::make($request->password), + 'wajib_ganti_password' => false, + ]) + + return redirect()->route('bendahara.iuran.index')->with('success', 'Password berhasil diganti. Selamat datang!'); + } +} diff --git a/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111913.php b/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111913.php new file mode 100644 index 0000000..916e415 --- /dev/null +++ b/.history/app/Http/Controllers/Bendahara/GantiPasswordController_20260619111913.php @@ -0,0 +1,46 @@ +wajib_ganti_password) { + return redirect()->route('bendahara.iuran.index'); + } + + return view('bendahara.ganti-password.form'); + } + + // Proses simpan password baru + public function update(Request $request) + { + $user = Auth::user(); + + $request->validate([ + 'password' => 'required|min:6|confirmed', + ]); + + // Wajib beda dari password default + if ($request->password === '12345678') { + return back()->withErrors(['password' => 'Password baru tidak boleh sama dengan password default (12345678).']); + } + + $user->update([ + 'password' => Hash::make($request->password), + 'wajib_ganti_password' => false, + ]); + + return redirect()->route('bendahara.iuran.index')->with('success', 'Password berhasil diganti. Selamat datang!'); + } +} diff --git a/.history/app/Http/Controllers/Bendahara/IuranController_20260619091229.php b/.history/app/Http/Controllers/Bendahara/IuranController_20260619091229.php new file mode 100644 index 0000000..e69de29 diff --git a/.history/app/Http/Controllers/Bendahara/IuranController_20260619091233.php b/.history/app/Http/Controllers/Bendahara/IuranController_20260619091233.php new file mode 100644 index 0000000..dfc3a6c --- /dev/null +++ b/.history/app/Http/Controllers/Bendahara/IuranController_20260619091233.php @@ -0,0 +1,107 @@ +id) + ->orderBy('created_at', 'desc') + ->get(); + + return view('bendahara.iuran.index', compact('iurans')); + } + + // Form buat iuran baru + public function create() + { + $bendahara = Auth::user(); + $penghunis = \App\Models\Penghuni::where('rt_id', $bendahara->rt_id)->get(); + + return view('bendahara.iuran.create', compact('penghunis')); + } + + // Simpan iuran baru -> status otomatis 'diajukan' + public function store(Request $request) + { + $bendahara = Auth::user(); + + $request->validate([ + 'penghuni_id' => 'required|exists:penghunis,id', + 'bulan' => 'required', + 'tahun' => 'required', + 'jumlah' => 'required|numeric', + 'jenis_iuran' => 'required', + ]); + + Iuran::create([ + 'penghuni_id' => $request->penghuni_id, + 'rt_id' => $bendahara->rt_id, + 'dibuat_oleh' => $bendahara->id, + 'bulan' => $request->bulan, + 'tahun' => $request->tahun, + 'jumlah' => $request->jumlah, + 'jenis_iuran' => $request->jenis_iuran, + 'keterangan' => $request->keterangan, + 'status' => 'diajukan', + ]); + + return redirect()->route('bendahara.iuran.index')->with('success', 'Iuran berhasil diajukan ke RT.'); + } + + // Form edit iuran yang ditolak + public function edit($id) + { + $bendahara = Auth::user(); + + $iuran = Iuran::where('id', $id) + ->where('dibuat_oleh', $bendahara->id) + ->where('status', 'ditolak') + ->firstOrFail(); + + $penghunis = \App\Models\Penghuni::where('rt_id', $bendahara->rt_id)->get(); + + return view('bendahara.iuran.edit', compact('iuran', 'penghunis')); + } + + // Update iuran yang ditolak -> ajukan ulang (status balik ke 'diajukan') + public function update(Request $request, $id) + { + $bendahara = Auth::user(); + + $iuran = Iuran::where('id', $id) + ->where('dibuat_oleh', $bendahara->id) + ->where('status', 'ditolak') + ->firstOrFail(); + + $request->validate([ + 'penghuni_id' => 'required|exists:penghunis,id', + 'bulan' => 'required', + 'tahun' => 'required', + 'jumlah' => 'required|numeric', + 'jenis_iuran' => 'required', + ]); + + $iuran->update([ + 'penghuni_id' => $request->penghuni_id, + 'bulan' => $request->bulan, + 'tahun' => $request->tahun, + 'jumlah' => $request->jumlah, + 'jenis_iuran' => $request->jenis_iuran, + 'keterangan' => $request->keterangan, + 'status' => 'diajukan', // ajukan ulang + 'catatan_rt' => null, // reset catatan penolakan lama + ]); + + return redirect()->route('bendahara.iuran.index')->with('success', 'Iuran berhasil diajukan ulang ke RT.'); + } +} diff --git a/.history/app/Http/Controllers/Bendahara/IuranController_20260619114355.php b/.history/app/Http/Controllers/Bendahara/IuranController_20260619114355.php new file mode 100644 index 0000000..2ceb690 --- /dev/null +++ b/.history/app/Http/Controllers/Bendahara/IuranController_20260619114355.php @@ -0,0 +1,107 @@ +id) + ->orderBy('created_at', 'desc') + ->get(); + + return view('bendahara.iuran.index', compact('iurans')); + } + + // Form buat iuran baru + public function create() + { + $bendahara = Auth::user(); + $penghunis = \App\Models\Penghuni::where('rt_id', $bendahara->rt_id)->get(); + + return view('bendahara.iuran.create', compact('penghunis')); + } + + // Simpan iuran baru -> status otomatis 'diajukan' + public function store(Request $request) + { + $bendahara = Auth::user(); + + $request->validate([ + 'penghuni_id' => 'required|exists:penghunis,id', + 'bulan' => 'required', + 'tahun' => 'required', + 'jumlah' => 'required|numeric', + 'jenis_iuran' => 'required', + ]); + + Iuran::create([ + 'penghuni_id' => $request->penghuni_id, + 'rt_id' => $bendahara->rt_id, + 'dibuat_oleh' => $bendahara->id, + 'bulan' => $request->bulan, + 'tahun' => $request->tahun, + 'jumlah' => $request->jumlah, + 'jenis_iuran' => $request->jenis_iuran, + 'keterangan' => $request->keterangan, + 'status' => 'diajukan', + ]); + + return redirect()->route('bendahara.iuran.index')->with('success', 'Iuran berhasil diajukan ke RT.'); + } + + // Form edit iuran yang ditolak + public function edit($id) + { + $bendahara = Auth::user(); + + $iuran = Iuran::where('id', $id) + ->where('dibuat_oleh', $bendahara->id) + ->where('status', 'ditolak') + ->firstOrFail(); + + $penghunis = \App\Models\Penghuni::where('rt_id', $bendahara->rt_id)->get(); + + return view('bendahara.iuran.edit', compact('iuran', 'penghunis')); + } + + // Update iuran yang ditolak -> ajukan ulang (status balik ke 'diajukan') + public function update(Request $request, $id) + { + $bendahara = Auth::user(); + + $iuran = Iuran::where('id', $id) + ->where('dibuat_oleh', $bendahara->id) + ->where('status', 'ditolak') + ->firstOrFail(); + + $request->validate([ + 'penghuni_id' => 'required|exists:penghuni,id', + 'bulan' => 'required', + 'tahun' => 'required', + 'jumlah' => 'required|numeric', + 'jenis_iuran' => 'required', + ]); + + $iuran->update([ + 'penghuni_id' => $request->penghuni_id, + 'bulan' => $request->bulan, + 'tahun' => $request->tahun, + 'jumlah' => $request->jumlah, + 'jenis_iuran' => $request->jenis_iuran, + 'keterangan' => $request->keterangan, + 'status' => 'diajukan', // ajukan ulang + 'catatan_rt' => null, // reset catatan penolakan lama + ]); + + return redirect()->route('bendahara.iuran.index')->with('success', 'Iuran berhasil diajukan ulang ke RT.'); + } +} diff --git a/.history/app/Http/Controllers/Bendahara/IuranController_20260619114400.php b/.history/app/Http/Controllers/Bendahara/IuranController_20260619114400.php new file mode 100644 index 0000000..ff0ddab --- /dev/null +++ b/.history/app/Http/Controllers/Bendahara/IuranController_20260619114400.php @@ -0,0 +1,107 @@ +id) + ->orderBy('created_at', 'desc') + ->get(); + + return view('bendahara.iuran.index', compact('iurans')); + } + + // Form buat iuran baru + public function create() + { + $bendahara = Auth::user(); + $penghunis = \App\Models\Penghuni::where('rt_id', $bendahara->rt_id)->get(); + + return view('bendahara.iuran.create', compact('penghunis')); + } + + // Simpan iuran baru -> status otomatis 'diajukan' + public function store(Request $request) + { + $bendahara = Auth::user(); + + $request->validate([ + 'penghuni_id' => 'required|exists:penghuni,id', + 'bulan' => 'required', + 'tahun' => 'required', + 'jumlah' => 'required|numeric', + 'jenis_iuran' => 'required', + ]); + + Iuran::create([ + 'penghuni_id' => $request->penghuni_id, + 'rt_id' => $bendahara->rt_id, + 'dibuat_oleh' => $bendahara->id, + 'bulan' => $request->bulan, + 'tahun' => $request->tahun, + 'jumlah' => $request->jumlah, + 'jenis_iuran' => $request->jenis_iuran, + 'keterangan' => $request->keterangan, + 'status' => 'diajukan', + ]); + + return redirect()->route('bendahara.iuran.index')->with('success', 'Iuran berhasil diajukan ke RT.'); + } + + // Form edit iuran yang ditolak + public function edit($id) + { + $bendahara = Auth::user(); + + $iuran = Iuran::where('id', $id) + ->where('dibuat_oleh', $bendahara->id) + ->where('status', 'ditolak') + ->firstOrFail(); + + $penghunis = \App\Models\Penghuni::where('rt_id', $bendahara->rt_id)->get(); + + return view('bendahara.iuran.edit', compact('iuran', 'penghunis')); + } + + // Update iuran yang ditolak -> ajukan ulang (status balik ke 'diajukan') + public function update(Request $request, $id) + { + $bendahara = Auth::user(); + + $iuran = Iuran::where('id', $id) + ->where('dibuat_oleh', $bendahara->id) + ->where('status', 'ditolak') + ->firstOrFail(); + + $request->validate([ + 'penghuni_id' => 'required|exists:penghuni,id', + 'bulan' => 'required', + 'tahun' => 'required', + 'jumlah' => 'required|numeric', + 'jenis_iuran' => 'required', + ]); + + $iuran->update([ + 'penghuni_id' => $request->penghuni_id, + 'bulan' => $request->bulan, + 'tahun' => $request->tahun, + 'jumlah' => $request->jumlah, + 'jenis_iuran' => $request->jenis_iuran, + 'keterangan' => $request->keterangan, + 'status' => 'diajukan', // ajukan ulang + 'catatan_rt' => null, // reset catatan penolakan lama + ]); + + return redirect()->route('bendahara.iuran.index')->with('success', 'Iuran berhasil diajukan ulang ke RT.'); + } +} diff --git a/.history/app/Http/Controllers/Bendahara/IuranController_20260620132415.php b/.history/app/Http/Controllers/Bendahara/IuranController_20260620132415.php new file mode 100644 index 0000000..ad11e9a --- /dev/null +++ b/.history/app/Http/Controllers/Bendahara/IuranController_20260620132415.php @@ -0,0 +1,125 @@ +id) + ->orderBy('created_at', 'desc') + ->get(); + + return view('bendahara.iuran.index', compact('iurans')); + } + + // Form buat iuran baru + public function create() + { + $bendahara = Auth::user(); + $penghunis = \App\Models\Penghuni::where('rt_id', $bendahara->rt_id)->get(); + + return view('bendahara.iuran.create', compact('penghunis')); + } + + // Simpan iuran baru -> status otomatis 'diajukan' + public function store(Request $request) + { + $bendahara = Auth::user(); + + $request->validate([ + 'penghuni_id' => 'required|exists:penghuni,id', + 'bulan' => 'required', + 'tahun' => 'required', + 'jumlah' => 'required|numeric', + 'jenis_iuran' => 'required', + ]); + + Iuran::create([ + 'penghuni_id' => $request->penghuni_id, + 'rt_id' => $bendahara->rt_id, + 'dibuat_oleh' => $bendahara->id, + 'bulan' => $request->bulan, + 'tahun' => $request->tahun, + 'jumlah' => $request->jumlah, + 'jenis_iuran' => $request->jenis_iuran, + 'keterangan' => $request->keterangan, + 'status' => 'diajukan', + ]); + + return redirect()->route('bendahara.iuran.index')->with('success', 'Iuran berhasil diajukan ke RT.'); + } + + // Form edit iuran yang ditolak + public function edit($id) + { + $bendahara = Auth::user(); + + $iuran = Iuran::where('id', $id) + ->where('dibuat_oleh', $bendahara->id) + ->where('status', 'ditolak') + ->firstOrFail(); + + $penghunis = \App\Models\Penghuni::where('rt_id', $bendahara->rt_id)->get(); + + return view('bendahara.iuran.edit', compact('iuran', 'penghunis')); + } + + // Update iuran yang ditolak -> ajukan ulang (status balik ke 'diajukan') + public function update(Request $request, $id) + { + $bendahara = Auth::user(); + + $iuran = Iuran::where('id', $id) + ->where('dibuat_oleh', $bendahara->id) + ->where('status', 'ditolak') + ->firstOrFail(); + + $request->validate([ + 'penghuni_id' => 'required|exists:penghuni,id', + 'bulan' => 'required', + 'tahun' => 'required', + 'jumlah' => 'required|numeric', + 'jenis_iuran' => 'required', + ]); + + $iuran->update([ + 'penghuni_id' => $request->penghuni_id, + 'bulan' => $request->bulan, + 'tahun' => $request->tahun, + 'jumlah' => $request->jumlah, + 'jenis_iuran' => $request->jenis_iuran, + 'keterangan' => $request->keterangan, + 'status' => 'diajukan', // ajukan ulang + 'catatan_rt' => null, // reset catatan penolakan lama + ]); + + return redirect()->route('bendahara.iuran.index')->with('success', 'Iuran berhasil diajukan ulang ke RT.'); + } + + // Bendahara konfirmasi iuran 'menunggu' jadi 'lunas' langsung + public function konfirmasiLunas($id) + { + $bendahara = Auth::user(); + + $iuran = Iuran::where('id', $id) + ->where('dibuat_oleh', $bendahara->id) + ->where('status', 'menunggu') + ->firstOrFail(); + + $iuran->update([ + 'status' => 'lunas', + 'tanggal_bayar' => now(), + ]); + + return back()->with('success', 'Iuran dikonfirmasi lunas.'); + } +} diff --git a/.history/app/Http/Controllers/Bendahara/KasController_20260619185433.php b/.history/app/Http/Controllers/Bendahara/KasController_20260619185433.php new file mode 100644 index 0000000..e69de29 diff --git a/.history/app/Http/Controllers/Bendahara/KasController_20260619185447.php b/.history/app/Http/Controllers/Bendahara/KasController_20260619185447.php new file mode 100644 index 0000000..d227943 --- /dev/null +++ b/.history/app/Http/Controllers/Bendahara/KasController_20260619185447.php @@ -0,0 +1,52 @@ +id) + ->orderBy('created_at', 'asc') + ->get(); + + $totalMasuk = $kas->where('jenis', 'masuk')->sum('jumlah'); + $totalKeluar = $kas->where('jenis', 'keluar')->sum('jumlah'); + $saldo = $totalMasuk - $totalKeluar; + + // Urutkan terbaru di atas untuk ditampilkan + $kas = $kas->sortByDesc('created_at'); + + return view('bendahara.kas.index', compact('kas', 'totalMasuk', 'totalKeluar', 'saldo')); + } + + // Catat kas keluar manual + public function store(Request $request) + { + $bendahara = Auth::user(); + + $request->validate([ + 'jumlah' => 'required|numeric|min:1', + 'keterangan' => 'required|string|max:255', + ]); + + KasBendahara::create([ + 'bendahara_id' => $bendahara->id, + 'rt_id' => $bendahara->rt_id, + 'jenis' => 'keluar', + 'jumlah' => $request->jumlah, + 'keterangan' => $request->keterangan, + 'iuran_id' => null, + ]); + + return back()->with('success', 'Kas keluar berhasil dicatat.'); + } +} diff --git a/.history/app/Http/Controllers/Bendahara/KasController_20260619191326.php b/.history/app/Http/Controllers/Bendahara/KasController_20260619191326.php new file mode 100644 index 0000000..b0daec6 --- /dev/null +++ b/.history/app/Http/Controllers/Bendahara/KasController_20260619191326.php @@ -0,0 +1,49 @@ +id) + ->orderBy('created_at', 'asc') + ->get(); + + $totalMasuk = $kas->where('jenis', 'masuk')->sum('jumlah'); + $totalKeluar = $kas->where('jenis', 'keluar')->sum('jumlah'); + $saldo = $totalMasuk - $totalKeluar; + + $kas = $kas->sortByDesc('created_at'); + + return view('bendahara.kas.index', compact('kas', 'totalMasuk', 'totalKeluar', 'saldo')); + } + + public function store(Request $request) + { + $bendahara = Auth::user(); + + $request->validate([ + 'jumlah' => 'required|numeric|min:1', + 'keterangan' => 'required|string|max:255', + ]); + + KasBendahara::create([ + 'bendahara_id' => $bendahara->id, + 'rt_id' => $bendahara->rt_id, + 'jenis' => 'keluar', + 'jumlah' => $request->jumlah, + 'keterangan' => $request->keterangan, + 'iuran_id' => null, + ]); + + return back()->with('success', 'Kas keluar berhasil dicatat.'); + } +} diff --git a/.history/app/Http/Controllers/Bendahara/KasController_20260619212536.php b/.history/app/Http/Controllers/Bendahara/KasController_20260619212536.php new file mode 100644 index 0000000..c09426d --- /dev/null +++ b/.history/app/Http/Controllers/Bendahara/KasController_20260619212536.php @@ -0,0 +1,104 @@ +id) + ->orderBy('created_at', 'asc') + ->get(); + + $totalMasuk = $kas->where('jenis', 'masuk')->sum('jumlah'); + $totalKeluar = $kas->where('jenis', 'keluar')->sum('jumlah'); + $saldo = $totalMasuk - $totalKeluar; + + $kas = $kas->sortByDesc('created_at'); + + return view('bendahara.kas.index', compact('kas', 'totalMasuk', 'totalKeluar', 'saldo')); + } + + // Catat kas manual (masuk ATAU keluar, tanpa penghuni) + public function store(Request $request) + { + $bendahara = Auth::user(); + + $request->validate([ + 'jenis' => 'required|in:masuk,keluar', + 'jumlah' => 'required|numeric|min:1', + 'keterangan' => 'required|string|max:255', + ]); + + KasBendahara::create([ + 'bendahara_id' => $bendahara->id, + 'rt_id' => $bendahara->rt_id, + 'penghuni_id' => null, + 'jenis' => $request->jenis, + 'jumlah' => $request->jumlah, + 'keterangan' => $request->keterangan, + 'status' => 'manual', + 'iuran_id' => null, + ]); + + return back()->with('success', 'Kas berhasil dicatat.'); + } + + // Form buat tagihan kas ke penghuni + public function createTagihan() + { + $bendahara = Auth::user(); + $penghunis = Penghuni::where('rt_id', $bendahara->rt_id)->get(); + + return view('bendahara.kas.create-tagihan', compact('penghunis')); + } + + // Simpan tagihan kas ke penghuni -> status 'menunggu_bayar' + public function storeTagihan(Request $request) + { + $bendahara = Auth::user(); + + $request->validate([ + 'penghuni_id' => 'required|exists:penghuni,id', + 'jumlah' => 'required|numeric|min:1', + 'keterangan' => 'required|string|max:255', + ]); + + KasBendahara::create([ + 'bendahara_id' => $bendahara->id, + 'rt_id' => $bendahara->rt_id, + 'penghuni_id' => $request->penghuni_id, + 'jenis' => 'masuk', + 'jumlah' => $request->jumlah, + 'keterangan' => $request->keterangan, + 'status' => 'menunggu_bayar', + 'iuran_id' => null, + ]); + + return redirect()->route('bendahara.kas.index')->with('success', 'Tagihan kas berhasil dikirim ke penghuni.'); + } + + // Bendahara konfirmasi kas yang sudah dibayar penghuni -> jadi 'lunas' + public function konfirmasi($id) + { + $bendahara = Auth::user(); + + $kas = KasBendahara::where('id', $id) + ->where('bendahara_id', $bendahara->id) + ->where('status', 'menunggu_konfirmasi') + ->firstOrFail(); + + $kas->update(['status' => 'lunas']); + + return back()->with('success', 'Pembayaran kas dikonfirmasi.'); + } +} diff --git a/.history/app/Http/Controllers/Bendahara/KasController_20260620082653.php b/.history/app/Http/Controllers/Bendahara/KasController_20260620082653.php new file mode 100644 index 0000000..7b61c48 --- /dev/null +++ b/.history/app/Http/Controllers/Bendahara/KasController_20260620082653.php @@ -0,0 +1,106 @@ +id) + ->orderBy('created_at', 'asc') + ->get(); + + $kasTerhitung = $kas->whereIn('status', ['manual', 'lunas']); + + $totalMasuk = $kasTerhitung->where('jenis', 'masuk')->sum('jumlah'); + $totalKeluar = $kasTerhitung->where('jenis', 'keluar')->sum('jumlah'); + $saldo = $totalMasuk - $totalKeluar; + + $kas = $kas->sortByDesc('created_at'); + + return view('bendahara.kas.index', compact('kas', 'totalMasuk', 'totalKeluar', 'saldo')); + } + + // Catat kas manual (masuk ATAU keluar, tanpa penghuni) + public function store(Request $request) + { + $bendahara = Auth::user(); + + $request->validate([ + 'jenis' => 'required|in:masuk,keluar', + 'jumlah' => 'required|numeric|min:1', + 'keterangan' => 'required|string|max:255', + ]); + + KasBendahara::create([ + 'bendahara_id' => $bendahara->id, + 'rt_id' => $bendahara->rt_id, + 'penghuni_id' => null, + 'jenis' => $request->jenis, + 'jumlah' => $request->jumlah, + 'keterangan' => $request->keterangan, + 'status' => 'manual', + 'iuran_id' => null, + ]); + + return back()->with('success', 'Kas berhasil dicatat.'); + } + + // Form buat tagihan kas ke penghuni + public function createTagihan() + { + $bendahara = Auth::user(); + $penghunis = Penghuni::where('rt_id', $bendahara->rt_id)->get(); + + return view('bendahara.kas.create-tagihan', compact('penghunis')); + } + + // Simpan tagihan kas ke penghuni -> status 'menunggu_bayar' + public function storeTagihan(Request $request) + { + $bendahara = Auth::user(); + + $request->validate([ + 'penghuni_id' => 'required|exists:penghuni,id', + 'jumlah' => 'required|numeric|min:1', + 'keterangan' => 'required|string|max:255', + ]); + + KasBendahara::create([ + 'bendahara_id' => $bendahara->id, + 'rt_id' => $bendahara->rt_id, + 'penghuni_id' => $request->penghuni_id, + 'jenis' => 'masuk', + 'jumlah' => $request->jumlah, + 'keterangan' => $request->keterangan, + 'status' => 'menunggu_bayar', + 'iuran_id' => null, + ]); + + return redirect()->route('bendahara.kas.index')->with('success', 'Tagihan kas berhasil dikirim ke penghuni.'); + } + + // Bendahara konfirmasi kas yang sudah dibayar penghuni -> jadi 'lunas' + public function konfirmasi($id) + { + $bendahara = Auth::user(); + + $kas = KasBendahara::where('id', $id) + ->where('bendahara_id', $bendahara->id) + ->where('status', 'menunggu_konfirmasi') + ->firstOrFail(); + + $kas->update(['status' => 'lunas']); + + return back()->with('success', 'Pembayaran kas dikonfirmasi.'); + } +} diff --git a/.history/app/Http/Controllers/Bendahara/RekapController_20260619095636.php b/.history/app/Http/Controllers/Bendahara/RekapController_20260619095636.php new file mode 100644 index 0000000..e69de29 diff --git a/.history/app/Http/Controllers/Bendahara/RekapController_20260619095645.php b/.history/app/Http/Controllers/Bendahara/RekapController_20260619095645.php new file mode 100644 index 0000000..eaaefbd --- /dev/null +++ b/.history/app/Http/Controllers/Bendahara/RekapController_20260619095645.php @@ -0,0 +1,69 @@ +id) + ->orderBy('created_at', 'desc') + ->get(); + + // Iuran berstatus 'menunggu' yang belum masuk rekap manapun + $iuranSiapRekap = Iuran::where('rt_id', $bendahara->rt_id) + ->where('status', 'menunggu') + ->whereNull('rekap_id') + ->get(); + + return view('bendahara.rekap.index', compact('rekaps', 'iuranSiapRekap')); + } + + // Kirim rekap baru -> kumpulkan semua iuran 'menunggu' jadi 1 batch + public function store(Request $request) + { + $bendahara = Auth::user(); + + $iuranIds = Iuran::where('rt_id', $bendahara->rt_id) + ->where('status', 'menunggu') + ->whereNull('rekap_id') + ->pluck('id'); + + if ($iuranIds->isEmpty()) { + return back()->withErrors(['rekap' => 'Tidak ada iuran berstatus menunggu untuk direkap.']); + } + + $rekap = RekapIuran::create([ + 'bendahara_id' => $bendahara->id, + 'rt_id' => $bendahara->rt_id, + 'periode' => $request->periode ?? now()->translatedFormat('F Y'), + 'status' => 'diajukan', + ]); + + Iuran::whereIn('id', $iuranIds)->update(['rekap_id' => $rekap->id]); + + return redirect()->route('bendahara.rekap.index')->with('success', 'Rekap berhasil dikirim ke RT.'); + } + + // Lihat detail isi 1 rekap + public function show($id) + { + $bendahara = Auth::user(); + + $rekap = RekapIuran::where('id', $id) + ->where('bendahara_id', $bendahara->id) + ->with('iurans.penghuni') + ->firstOrFail(); + + return view('bendahara.rekap.show', compact('rekap')); + } +} diff --git a/.history/app/Http/Controllers/Bendahara/RekapController_20260619101907.php b/.history/app/Http/Controllers/Bendahara/RekapController_20260619101907.php new file mode 100644 index 0000000..e675f5d --- /dev/null +++ b/.history/app/Http/Controllers/Bendahara/RekapController_20260619101907.php @@ -0,0 +1,70 @@ +id) + ->orderBy('created_at', 'desc') + ->get(); + + // Iuran berstatus 'menunggu' yang belum masuk rekap manapun + $iuranSiapRekap = Iuran::where('rt_id', $bendahara->rt_id) + ->where('status', 'menunggu') + ->whereNull('rekap_id') + ->get(); + + return view('bendahara.rekap.index', compact('rekaps', 'iuranSiapRekap')); + } + + // Kirim rekap baru -> kumpulkan semua iuran 'menunggu' jadi 1 batch + public function store(Request $request) + { + $bendahara = Auth::user(); + + $iuranIds = Iuran::where('rt_id', $bendahara->rt_id) + ->where('status', 'menunggu') + ->whereNull('rekap_id') + ->pluck('id'); + + if ($iuranIds->isEmpty()) { + return back()->withErrors(['rekap' => 'Tidak ada iuran berstatus menunggu untuk direkap.']); + } + + $rekap = RekapIuran::create([ + 'bendahara_id' => $bendahara->id, + 'rt_id' => $bendahara->rt_id, + 'periode' => $request->periode ?? now()->translatedFormat('F Y'), + 'status' => 'diajukan', + ]); + + Iuran::whereIn('id', $iuranIds)->update(['rekap_id' => $rekap->id]); + + return redirect()->route('bendahara.rekap.index')->with('success', 'Rekap berhasil dikirim ke RT.'); + } + + // Lihat detail isi 1 rekap + public function show($id) + { + $bendahara = Auth::user(); + + $rekap = RekapIuran::where('id', $id) + ->where('bendahara_id', $bendahara->id) + ->with('iurans.penghuni') + ->firstOrFail(); + + return view('bendahara.rekap.show', compact('rekap')); + } +} diff --git a/.history/app/Http/Controllers/Bendahara/RekapController_20260619101908.php b/.history/app/Http/Controllers/Bendahara/RekapController_20260619101908.php new file mode 100644 index 0000000..d4570fa --- /dev/null +++ b/.history/app/Http/Controllers/Bendahara/RekapController_20260619101908.php @@ -0,0 +1,70 @@ +id) + ->orderBy('created_at', 'desc') + ->get(); + + // Iuran berstatus 'menunggu' yang belum masuk rekap manapun + $iuranSiapRekap = Iuran::where('rt_id', $bendahara->rt_id) + ->where('status', 'menunggu') + ->whereNull('rekap_id') + ->get(); + + return view('bendahara.rekap.index', compact('rekaps', 'iuranSiapRekap')); + } + + // Kirim rekap baru -> kumpulkan semua iuran 'menunggu' jadi 1 batch + public function store(Request $request) + { + $bendahara = Auth::user(); + + $iuranIds = Iuran::where('rt_id', $bendahara->rt_id) + ->where('status', 'menunggu') + ->whereNull('rekap_id') + ->pluck('id'); + + if ($iuranIds->isEmpty()) { + return back()->withErrors(['rekap' => 'Tidak ada iuran berstatus menunggu untuk direkap.']); + } + + $rekap = RekapIuran::create([ + 'bendahara_id' => $bendahara->id, + 'rt_id' => $bendahara->rt_id, + 'periode' => $request->periode ?? now()->translatedFormat('F Y'), + 'status' => 'diajukan', + ]); + + Iuran::whereIn('id', $iuranIds)->update(['rekap_id' => $rekap->id]); + + return redirect()->route('bendahara.rekap.index')->with('success', 'Rekap berhasil dikirim ke RT.'); + } + + // Lihat detail isi 1 rekap + public function show($id) + { + $bendahara = Auth::user(); + + $rekap = RekapIuran::where('id', $id) + ->where('bendahara_id', $bendahara->id) + ->with('iurans.penghuni') + ->firstOrFail(); + + return view('bendahara.rekap.show', compact('rekap')); + } +} diff --git a/.history/app/Http/Controllers/Bendahara/RekapController_20260619101916.php b/.history/app/Http/Controllers/Bendahara/RekapController_20260619101916.php new file mode 100644 index 0000000..eaaefbd --- /dev/null +++ b/.history/app/Http/Controllers/Bendahara/RekapController_20260619101916.php @@ -0,0 +1,69 @@ +id) + ->orderBy('created_at', 'desc') + ->get(); + + // Iuran berstatus 'menunggu' yang belum masuk rekap manapun + $iuranSiapRekap = Iuran::where('rt_id', $bendahara->rt_id) + ->where('status', 'menunggu') + ->whereNull('rekap_id') + ->get(); + + return view('bendahara.rekap.index', compact('rekaps', 'iuranSiapRekap')); + } + + // Kirim rekap baru -> kumpulkan semua iuran 'menunggu' jadi 1 batch + public function store(Request $request) + { + $bendahara = Auth::user(); + + $iuranIds = Iuran::where('rt_id', $bendahara->rt_id) + ->where('status', 'menunggu') + ->whereNull('rekap_id') + ->pluck('id'); + + if ($iuranIds->isEmpty()) { + return back()->withErrors(['rekap' => 'Tidak ada iuran berstatus menunggu untuk direkap.']); + } + + $rekap = RekapIuran::create([ + 'bendahara_id' => $bendahara->id, + 'rt_id' => $bendahara->rt_id, + 'periode' => $request->periode ?? now()->translatedFormat('F Y'), + 'status' => 'diajukan', + ]); + + Iuran::whereIn('id', $iuranIds)->update(['rekap_id' => $rekap->id]); + + return redirect()->route('bendahara.rekap.index')->with('success', 'Rekap berhasil dikirim ke RT.'); + } + + // Lihat detail isi 1 rekap + public function show($id) + { + $bendahara = Auth::user(); + + $rekap = RekapIuran::where('id', $id) + ->where('bendahara_id', $bendahara->id) + ->with('iurans.penghuni') + ->firstOrFail(); + + return view('bendahara.rekap.show', compact('rekap')); + } +} diff --git a/.history/app/Http/Controllers/Bendahara/RekapController_20260620133154.php b/.history/app/Http/Controllers/Bendahara/RekapController_20260620133154.php new file mode 100644 index 0000000..c2137c2 --- /dev/null +++ b/.history/app/Http/Controllers/Bendahara/RekapController_20260620133154.php @@ -0,0 +1,66 @@ +id) + ->orderBy('created_at', 'desc') + ->get(); + + // Iuran yang sudah lunas, belum masuk rekap manapun + $iuranSiapRekap = Iuran::where('rt_id', $bendahara->rt_id) + ->where('status', 'lunas') + ->whereNull('rekap_id') + ->get(); + + return view('bendahara.rekap.index', compact('rekaps', 'iuranSiapRekap')); + } + + public function store(Request $request) + { + $bendahara = Auth::user(); + + $iuranIds = Iuran::where('rt_id', $bendahara->rt_id) + ->where('status', 'lunas') + ->whereNull('rekap_id') + ->pluck('id'); + + if ($iuranIds->isEmpty()) { + return back()->withErrors(['rekap' => 'Tidak ada iuran lunas untuk direkap.']); + } + + $rekap = RekapIuran::create([ + 'bendahara_id' => $bendahara->id, + 'rt_id' => $bendahara->rt_id, + 'periode' => $request->periode ?? now()->translatedFormat('F Y'), + 'status' => 'disetujui', + ]); + + Iuran::whereIn('id', $iuranIds)->update(['rekap_id' => $rekap->id]); + + return redirect()->route('bendahara.rekap.index')->with('success', 'Rekap berhasil dikirim sebagai laporan ke RT.'); + } + + public function show($id) + { + $bendahara = Auth::user(); + + $rekap = RekapIuran::where('id', $id) + ->where('bendahara_id', $bendahara->id) + ->with('iurans.penghuni') + ->firstOrFail(); + + return view('bendahara.rekap.show', compact('rekap')); + } +} diff --git a/.history/app/Http/Controllers/Bendahara/RekapController_20260620134854.php b/.history/app/Http/Controllers/Bendahara/RekapController_20260620134854.php new file mode 100644 index 0000000..c2eb6f2 --- /dev/null +++ b/.history/app/Http/Controllers/Bendahara/RekapController_20260620134854.php @@ -0,0 +1,66 @@ +id) + ->orderBy('created_at', 'desc') + ->get(); + + // Iuran yang sudah lunas, belum masuk rekap manapun + $iuranSiapRekap = Iuran::where('rt_id', $bendahara->rt_id) + ->where('status', 'lunas') + ->whereNull('rekap_id') + ->get(); + + return view('bendahara.rekap.index', compact('rekaps', 'iuranSiapRekap')); + } + + public function store(Request $request) + { + $bendahara = Auth::user(); + + $iuranIds = Iuran::where('rt_id', $bendahara->rt_id) + ->where('status', 'lunas') + ->whereNull('rekap_id') + ->pluck('id'); + + if ($iuranIds->isEmpty()) { + return back()->withErrors(['rekap' => 'Tidak ada iuran lunas untuk direkap.']); + } + + $rekap = RekapIuran::create([ + 'bendahara_id' => $bendahara->id, + 'rt_id' => $bendahara->rt_id, + 'periode' => $request->periode ?? now()->translatedFormat('F Y'), + 'status' => 'diajukan', + ]); + + Iuran::whereIn('id', $iuranIds)->update(['rekap_id' => $rekap->id]); + + return redirect()->route('bendahara.rekap.index')->with('success', 'Rekap berhasil dikirim sebagai laporan ke RT.'); + } + + public function show($id) + { + $bendahara = Auth::user(); + + $rekap = RekapIuran::where('id', $id) + ->where('bendahara_id', $bendahara->id) + ->with('iurans.penghuni') + ->firstOrFail(); + + return view('bendahara.rekap.show', compact('rekap')); + } +} diff --git a/.history/app/Http/Controllers/DashboardController_20260428130350.php b/.history/app/Http/Controllers/DashboardController_20260428130350.php deleted file mode 100644 index 67d9ce6..0000000 --- a/.history/app/Http/Controllers/DashboardController_20260428130350.php +++ /dev/null @@ -1,112 +0,0 @@ -groupBy('status') - ->pluck('total', 'status'); - - $diajukan = $statistik['diajukan'] ?? 0; - $menunggu = $statistik['menunggu'] ?? 0; - $selesai = $statistik['selesai'] ?? 0; - - return view('rt.dashboard', [ - 'totalPenghuni' => Penghuni::count(), - 'totalRumah' => Rumah::count(), - 'totalIuran' => Iuran::count(), - 'totalPengaduan'=> Layanan::count(), - - 'menungguRT' => $diajukan, - 'menungguAdmin' => $menunggu, - - 'diajukan' => $diajukan, - 'menunggu' => $menunggu, - 'selesai' => $selesai, - ]); - } - - // 🔥 DASHBOARD ADMIN - public function admin() -{ - $totalPenghuni = Penghuni::count(); - $totalRumah = Rumah::count(); - $totalPengaduan = Layanan::count(); - $totalIuran = Iuran::sum('jumlah'); - - // ========================= - // 🔥 BULANAN (REAL - 12 BULAN) - // ========================= - $chartBulananRaw = Layanan::selectRaw("MONTH(created_at) as bulan, COUNT(*) as total") - ->groupBy('bulan') - ->pluck('total','bulan'); - - $chartBulanan = []; - for ($i = 1; $i <= 12; $i++) { - $chartBulanan[] = $chartBulananRaw[$i] ?? 0; - } - - // ========================= - // 🔥 HARIAN (7 HARI TERAKHIR) - // ========================= - $harianRaw = Layanan::selectRaw("DATE(created_at) as tgl, COUNT(*) as total") - ->whereDate('created_at', '>=', now()->subDays(6)) - ->groupBy('tgl') - ->pluck('total','tgl'); - - $chartHarian = []; - for ($i = 6; $i >= 0; $i--) { - $tgl = now()->subDays($i)->format('Y-m-d'); - $chartHarian[] = $harianRaw[$tgl] ?? 0; - } - - // ========================= - // 🔥 MINGGUAN (4 MINGGU TERAKHIR) - // ========================= - $chartMingguan = []; - for ($i = 3; $i >= 0; $i--) { - $start = now()->subWeeks($i)->startOfWeek(); - $end = now()->subWeeks($i)->endOfWeek(); - - $total = Layanan::whereBetween('created_at', [$start, $end])->count(); - $chartMingguan[] = $total; - } - - // ========================= - // 🔥 TAHUNAN (4 TAHUN TERAKHIR) - // ========================= - $tahunanRaw = Layanan::selectRaw("YEAR(created_at) as tahun, COUNT(*) as total") - ->groupBy('tahun') - ->pluck('total','tahun'); - - $chartTahunan = []; - $tahunSekarang = now()->year; - - for ($i = 3; $i >= 0; $i--) { - $tahun = $tahunSekarang - $i; - $chartTahunan[] = $tahunanRaw[$tahun] ?? 0; - } - - return view('admin.dashboard', compact( - 'totalPenghuni', - 'totalRumah', - 'totalPengaduan', - 'totalIuran', - 'chartHarian', - 'chartMingguan', - 'chartBulanan', - 'chartTahunan' - )); -}} diff --git a/.history/app/Http/Controllers/DashboardController_20260507082141.php b/.history/app/Http/Controllers/DashboardController_20260507082141.php deleted file mode 100644 index ddd7da9..0000000 --- a/.history/app/Http/Controllers/DashboardController_20260507082141.php +++ /dev/null @@ -1,140 +0,0 @@ -id; // rt_id di tabel rumah = user id si RT - - // Statistik status layanan - $statistik = Layanan::selectRaw('status, COUNT(*) as total') - ->groupBy('status') - ->pluck('total', 'status'); - - $diajukan = $statistik['diajukan'] ?? 0; - $menunggu = $statistik['menunggu'] ?? 0; - $selesai = $statistik['selesai'] ?? 0; - - // ── PER RT ── - $rt1Id = 13; // blok D - $rt2Id = 19; // blok E - $rt3Id = 28; // blok C - // (blok B = 34, kalau ada RT ke-4) - - $rt1_penghuni = Penghuni::whereHas('rumah', fn($q) => $q->where('rt_id', $rt1Id))->count(); - $rt2_penghuni = Penghuni::whereHas('rumah', fn($q) => $q->where('rt_id', $rt2Id))->count(); - $rt3_penghuni = Penghuni::whereHas('rumah', fn($q) => $q->where('rt_id', $rt3Id))->count(); - - $rt1_rumah_terisi = Rumah::where('rt_id', $rt1Id)->where('status', 'Terisi')->count(); - $rt2_rumah_terisi = Rumah::where('rt_id', $rt2Id)->where('status', 'Terisi')->count(); - $rt3_rumah_terisi = Rumah::where('rt_id', $rt3Id)->where('status', 'Terisi')->count(); - - $rt1_rumah_total = Rumah::where('rt_id', $rt1Id)->count(); - $rt2_rumah_total = Rumah::where('rt_id', $rt2Id)->count(); - $rt3_rumah_total = Rumah::where('rt_id', $rt3Id)->count(); - - return view('rt.dashboard', [ - 'totalPenghuni' => Penghuni::count(), - 'totalRumah' => Rumah::count(), - 'totalIuran' => Iuran::count(), - 'totalPengaduan' => Layanan::count(), - 'menungguRT' => $diajukan, - 'menungguAdmin' => $menunggu, - 'diajukan' => $diajukan, - 'menunggu' => $menunggu, - 'selesai' => $selesai, - - // ── tambahan per RT ── - 'rt1_penghuni' => $rt1_penghuni, - 'rt2_penghuni' => $rt2_penghuni, - 'rt3_penghuni' => $rt3_penghuni, - 'rt1_rumah_terisi'=> $rt1_rumah_terisi, - 'rt2_rumah_terisi'=> $rt2_rumah_terisi, - 'rt3_rumah_terisi'=> $rt3_rumah_terisi, - 'rt1_rumah_total' => $rt1_rumah_total, - 'rt2_rumah_total' => $rt2_rumah_total, - 'rt3_rumah_total' => $rt3_rumah_total, - ]); -} - - // 🔥 DASHBOARD ADMIN - public function admin() -{ - $totalPenghuni = Penghuni::count(); - $totalRumah = Rumah::count(); - $totalPengaduan = Layanan::count(); - $totalIuran = Iuran::sum('jumlah'); - - // ========================= - // 🔥 BULANAN (REAL - 12 BULAN) - // ========================= - $chartBulananRaw = Layanan::selectRaw("MONTH(created_at) as bulan, COUNT(*) as total") - ->groupBy('bulan') - ->pluck('total','bulan'); - - $chartBulanan = []; - for ($i = 1; $i <= 12; $i++) { - $chartBulanan[] = $chartBulananRaw[$i] ?? 0; - } - - // ========================= - // 🔥 HARIAN (7 HARI TERAKHIR) - // ========================= - $harianRaw = Layanan::selectRaw("DATE(created_at) as tgl, COUNT(*) as total") - ->whereDate('created_at', '>=', now()->subDays(6)) - ->groupBy('tgl') - ->pluck('total','tgl'); - - $chartHarian = []; - for ($i = 6; $i >= 0; $i--) { - $tgl = now()->subDays($i)->format('Y-m-d'); - $chartHarian[] = $harianRaw[$tgl] ?? 0; - } - - // ========================= - // 🔥 MINGGUAN (4 MINGGU TERAKHIR) - // ========================= - $chartMingguan = []; - for ($i = 3; $i >= 0; $i--) { - $start = now()->subWeeks($i)->startOfWeek(); - $end = now()->subWeeks($i)->endOfWeek(); - - $total = Layanan::whereBetween('created_at', [$start, $end])->count(); - $chartMingguan[] = $total; - } - - // ========================= - // 🔥 TAHUNAN (4 TAHUN TERAKHIR) - // ========================= - $tahunanRaw = Layanan::selectRaw("YEAR(created_at) as tahun, COUNT(*) as total") - ->groupBy('tahun') - ->pluck('total','tahun'); - - $chartTahunan = []; - $tahunSekarang = now()->year; - - for ($i = 3; $i >= 0; $i--) { - $tahun = $tahunSekarang - $i; - $chartTahunan[] = $tahunanRaw[$tahun] ?? 0; - } - - return view('admin.dashboard', compact( - 'totalPenghuni', - 'totalRumah', - 'totalPengaduan', - 'totalIuran', - 'chartHarian', - 'chartMingguan', - 'chartBulanan', - 'chartTahunan' - )); -}} diff --git a/.history/app/Http/Controllers/DashboardController_20260507082206.php b/.history/app/Http/Controllers/DashboardController_20260507082206.php deleted file mode 100644 index d050d49..0000000 --- a/.history/app/Http/Controllers/DashboardController_20260507082206.php +++ /dev/null @@ -1,140 +0,0 @@ -id; // rt_id di tabel rumah = user id si RT - - // Statistik status layanan - $statistik = Layanan::selectRaw('status, COUNT(*) as total') - ->groupBy('status') - ->pluck('total', 'status'); - - $diajukan = $statistik['diajukan'] ?? 0; - $menunggu = $statistik['menunggu'] ?? 0; - $selesai = $statistik['selesai'] ?? 0; - - // ── PER RT ── - $rt1Id = 13; // blok D - $rt2Id = 19; // blok E - $rt3Id = 28; // blok C - // (blok B = 34, kalau ada RT ke-4) - - $rt1_penghuni = Penghuni::whereHas('rumah', fn($q) => $q->where('rt_id', $rt1Id))->count(); - $rt2_penghuni = Penghuni::whereHas('rumah', fn($q) => $q->where('rt_id', $rt2Id))->count(); - $rt3_penghuni = Penghuni::whereHas('rumah', fn($q) => $q->where('rt_id', $rt3Id))->count(); - - $rt1_rumah_terisi = Rumah::where('rt_id', $rt1Id)->where('status', 'Terisi')->count(); - $rt2_rumah_terisi = Rumah::where('rt_id', $rt2Id)->where('status', 'Terisi')->count(); - $rt3_rumah_terisi = Rumah::where('rt_id', $rt3Id)->where('status', 'Terisi')->count(); - - $rt1_rumah_total = Rumah::where('rt_id', $rt1Id)->count(); - $rt2_rumah_total = Rumah::where('rt_id', $rt2Id)->count(); - $rt3_rumah_total = Rumah::where('rt_id', $rt3Id)->count(); - - return view('rt.dashboard', [ - 'totalPenghuni' => Penghuni::count(), - 'totalRumah' => Rumah::count(), - 'totalIuran' => Iuran::count(), - 'totalPengaduan' => Layanan::count(), - 'menungguRT' => $diajukan, - 'menungguAdmin' => $menunggu, - 'diajukan' => $diajukan, - 'menunggu' => $menunggu, - 'selesai' => $selesai, - - // ── tambahan per RT ── - 'rt1_penghuni' => $rt1_penghuni, - 'rt2_penghuni' => $rt2_penghuni, - 'rt3_penghuni' => $rt3_penghuni, - 'rt1_rumah_terisi'=> $rt1_rumah_terisi, - 'rt2_rumah_terisi'=> $rt2_rumah_terisi, - 'rt3_rumah_terisi'=> $rt3_rumah_terisi, - 'rt1_rumah_total' => $rt1_rumah_total, - 'rt2_rumah_total' => $rt2_rumah_total, - 'rt3_rumah_total' => $rt3_rumah_total, - ]); - } - - // 🔥 DASHBOARD ADMIN - public function admin() -{ - $totalPenghuni = Penghuni::count(); - $totalRumah = Rumah::count(); - $totalPengaduan = Layanan::count(); - $totalIuran = Iuran::sum('jumlah'); - - // ========================= - // 🔥 BULANAN (REAL - 12 BULAN) - // ========================= - $chartBulananRaw = Layanan::selectRaw("MONTH(created_at) as bulan, COUNT(*) as total") - ->groupBy('bulan') - ->pluck('total','bulan'); - - $chartBulanan = []; - for ($i = 1; $i <= 12; $i++) { - $chartBulanan[] = $chartBulananRaw[$i] ?? 0; - } - - // ========================= - // 🔥 HARIAN (7 HARI TERAKHIR) - // ========================= - $harianRaw = Layanan::selectRaw("DATE(created_at) as tgl, COUNT(*) as total") - ->whereDate('created_at', '>=', now()->subDays(6)) - ->groupBy('tgl') - ->pluck('total','tgl'); - - $chartHarian = []; - for ($i = 6; $i >= 0; $i--) { - $tgl = now()->subDays($i)->format('Y-m-d'); - $chartHarian[] = $harianRaw[$tgl] ?? 0; - } - - // ========================= - // 🔥 MINGGUAN (4 MINGGU TERAKHIR) - // ========================= - $chartMingguan = []; - for ($i = 3; $i >= 0; $i--) { - $start = now()->subWeeks($i)->startOfWeek(); - $end = now()->subWeeks($i)->endOfWeek(); - - $total = Layanan::whereBetween('created_at', [$start, $end])->count(); - $chartMingguan[] = $total; - } - - // ========================= - // 🔥 TAHUNAN (4 TAHUN TERAKHIR) - // ========================= - $tahunanRaw = Layanan::selectRaw("YEAR(created_at) as tahun, COUNT(*) as total") - ->groupBy('tahun') - ->pluck('total','tahun'); - - $chartTahunan = []; - $tahunSekarang = now()->year; - - for ($i = 3; $i >= 0; $i--) { - $tahun = $tahunSekarang - $i; - $chartTahunan[] = $tahunanRaw[$tahun] ?? 0; - } - - return view('admin.dashboard', compact( - 'totalPenghuni', - 'totalRumah', - 'totalPengaduan', - 'totalIuran', - 'chartHarian', - 'chartMingguan', - 'chartBulanan', - 'chartTahunan' - )); -}} diff --git a/.history/app/Http/Controllers/DashboardController_20260507082214.php b/.history/app/Http/Controllers/DashboardController_20260507082214.php deleted file mode 100644 index 78f7eb0..0000000 --- a/.history/app/Http/Controllers/DashboardController_20260507082214.php +++ /dev/null @@ -1,140 +0,0 @@ -id; // rt_id di tabel rumah = user id si RT - - // Statistik status layanan - $statistik = Layanan::selectRaw('status, COUNT(*) as total') - ->groupBy('status') - ->pluck('total', 'status'); - - $diajukan = $statistik['diajukan'] ?? 0; - $menunggu = $statistik['menunggu'] ?? 0; - $selesai = $statistik['selesai'] ?? 0; - - // ── PER RT ── - $rt1Id = 13; // blok D - $rt2Id = 19; // blok E - $rt3Id = 28; // blok C - // (blok B = 34, kalau ada RT ke-4) - - $rt1_penghuni = Penghuni::whereHas('rumah', fn($q) => $q->where('rt_id', $rt1Id))->count(); - $rt2_penghuni = Penghuni::whereHas('rumah', fn($q) => $q->where('rt_id', $rt2Id))->count(); - $rt3_penghuni = Penghuni::whereHas('rumah', fn($q) => $q->where('rt_id', $rt3Id))->count(); - - $rt1_rumah_terisi = Rumah::where('rt_id', $rt1Id)->where('status', 'Terisi')->count(); - $rt2_rumah_terisi = Rumah::where('rt_id', $rt2Id)->where('status', 'Terisi')->count(); - $rt3_rumah_terisi = Rumah::where('rt_id', $rt3Id)->where('status', 'Terisi')->count(); - - $rt1_rumah_total = Rumah::where('rt_id', $rt1Id)->count(); - $rt2_rumah_total = Rumah::where('rt_id', $rt2Id)->count(); - $rt3_rumah_total = Rumah::where('rt_id', $rt3Id)->count(); - - return view('rt.dashboard', [ - 'totalPenghuni' => Penghuni::count(), - 'totalRumah' => Rumah::count(), - 'totalIuran' => Iuran::count(), - 'totalPengaduan' => Layanan::count(), - 'menungguRT' => $diajukan, - 'menungguAdmin' => $menunggu, - 'diajukan' => $diajukan, - 'menunggu' => $menunggu, - 'selesai' => $selesai, - - // ── tambahan per RT ── - 'rt1_penghuni' => $rt1_penghuni, - 'rt2_penghuni' => $rt2_penghuni, - 'rt3_penghuni' => $rt3_penghuni, - 'rt1_rumah_terisi'=> $rt1_rumah_terisi, - 'rt2_rumah_terisi'=> $rt2_rumah_terisi, - 'rt3_rumah_terisi'=> $rt3_rumah_terisi, - 'rt1_rumah_total' => $rt1_rumah_total, - 'rt2_rumah_total' => $rt2_rumah_total, - 'rt3_rumah_total' => $rt3_rumah_total, - ]); - } - - // 🔥 DASHBOARD ADMIN - public function admin() - { - $totalPenghuni = Penghuni::count(); - $totalRumah = Rumah::count(); - $totalPengaduan = Layanan::count(); - $totalIuran = Iuran::sum('jumlah'); - - // ========================= - // 🔥 BULANAN (REAL - 12 BULAN) - // ========================= - $chartBulananRaw = Layanan::selectRaw("MONTH(created_at) as bulan, COUNT(*) as total") - ->groupBy('bulan') - ->pluck('total','bulan'); - - $chartBulanan = []; - for ($i = 1; $i <= 12; $i++) { - $chartBulanan[] = $chartBulananRaw[$i] ?? 0; - } - - // ========================= - // 🔥 HARIAN (7 HARI TERAKHIR) - // ========================= - $harianRaw = Layanan::selectRaw("DATE(created_at) as tgl, COUNT(*) as total") - ->whereDate('created_at', '>=', now()->subDays(6)) - ->groupBy('tgl') - ->pluck('total','tgl'); - - $chartHarian = []; - for ($i = 6; $i >= 0; $i--) { - $tgl = now()->subDays($i)->format('Y-m-d'); - $chartHarian[] = $harianRaw[$tgl] ?? 0; - } - - // ========================= - // 🔥 MINGGUAN (4 MINGGU TERAKHIR) - // ========================= - $chartMingguan = []; - for ($i = 3; $i >= 0; $i--) { - $start = now()->subWeeks($i)->startOfWeek(); - $end = now()->subWeeks($i)->endOfWeek(); - - $total = Layanan::whereBetween('created_at', [$start, $end])->count(); - $chartMingguan[] = $total; - } - - // ========================= - // 🔥 TAHUNAN (4 TAHUN TERAKHIR) - // ========================= - $tahunanRaw = Layanan::selectRaw("YEAR(created_at) as tahun, COUNT(*) as total") - ->groupBy('tahun') - ->pluck('total','tahun'); - - $chartTahunan = []; - $tahunSekarang = now()->year; - - for ($i = 3; $i >= 0; $i--) { - $tahun = $tahunSekarang - $i; - $chartTahunan[] = $tahunanRaw[$tahun] ?? 0; - } - - return view('admin.dashboard', compact( - 'totalPenghuni', - 'totalRumah', - 'totalPengaduan', - 'totalIuran', - 'chartHarian', - 'chartMingguan', - 'chartBulanan', - 'chartTahunan' - )); - }} diff --git a/.history/app/Http/Controllers/DashboardController_20260507082225.php b/.history/app/Http/Controllers/DashboardController_20260507082225.php deleted file mode 100644 index 83ca75a..0000000 --- a/.history/app/Http/Controllers/DashboardController_20260507082225.php +++ /dev/null @@ -1,141 +0,0 @@ -id; // rt_id di tabel rumah = user id si RT - - // Statistik status layanan - $statistik = Layanan::selectRaw('status, COUNT(*) as total') - ->groupBy('status') - ->pluck('total', 'status'); - - $diajukan = $statistik['diajukan'] ?? 0; - $menunggu = $statistik['menunggu'] ?? 0; - $selesai = $statistik['selesai'] ?? 0; - - // ── PER RT ── - $rt1Id = 13; // blok D - $rt2Id = 19; // blok E - $rt3Id = 28; // blok C - // (blok B = 34, kalau ada RT ke-4) - - $rt1_penghuni = Penghuni::whereHas('rumah', fn($q) => $q->where('rt_id', $rt1Id))->count(); - $rt2_penghuni = Penghuni::whereHas('rumah', fn($q) => $q->where('rt_id', $rt2Id))->count(); - $rt3_penghuni = Penghuni::whereHas('rumah', fn($q) => $q->where('rt_id', $rt3Id))->count(); - - $rt1_rumah_terisi = Rumah::where('rt_id', $rt1Id)->where('status', 'Terisi')->count(); - $rt2_rumah_terisi = Rumah::where('rt_id', $rt2Id)->where('status', 'Terisi')->count(); - $rt3_rumah_terisi = Rumah::where('rt_id', $rt3Id)->where('status', 'Terisi')->count(); - - $rt1_rumah_total = Rumah::where('rt_id', $rt1Id)->count(); - $rt2_rumah_total = Rumah::where('rt_id', $rt2Id)->count(); - $rt3_rumah_total = Rumah::where('rt_id', $rt3Id)->count(); - - return view('rt.dashboard', [ - 'totalPenghuni' => Penghuni::count(), - 'totalRumah' => Rumah::count(), - 'totalIuran' => Iuran::count(), - 'totalPengaduan' => Layanan::count(), - 'menungguRT' => $diajukan, - 'menungguAdmin' => $menunggu, - 'diajukan' => $diajukan, - 'menunggu' => $menunggu, - 'selesai' => $selesai, - - // ── tambahan per RT ── - 'rt1_penghuni' => $rt1_penghuni, - 'rt2_penghuni' => $rt2_penghuni, - 'rt3_penghuni' => $rt3_penghuni, - 'rt1_rumah_terisi'=> $rt1_rumah_terisi, - 'rt2_rumah_terisi'=> $rt2_rumah_terisi, - 'rt3_rumah_terisi'=> $rt3_rumah_terisi, - 'rt1_rumah_total' => $rt1_rumah_total, - 'rt2_rumah_total' => $rt2_rumah_total, - 'rt3_rumah_total' => $rt3_rumah_total, - ]); - } - - // 🔥 DASHBOARD ADMIN - public function admin() - { - $totalPenghuni = Penghuni::count(); - $totalRumah = Rumah::count(); - $totalPengaduan = Layanan::count(); - $totalIuran = Iuran::sum('jumlah'); - - // ========================= - // 🔥 BULANAN (REAL - 12 BULAN) - // ========================= - $chartBulananRaw = Layanan::selectRaw("MONTH(created_at) as bulan, COUNT(*) as total") - ->groupBy('bulan') - ->pluck('total','bulan'); - - $chartBulanan = []; - for ($i = 1; $i <= 12; $i++) { - $chartBulanan[] = $chartBulananRaw[$i] ?? 0; - } - - // ========================= - // 🔥 HARIAN (7 HARI TERAKHIR) - // ========================= - $harianRaw = Layanan::selectRaw("DATE(created_at) as tgl, COUNT(*) as total") - ->whereDate('created_at', '>=', now()->subDays(6)) - ->groupBy('tgl') - ->pluck('total','tgl'); - - $chartHarian = []; - for ($i = 6; $i >= 0; $i--) { - $tgl = now()->subDays($i)->format('Y-m-d'); - $chartHarian[] = $harianRaw[$tgl] ?? 0; - } - - // ========================= - // 🔥 MINGGUAN (4 MINGGU TERAKHIR) - // ========================= - $chartMingguan = []; - for ($i = 3; $i >= 0; $i--) { - $start = now()->subWeeks($i)->startOfWeek(); - $end = now()->subWeeks($i)->endOfWeek(); - - $total = Layanan::whereBetween('created_at', [$start, $end])->count(); - $chartMingguan[] = $total; - } - - // ========================= - // 🔥 TAHUNAN (4 TAHUN TERAKHIR) - // ========================= - $tahunanRaw = Layanan::selectRaw("YEAR(created_at) as tahun, COUNT(*) as total") - ->groupBy('tahun') - ->pluck('total','tahun'); - - $chartTahunan = []; - $tahunSekarang = now()->year; - - for ($i = 3; $i >= 0; $i--) { - $tahun = $tahunSekarang - $i; - $chartTahunan[] = $tahunanRaw[$tahun] ?? 0; - } - - return view('admin.dashboard', compact( - 'totalPenghuni', - 'totalRumah', - 'totalPengaduan', - 'totalIuran', - 'chartHarian', - 'chartMingguan', - 'chartBulanan', - 'chartTahunan' - )); - } - } diff --git a/.history/app/Http/Controllers/DashboardController_20260507082229.php b/.history/app/Http/Controllers/DashboardController_20260507082229.php deleted file mode 100644 index a4b98af..0000000 --- a/.history/app/Http/Controllers/DashboardController_20260507082229.php +++ /dev/null @@ -1,141 +0,0 @@ -id; // rt_id di tabel rumah = user id si RT - - // Statistik status layanan - $statistik = Layanan::selectRaw('status, COUNT(*) as total') - ->groupBy('status') - ->pluck('total', 'status'); - - $diajukan = $statistik['diajukan'] ?? 0; - $menunggu = $statistik['menunggu'] ?? 0; - $selesai = $statistik['selesai'] ?? 0; - - // ── PER RT ── - $rt1Id = 13; // blok D - $rt2Id = 19; // blok E - $rt3Id = 28; // blok C - // (blok B = 34, kalau ada RT ke-4) - - $rt1_penghuni = Penghuni::whereHas('rumah', fn($q) => $q->where('rt_id', $rt1Id))->count(); - $rt2_penghuni = Penghuni::whereHas('rumah', fn($q) => $q->where('rt_id', $rt2Id))->count(); - $rt3_penghuni = Penghuni::whereHas('rumah', fn($q) => $q->where('rt_id', $rt3Id))->count(); - - $rt1_rumah_terisi = Rumah::where('rt_id', $rt1Id)->where('status', 'Terisi')->count(); - $rt2_rumah_terisi = Rumah::where('rt_id', $rt2Id)->where('status', 'Terisi')->count(); - $rt3_rumah_terisi = Rumah::where('rt_id', $rt3Id)->where('status', 'Terisi')->count(); - - $rt1_rumah_total = Rumah::where('rt_id', $rt1Id)->count(); - $rt2_rumah_total = Rumah::where('rt_id', $rt2Id)->count(); - $rt3_rumah_total = Rumah::where('rt_id', $rt3Id)->count(); - - return view('rt.dashboard', [ - 'totalPenghuni' => Penghuni::count(), - 'totalRumah' => Rumah::count(), - 'totalIuran' => Iuran::count(), - 'totalPengaduan' => Layanan::count(), - 'menungguRT' => $diajukan, - 'menungguAdmin' => $menunggu, - 'diajukan' => $diajukan, - 'menunggu' => $menunggu, - 'selesai' => $selesai, - - // ── tambahan per RT ── - 'rt1_penghuni' => $rt1_penghuni, - 'rt2_penghuni' => $rt2_penghuni, - 'rt3_penghuni' => $rt3_penghuni, - 'rt1_rumah_terisi'=> $rt1_rumah_terisi, - 'rt2_rumah_terisi'=> $rt2_rumah_terisi, - 'rt3_rumah_terisi'=> $rt3_rumah_terisi, - 'rt1_rumah_total' => $rt1_rumah_total, - 'rt2_rumah_total' => $rt2_rumah_total, - 'rt3_rumah_total' => $rt3_rumah_total, - ]); - } - - // 🔥 DASHBOARD ADMIN - public function admin() - { - $totalPenghuni = Penghuni::count(); - $totalRumah = Rumah::count(); - $totalPengaduan = Layanan::count(); - $totalIuran = Iuran::sum('jumlah'); - - // ========================= - // 🔥 BULANAN (REAL - 12 BULAN) - // ========================= - $chartBulananRaw = Layanan::selectRaw("MONTH(created_at) as bulan, COUNT(*) as total") - ->groupBy('bulan') - ->pluck('total','bulan'); - - $chartBulanan = []; - for ($i = 1; $i <= 12; $i++) { - $chartBulanan[] = $chartBulananRaw[$i] ?? 0; - } - - // ========================= - // 🔥 HARIAN (7 HARI TERAKHIR) - // ========================= - $harianRaw = Layanan::selectRaw("DATE(created_at) as tgl, COUNT(*) as total") - ->whereDate('created_at', '>=', now()->subDays(6)) - ->groupBy('tgl') - ->pluck('total','tgl'); - - $chartHarian = []; - for ($i = 6; $i >= 0; $i--) { - $tgl = now()->subDays($i)->format('Y-m-d'); - $chartHarian[] = $harianRaw[$tgl] ?? 0; - } - - // ========================= - // 🔥 MINGGUAN (4 MINGGU TERAKHIR) - // ========================= - $chartMingguan = []; - for ($i = 3; $i >= 0; $i--) { - $start = now()->subWeeks($i)->startOfWeek(); - $end = now()->subWeeks($i)->endOfWeek(); - - $total = Layanan::whereBetween('created_at', [$start, $end])->count(); - $chartMingguan[] = $total; - } - - // ========================= - // 🔥 TAHUNAN (4 TAHUN TERAKHIR) - // ========================= - $tahunanRaw = Layanan::selectRaw("YEAR(created_at) as tahun, COUNT(*) as total") - ->groupBy('tahun') - ->pluck('total','tahun'); - - $chartTahunan = []; - $tahunSekarang = now()->year; - - for ($i = 3; $i >= 0; $i--) { - $tahun = $tahunSekarang - $i; - $chartTahunan[] = $tahunanRaw[$tahun] ?? 0; - } - - return view('admin.dashboard', compact( - 'totalPenghuni', - 'totalRumah', - 'totalPengaduan', - 'totalIuran', - 'chartHarian', - 'chartMingguan', - 'chartBulanan', - 'chartTahunan' - )); - } -} diff --git a/.history/app/Http/Controllers/DashboardController_20260507083233.php b/.history/app/Http/Controllers/DashboardController_20260507083233.php deleted file mode 100644 index cea23c9..0000000 --- a/.history/app/Http/Controllers/DashboardController_20260507083233.php +++ /dev/null @@ -1,118 +0,0 @@ -groupBy('status') - ->pluck('total', 'status'); - - $diajukan = $statistik['diajukan'] ?? 0; - $menunggu = $statistik['menunggu'] ?? 0; - $selesai = $statistik['selesai'] ?? 0; - - // Data khusus RT yang sedang login - $totalPenghuni = Penghuni::whereHas('rumah', fn($q) => $q->where('rt_id', $rtId))->count(); - $totalRumah = Rumah::where('rt_id', $rtId)->count(); - $rumahTerisi = Rumah::where('rt_id', $rtId)->where('status', 'Terisi')->count(); - $rumahKosong = Rumah::where('rt_id', $rtId)->where('status', 'Kosong')->count(); - - return view('rt.dashboard', [ - 'totalPenghuni' => $totalPenghuni, - 'totalRumah' => $totalRumah, - 'rumahTerisi' => $rumahTerisi, - 'rumahKosong' => $rumahKosong, - 'totalIuran' => Iuran::count(), - 'totalPengaduan' => Layanan::count(), - 'menungguRT' => $diajukan, - 'menungguAdmin' => $menunggu, - 'diajukan' => $diajukan, - 'menunggu' => $menunggu, - 'selesai' => $selesai, - ]); -} - - // 🔥 DASHBOARD ADMIN - public function admin() - { - $totalPenghuni = Penghuni::count(); - $totalRumah = Rumah::count(); - $totalPengaduan = Layanan::count(); - $totalIuran = Iuran::sum('jumlah'); - - // ========================= - // 🔥 BULANAN (REAL - 12 BULAN) - // ========================= - $chartBulananRaw = Layanan::selectRaw("MONTH(created_at) as bulan, COUNT(*) as total") - ->groupBy('bulan') - ->pluck('total','bulan'); - - $chartBulanan = []; - for ($i = 1; $i <= 12; $i++) { - $chartBulanan[] = $chartBulananRaw[$i] ?? 0; - } - - // ========================= - // 🔥 HARIAN (7 HARI TERAKHIR) - // ========================= - $harianRaw = Layanan::selectRaw("DATE(created_at) as tgl, COUNT(*) as total") - ->whereDate('created_at', '>=', now()->subDays(6)) - ->groupBy('tgl') - ->pluck('total','tgl'); - - $chartHarian = []; - for ($i = 6; $i >= 0; $i--) { - $tgl = now()->subDays($i)->format('Y-m-d'); - $chartHarian[] = $harianRaw[$tgl] ?? 0; - } - - // ========================= - // 🔥 MINGGUAN (4 MINGGU TERAKHIR) - // ========================= - $chartMingguan = []; - for ($i = 3; $i >= 0; $i--) { - $start = now()->subWeeks($i)->startOfWeek(); - $end = now()->subWeeks($i)->endOfWeek(); - - $total = Layanan::whereBetween('created_at', [$start, $end])->count(); - $chartMingguan[] = $total; - } - - // ========================= - // 🔥 TAHUNAN (4 TAHUN TERAKHIR) - // ========================= - $tahunanRaw = Layanan::selectRaw("YEAR(created_at) as tahun, COUNT(*) as total") - ->groupBy('tahun') - ->pluck('total','tahun'); - - $chartTahunan = []; - $tahunSekarang = now()->year; - - for ($i = 3; $i >= 0; $i--) { - $tahun = $tahunSekarang - $i; - $chartTahunan[] = $tahunanRaw[$tahun] ?? 0; - } - - return view('admin.dashboard', compact( - 'totalPenghuni', - 'totalRumah', - 'totalPengaduan', - 'totalIuran', - 'chartHarian', - 'chartMingguan', - 'chartBulanan', - 'chartTahunan' - )); - } -} diff --git a/.history/app/Http/Controllers/DashboardController_20260622095816.php b/.history/app/Http/Controllers/DashboardController_20260622095816.php new file mode 100644 index 0000000..a326a4b --- /dev/null +++ b/.history/app/Http/Controllers/DashboardController_20260622095816.php @@ -0,0 +1,118 @@ +groupBy('status') + ->pluck('total', 'status'); + + $diajukan = $statistik['diajukan'] ?? 0; + $menunggu = $statistik['menunggu'] ?? 0; + $selesai = $statistik['selesai'] ?? 0; + + // Data khusus RT yang sedang login + $totalPenghuni = Penghuni::whereHas('rumah', fn($q) => $q->where('rt_id', $rtId))->count(); + $totalRumah = Rumah::where('rt_id', $rtId)->count(); + $rumahTerisi = Rumah::where('rt_id', $rtId)->where('status', 'Terisi')->count(); + $rumahKosong = Rumah::where('rt_id', $rtId)->where('status', 'Kosong')->count(); + + return view('rt.dashboard', [ + 'totalPenghuni' => $totalPenghuni, + 'totalRumah' => $totalRumah, + 'rumahTerisi' => $rumahTerisi, + 'rumahKosong' => $rumahKosong, + 'totalIuran' => Iuran::count(), + 'totalPengaduan' => Layanan::count(), + 'menungguRT' => $diajukan, + 'menungguAdmin' => $menunggu, + 'diajukan' => $diajukan, + 'menunggu' => $menunggu, + 'selesai' => $selesai, + ]); + } + + // 🔥 DASHBOARD ADMIN + public function admin() + { + $totalPenghuni = Penghuni::count(); + $totalRumah = Rumah::count(); + $totalPengaduan = Layanan::count(); + $totalIuran = Iuran::sum('jumlah'); + + // ========================= + // 🔥 BULANAN (REAL - 12 BULAN) + // ========================= + $chartBulananRaw = Layanan::selectRaw("MONTH(created_at) as bulan, COUNT(*) as total") + ->groupBy('bulan') + ->pluck('total','bulan'); + + $chartBulanan = []; + for ($i = 1; $i <= 12; $i++) { + $chartBulanan[] = $chartBulananRaw[$i] ?? 0; + } + + // ========================= + // 🔥 HARIAN (7 HARI TERAKHIR) + // ========================= + $harianRaw = Layanan::selectRaw("DATE(created_at) as tgl, COUNT(*) as total") + ->whereDate('created_at', '>=', now()->subDays(6)) + ->groupBy('tgl') + ->pluck('total','tgl'); + + $chartHarian = []; + for ($i = 6; $i >= 0; $i--) { + $tgl = now()->subDays($i)->format('Y-m-d'); + $chartHarian[] = $harianRaw[$tgl] ?? 0; + } + + // ========================= + // 🔥 MINGGUAN (4 MINGGU TERAKHIR) + // ========================= + $chartMingguan = []; + for ($i = 3; $i >= 0; $i--) { + $start = now()->subWeeks($i)->startOfWeek(); + $end = now()->subWeeks($i)->endOfWeek(); + + $total = Layanan::whereBetween('created_at', [$start, $end])->count(); + $chartMingguan[] = $total; + } + + // ========================= + // 🔥 TAHUNAN (4 TAHUN TERAKHIR) + // ========================= + $tahunanRaw = Layanan::selectRaw("YEAR(created_at) as tahun, COUNT(*) as total") + ->groupBy('tahun') + ->pluck('total','tahun'); + + $chartTahunan = []; + $tahunSekarang = now()->year; + + for ($i = 3; $i >= 0; $i--) { + $tahun = $tahunSekarang - $i; + $chartTahunan[] = $tahunanRaw[$tahun] ?? 0; + } + + return view('admin.dashboard', compact( + 'totalPenghuni', + 'totalRumah', + 'totalPengaduan', + 'totalIuran', + 'chartHarian', + 'chartMingguan', + 'chartBulanan', + 'chartTahunan' + )); + } +} diff --git a/.history/app/Http/Controllers/DashboardController_20260520084156.php b/.history/app/Http/Controllers/DashboardController_20260622095819.php similarity index 100% rename from .history/app/Http/Controllers/DashboardController_20260520084156.php rename to .history/app/Http/Controllers/DashboardController_20260622095819.php diff --git a/.history/app/Http/Controllers/DashboardController_20260622095829.php b/.history/app/Http/Controllers/DashboardController_20260622095829.php new file mode 100644 index 0000000..d519496 --- /dev/null +++ b/.history/app/Http/Controllers/DashboardController_20260622095829.php @@ -0,0 +1,121 @@ +groupBy('status') + ->pluck('total', 'status'); + + $diajukan = $statistik['diajukan'] ?? 0; + $menunggu = $statistik['menunggu'] ?? 0; + $selesai = $statistik['selesai'] ?? 0; + + // Data khusus RT yang sedang login + $totalPenghuni = Penghuni::whereHas('rumah', fn($q) => $q->where('rt_id', $rtId))->count(); + $totalRumah = Rumah::where('rt_id', $rtId)->count(); + $rumahTerisi = Rumah::where('rt_id', $rtId)->where('status', 'Terisi')->count(); + $rumahKosong = Rumah::where('rt_id', $rtId)->where('status', 'Kosong')->count(); + + return view('rt.dashboard', [ + 'totalPenghuni' => $totalPenghuni, + 'totalRumah' => $totalRumah, + 'rumahTerisi' => $rumahTerisi, + 'rumahKosong' => $rumahKosong, + 'totalIuran' => Iuran::count(), + 'totalPengaduan' => Layanan::count(), + 'menungguRT' => $diajukan, + 'menungguAdmin' => $menunggu, + 'diajukan' => $diajukan, + 'menunggu' => $menunggu, + 'selesai' => $selesai, + ]); + } + + // 🔥 DASHBOARD ADMIN + public function admin() + { + $totalPenghuni = Penghuni::count(); + $totalRumah = Rumah::count(); + $totalPengaduan = Layanan::count(); + $totalIuran = Iuran::sum('jumlah'); + + // ========================= + // 🔥 BULANAN (REAL - 12 BULAN) + // ========================= + $chartBulananRaw = Layanan::selectRaw("MONTH(created_at) as bulan, COUNT(*) as total") + ->groupBy('bulan') + ->pluck('total','bulan'); + + $chartBulanan = []; + for ($i = 1; $i <= 12; $i++) { + $chartBulanan[] = $chartBulananRaw[$i] ?? 0; + } + + // ========================= + // 🔥 HARIAN (7 HARI TERAKHIR) + // ========================= + $harianRaw = Layanan::selectRaw("DATE(created_at) as tgl, COUNT(*) as total") + ->whereDate('created_at', '>=', now()->subDays(6)) + ->groupBy('tgl') + ->pluck('total','tgl'); + + $chartHarian = []; + for ($i = 6; $i >= 0; $i--) { + $tgl = now()->subDays($i)->format('Y-m-d'); + $chartHarian[] = $harianRaw[$tgl] ?? 0; + } + + // ========================= + // 🔥 MINGGUAN (4 MINGGU TERAKHIR) + // ========================= + $chartMingguan = []; + for ($i = 3; $i >= 0; $i--) { + $start = now()->subWeeks($i)->startOfWeek(); + $end = now()->subWeeks($i)->endOfWeek(); + + $total = Layanan::whereBetween('created_at', [$start, $end])->count(); + $chartMingguan[] = $total; + } + + // ========================= + // 🔥 TAHUNAN (4 TAHUN TERAKHIR) + // ========================= + $tahunanRaw = Layanan::selectRaw("YEAR(created_at) as tahun, COUNT(*) as total") + ->groupBy('tahun') + ->pluck('total','tahun'); + + $chartTahunan = []; + $tahunSekarang = now()->year; + + for ($i = 3; $i >= 0; $i--) { + $tahun = $tahunSekarang - $i; + $chartTahunan[] = $tahunanRaw[$tahun] ?? 0; + } + + return view('admin.dashboard', compact( + 'totalPenghuni', + 'totalRumah', + 'totalPengaduan', + 'totalIuran', + 'chartHarian', + 'chartMingguan', + 'chartBulanan', + 'chartTahunan' + )); + } +} diff --git a/.history/app/Http/Controllers/DashboardController_20260622095850.php b/.history/app/Http/Controllers/DashboardController_20260622095850.php new file mode 100644 index 0000000..e262744 --- /dev/null +++ b/.history/app/Http/Controllers/DashboardController_20260622095850.php @@ -0,0 +1,166 @@ +groupBy('status') + ->pluck('total', 'status'); + + $diajukan = $statistik['diajukan'] ?? 0; + $menunggu = $statistik['menunggu'] ?? 0; + $selesai = $statistik['selesai'] ?? 0; + + // Data khusus RT yang sedang login + $totalPenghuni = Penghuni::whereHas('rumah', fn($q) => $q->where('rt_id', $rtId))->count(); + $totalRumah = Rumah::where('rt_id', $rtId)->count(); + $rumahTerisi = Rumah::where('rt_id', $rtId)->where('status', 'Terisi')->count(); + $rumahKosong = Rumah::where('rt_id', $rtId)->where('status', 'Kosong')->count(); + + // Data bendahara aktif milik RT ini + $bendaharaAktif = User::where('rt_id', $rtId) + ->where('role', 'bendahara') + ->where('status_akun', 'aktif') + ->first(); + + $menungguKonfirmasi = 0; + $lunasBuilanIni = 0; + $saldoKas = 0; + $rekapBelumDikirim = 0; + $tagihanKasBelumBayar = 0; + + if ($bendaharaAktif) { + $menungguKonfirmasi = Iuran::where('dibuat_oleh', $bendaharaAktif->id) + ->where('status', 'menunggu') + ->count(); + + $lunasBuilanIni = Iuran::where('dibuat_oleh', $bendaharaAktif->id) + ->where('status', 'lunas') + ->whereMonth('updated_at', now()->month) + ->whereYear('updated_at', now()->year) + ->count(); + + $kas = KasBendahara::where('bendahara_id', $bendaharaAktif->id) + ->whereIn('status', ['manual', 'lunas']) + ->get(); + $saldoKas = $kas->where('jenis', 'masuk')->sum('jumlah') + - $kas->where('jenis', 'keluar')->sum('jumlah'); + + $rekapBelumDikirim = Iuran::where('dibuat_oleh', $bendaharaAktif->id) + ->where('status', 'lunas') + ->whereNull('rekap_id') + ->count(); + + $tagihanKasBelumBayar = KasBendahara::where('bendahara_id', $bendaharaAktif->id) + ->where('status', 'menunggu_bayar') + ->count(); + } + + return view('rt.dashboard', [ + 'totalPenghuni' => $totalPenghuni, + 'totalRumah' => $totalRumah, + 'rumahTerisi' => $rumahTerisi, + 'rumahKosong' => $rumahKosong, + 'totalIuran' => Iuran::count(), + 'totalPengaduan' => Layanan::count(), + 'menungguRT' => $diajukan, + 'menungguAdmin' => $menunggu, + 'diajukan' => $diajukan, + 'menunggu' => $menunggu, + 'selesai' => $selesai, + 'bendaharaAktif' => $bendaharaAktif, + 'menungguKonfirmasi' => $menungguKonfirmasi, + 'lunasBuilanIni' => $lunasBuilanIni, + 'saldoKas' => $saldoKas, + 'rekapBelumDikirim' => $rekapBelumDikirim, + 'tagihanKasBelumBayar' => $tagihanKasBelumBayar, + ]); + } + + // 🔥 DASHBOARD ADMIN + public function admin() + { + $totalPenghuni = Penghuni::count(); + $totalRumah = Rumah::count(); + $totalPengaduan = Layanan::count(); + $totalIuran = Iuran::sum('jumlah'); + + // ========================= + // 🔥 BULANAN (REAL - 12 BULAN) + // ========================= + $chartBulananRaw = Layanan::selectRaw("MONTH(created_at) as bulan, COUNT(*) as total") + ->groupBy('bulan') + ->pluck('total','bulan'); + + $chartBulanan = []; + for ($i = 1; $i <= 12; $i++) { + $chartBulanan[] = $chartBulananRaw[$i] ?? 0; + } + + // ========================= + // 🔥 HARIAN (7 HARI TERAKHIR) + // ========================= + $harianRaw = Layanan::selectRaw("DATE(created_at) as tgl, COUNT(*) as total") + ->whereDate('created_at', '>=', now()->subDays(6)) + ->groupBy('tgl') + ->pluck('total','tgl'); + + $chartHarian = []; + for ($i = 6; $i >= 0; $i--) { + $tgl = now()->subDays($i)->format('Y-m-d'); + $chartHarian[] = $harianRaw[$tgl] ?? 0; + } + + // ========================= + // 🔥 MINGGUAN (4 MINGGU TERAKHIR) + // ========================= + $chartMingguan = []; + for ($i = 3; $i >= 0; $i--) { + $start = now()->subWeeks($i)->startOfWeek(); + $end = now()->subWeeks($i)->endOfWeek(); + + $total = Layanan::whereBetween('created_at', [$start, $end])->count(); + $chartMingguan[] = $total; + } + + // ========================= + // 🔥 TAHUNAN (4 TAHUN TERAKHIR) + // ========================= + $tahunanRaw = Layanan::selectRaw("YEAR(created_at) as tahun, COUNT(*) as total") + ->groupBy('tahun') + ->pluck('total','tahun'); + + $chartTahunan = []; + $tahunSekarang = now()->year; + + for ($i = 3; $i >= 0; $i--) { + $tahun = $tahunSekarang - $i; + $chartTahunan[] = $tahunanRaw[$tahun] ?? 0; + } + + return view('admin.dashboard', compact( + 'totalPenghuni', + 'totalRumah', + 'totalPengaduan', + 'totalIuran', + 'chartHarian', + 'chartMingguan', + 'chartBulanan', + 'chartTahunan' + )); + } +} diff --git a/.history/app/Http/Controllers/DashboardController_20260622100905.php b/.history/app/Http/Controllers/DashboardController_20260622100905.php new file mode 100644 index 0000000..728f815 --- /dev/null +++ b/.history/app/Http/Controllers/DashboardController_20260622100905.php @@ -0,0 +1,178 @@ +groupBy('status') + ->pluck('total', 'status'); + + $diajukan = $statistik['diajukan'] ?? 0; + $menunggu = $statistik['menunggu'] ?? 0; + $selesai = $statistik['selesai'] ?? 0; + + // Data chart bulanan real (12 bulan) + $chartDiajukan = []; + $chartMenunggu = []; + $chartSelesai = []; + for ($i = 11; $i >= 0; $i--) { + $bulan = now()->subMonths($i)->month; + $tahun = now()->subMonths($i)->year; + $chartDiajukan[] = Layanan::where('status','diajukan')->whereMonth('created_at',$bulan)->whereYear('created_at',$tahun)->count(); + $chartMenunggu[] = Layanan::where('status','menunggu')->whereMonth('created_at',$bulan)->whereYear('created_at',$tahun)->count(); + $chartSelesai[] = Layanan::where('status','selesai')->whereMonth('created_at',$bulan)->whereYear('created_at',$tahun)->count(); + } + + // Data khusus RT yang sedang login + $totalPenghuni = Penghuni::whereHas('rumah', fn($q) => $q->where('rt_id', $rtId))->count(); + $totalRumah = Rumah::where('rt_id', $rtId)->count(); + $rumahTerisi = Rumah::where('rt_id', $rtId)->where('status', 'Terisi')->count(); + $rumahKosong = Rumah::where('rt_id', $rtId)->where('status', 'Kosong')->count(); + + // Data bendahara aktif milik RT ini + $bendaharaAktif = User::where('rt_id', $rtId) + ->where('role', 'bendahara') + ->where('status_akun', 'aktif') + ->first(); + + $menungguKonfirmasi = 0; + $lunasBuilanIni = 0; + $saldoKas = 0; + $rekapBelumDikirim = 0; + $tagihanKasBelumBayar = 0; + + if ($bendaharaAktif) { + $menungguKonfirmasi = Iuran::where('dibuat_oleh', $bendaharaAktif->id) + ->where('status', 'menunggu') + ->count(); + + $lunasBuilanIni = Iuran::where('dibuat_oleh', $bendaharaAktif->id) + ->where('status', 'lunas') + ->whereMonth('updated_at', now()->month) + ->whereYear('updated_at', now()->year) + ->count(); + + $kas = KasBendahara::where('bendahara_id', $bendaharaAktif->id) + ->whereIn('status', ['manual', 'lunas']) + ->get(); + $saldoKas = $kas->where('jenis', 'masuk')->sum('jumlah') + - $kas->where('jenis', 'keluar')->sum('jumlah'); + + $rekapBelumDikirim = Iuran::where('dibuat_oleh', $bendaharaAktif->id) + ->where('status', 'lunas') + ->whereNull('rekap_id') + ->count(); + + $tagihanKasBelumBayar = KasBendahara::where('bendahara_id', $bendaharaAktif->id) + ->where('status', 'menunggu_bayar') + ->count(); + } + + return view('rt.dashboard', [ + 'totalPenghuni' => $totalPenghuni, + 'totalRumah' => $totalRumah, + 'rumahTerisi' => $rumahTerisi, + 'rumahKosong' => $rumahKosong, + 'totalIuran' => Iuran::count(), + 'totalPengaduan' => Layanan::count(), + 'menungguRT' => $diajukan, + 'menungguAdmin' => $menunggu, + 'diajukan' => $diajukan, + 'menunggu' => $menunggu, + 'selesai' => $selesai, + 'bendaharaAktif' => $bendaharaAktif, + 'menungguKonfirmasi' => $menungguKonfirmasi, + 'lunasBuilanIni' => $lunasBuilanIni, + 'saldoKas' => $saldoKas, + 'rekapBelumDikirim' => $rekapBelumDikirim, + 'tagihanKasBelumBayar' => $tagihanKasBelumBayar, + ]); + } + + // 🔥 DASHBOARD ADMIN + public function admin() + { + $totalPenghuni = Penghuni::count(); + $totalRumah = Rumah::count(); + $totalPengaduan = Layanan::count(); + $totalIuran = Iuran::sum('jumlah'); + + // ========================= + // 🔥 BULANAN (REAL - 12 BULAN) + // ========================= + $chartBulananRaw = Layanan::selectRaw("MONTH(created_at) as bulan, COUNT(*) as total") + ->groupBy('bulan') + ->pluck('total','bulan'); + + $chartBulanan = []; + for ($i = 1; $i <= 12; $i++) { + $chartBulanan[] = $chartBulananRaw[$i] ?? 0; + } + + // ========================= + // 🔥 HARIAN (7 HARI TERAKHIR) + // ========================= + $harianRaw = Layanan::selectRaw("DATE(created_at) as tgl, COUNT(*) as total") + ->whereDate('created_at', '>=', now()->subDays(6)) + ->groupBy('tgl') + ->pluck('total','tgl'); + + $chartHarian = []; + for ($i = 6; $i >= 0; $i--) { + $tgl = now()->subDays($i)->format('Y-m-d'); + $chartHarian[] = $harianRaw[$tgl] ?? 0; + } + + // ========================= + // 🔥 MINGGUAN (4 MINGGU TERAKHIR) + // ========================= + $chartMingguan = []; + for ($i = 3; $i >= 0; $i--) { + $start = now()->subWeeks($i)->startOfWeek(); + $end = now()->subWeeks($i)->endOfWeek(); + + $total = Layanan::whereBetween('created_at', [$start, $end])->count(); + $chartMingguan[] = $total; + } + + // ========================= + // 🔥 TAHUNAN (4 TAHUN TERAKHIR) + // ========================= + $tahunanRaw = Layanan::selectRaw("YEAR(created_at) as tahun, COUNT(*) as total") + ->groupBy('tahun') + ->pluck('total','tahun'); + + $chartTahunan = []; + $tahunSekarang = now()->year; + + for ($i = 3; $i >= 0; $i--) { + $tahun = $tahunSekarang - $i; + $chartTahunan[] = $tahunanRaw[$tahun] ?? 0; + } + + return view('admin.dashboard', compact( + 'totalPenghuni', + 'totalRumah', + 'totalPengaduan', + 'totalIuran', + 'chartHarian', + 'chartMingguan', + 'chartBulanan', + 'chartTahunan' + )); + } +} diff --git a/.history/app/Http/Controllers/DashboardController_20260622100935.php b/.history/app/Http/Controllers/DashboardController_20260622100935.php new file mode 100644 index 0000000..1d852c0 --- /dev/null +++ b/.history/app/Http/Controllers/DashboardController_20260622100935.php @@ -0,0 +1,181 @@ +groupBy('status') + ->pluck('total', 'status'); + + $diajukan = $statistik['diajukan'] ?? 0; + $menunggu = $statistik['menunggu'] ?? 0; + $selesai = $statistik['selesai'] ?? 0; + + // Data chart bulanan real (12 bulan) + $chartDiajukan = []; + $chartMenunggu = []; + $chartSelesai = []; + for ($i = 11; $i >= 0; $i--) { + $bulan = now()->subMonths($i)->month; + $tahun = now()->subMonths($i)->year; + $chartDiajukan[] = Layanan::where('status','diajukan')->whereMonth('created_at',$bulan)->whereYear('created_at',$tahun)->count(); + $chartMenunggu[] = Layanan::where('status','menunggu')->whereMonth('created_at',$bulan)->whereYear('created_at',$tahun)->count(); + $chartSelesai[] = Layanan::where('status','selesai')->whereMonth('created_at',$bulan)->whereYear('created_at',$tahun)->count(); + } + + // Data khusus RT yang sedang login + $totalPenghuni = Penghuni::whereHas('rumah', fn($q) => $q->where('rt_id', $rtId))->count(); + $totalRumah = Rumah::where('rt_id', $rtId)->count(); + $rumahTerisi = Rumah::where('rt_id', $rtId)->where('status', 'Terisi')->count(); + $rumahKosong = Rumah::where('rt_id', $rtId)->where('status', 'Kosong')->count(); + + // Data bendahara aktif milik RT ini + $bendaharaAktif = User::where('rt_id', $rtId) + ->where('role', 'bendahara') + ->where('status_akun', 'aktif') + ->first(); + + $menungguKonfirmasi = 0; + $lunasBuilanIni = 0; + $saldoKas = 0; + $rekapBelumDikirim = 0; + $tagihanKasBelumBayar = 0; + + if ($bendaharaAktif) { + $menungguKonfirmasi = Iuran::where('dibuat_oleh', $bendaharaAktif->id) + ->where('status', 'menunggu') + ->count(); + + $lunasBuilanIni = Iuran::where('dibuat_oleh', $bendaharaAktif->id) + ->where('status', 'lunas') + ->whereMonth('updated_at', now()->month) + ->whereYear('updated_at', now()->year) + ->count(); + + $kas = KasBendahara::where('bendahara_id', $bendaharaAktif->id) + ->whereIn('status', ['manual', 'lunas']) + ->get(); + $saldoKas = $kas->where('jenis', 'masuk')->sum('jumlah') + - $kas->where('jenis', 'keluar')->sum('jumlah'); + + $rekapBelumDikirim = Iuran::where('dibuat_oleh', $bendaharaAktif->id) + ->where('status', 'lunas') + ->whereNull('rekap_id') + ->count(); + + $tagihanKasBelumBayar = KasBendahara::where('bendahara_id', $bendaharaAktif->id) + ->where('status', 'menunggu_bayar') + ->count(); + } + + return view('rt.dashboard', [ + 'totalPenghuni' => $totalPenghuni, + 'totalRumah' => $totalRumah, + 'rumahTerisi' => $rumahTerisi, + 'rumahKosong' => $rumahKosong, + 'totalIuran' => Iuran::count(), + 'totalPengaduan' => Layanan::count(), + 'menungguRT' => $diajukan, + 'menungguAdmin' => $menunggu, + 'diajukan' => $diajukan, + 'menunggu' => $menunggu, + 'selesai' => $selesai, + 'bendaharaAktif' => $bendaharaAktif, + 'menungguKonfirmasi' => $menungguKonfirmasi, + 'lunasBuilanIni' => $lunasBuilanIni, + 'saldoKas' => $saldoKas, + 'rekapBelumDikirim' => $rekapBelumDikirim, + 'tagihanKasBelumBayar' => $tagihanKasBelumBayar, + 'chartDiajukan' => json_encode($chartDiajukan), + 'chartMenunggu' => json_encode($chartMenunggu), + 'chartSelesai' => json_encode($chartSelesai), + ]); + } + + // 🔥 DASHBOARD ADMIN + public function admin() + { + $totalPenghuni = Penghuni::count(); + $totalRumah = Rumah::count(); + $totalPengaduan = Layanan::count(); + $totalIuran = Iuran::sum('jumlah'); + + // ========================= + // 🔥 BULANAN (REAL - 12 BULAN) + // ========================= + $chartBulananRaw = Layanan::selectRaw("MONTH(created_at) as bulan, COUNT(*) as total") + ->groupBy('bulan') + ->pluck('total','bulan'); + + $chartBulanan = []; + for ($i = 1; $i <= 12; $i++) { + $chartBulanan[] = $chartBulananRaw[$i] ?? 0; + } + + // ========================= + // 🔥 HARIAN (7 HARI TERAKHIR) + // ========================= + $harianRaw = Layanan::selectRaw("DATE(created_at) as tgl, COUNT(*) as total") + ->whereDate('created_at', '>=', now()->subDays(6)) + ->groupBy('tgl') + ->pluck('total','tgl'); + + $chartHarian = []; + for ($i = 6; $i >= 0; $i--) { + $tgl = now()->subDays($i)->format('Y-m-d'); + $chartHarian[] = $harianRaw[$tgl] ?? 0; + } + + // ========================= + // 🔥 MINGGUAN (4 MINGGU TERAKHIR) + // ========================= + $chartMingguan = []; + for ($i = 3; $i >= 0; $i--) { + $start = now()->subWeeks($i)->startOfWeek(); + $end = now()->subWeeks($i)->endOfWeek(); + + $total = Layanan::whereBetween('created_at', [$start, $end])->count(); + $chartMingguan[] = $total; + } + + // ========================= + // 🔥 TAHUNAN (4 TAHUN TERAKHIR) + // ========================= + $tahunanRaw = Layanan::selectRaw("YEAR(created_at) as tahun, COUNT(*) as total") + ->groupBy('tahun') + ->pluck('total','tahun'); + + $chartTahunan = []; + $tahunSekarang = now()->year; + + for ($i = 3; $i >= 0; $i--) { + $tahun = $tahunSekarang - $i; + $chartTahunan[] = $tahunanRaw[$tahun] ?? 0; + } + + return view('admin.dashboard', compact( + 'totalPenghuni', + 'totalRumah', + 'totalPengaduan', + 'totalIuran', + 'chartHarian', + 'chartMingguan', + 'chartBulanan', + 'chartTahunan' + )); + } +} diff --git a/.history/app/Http/Controllers/IuranController_20260421225646.php b/.history/app/Http/Controllers/IuranController_20260421225646.php new file mode 100644 index 0000000..bff6f4a --- /dev/null +++ b/.history/app/Http/Controllers/IuranController_20260421225646.php @@ -0,0 +1,185 @@ +role == 'admin') { + $iuran = Iuran::with('penghuni')->get(); + } else { + $iuran = Iuran::with('penghuni') + ->where('rt_id', $user->id) + ->get(); + } + + return view('admin.iuran.index', compact('iuran')); + } + + public function create() + { + $rtId = Auth::id(); + + $penghuni = Penghuni::where('rt_id', $rtId)->get(); + + return view('admin.iuran.create', compact('penghuni')); + } + + public function store(Request $request) + { + $request->validate([ + 'penghuni_id' => 'required', + 'bulan' => 'required', + 'tahun' => 'required', + 'jumlah' => 'required', + 'jenis_iuran' => 'required', + 'keterangan' => 'required', + ]); + + // 🔥 ambil penghuni + $penghuni = Penghuni::findOrFail($request->penghuni_id); + + Iuran::create([ + 'penghuni_id' => $request->penghuni_id, + + // 🔥 FIX UTAMA (ambil dari penghuni) + 'rt_id' => $penghuni->rt_id, + + 'bulan' => $request->bulan, + 'tahun' => $request->tahun, + 'jumlah' => $request->jumlah, + 'jenis_iuran' => $request->jenis_iuran, + 'keterangan' => $request->keterangan, + 'status' => 'belum', + ]); + + // 🔥 WHATSAPP + $penghuni = Penghuni::find($request->penghuni_id); + + if ($penghuni && $penghuni->telepon) { + $nohp = preg_replace('/^0/', '62', $penghuni->telepon); + + $pesan = "Halo {$penghuni->nama},\n"; + $pesan .= "Iuran baru ditambahkan:\n"; + $pesan .= "Bulan: {$request->bulan} {$request->tahun}\n"; + $pesan .= "Jumlah: Rp " . number_format($request->jumlah,0,',','.') . "\n"; + $pesan .= "Jenis: {$request->jenis_iuran}\n"; + $pesan .= "Terima kasih 🙏"; + + Http::withHeaders([ + 'Authorization' => env('FONNTE_TOKEN') + ])->post('https://api.fonnte.com/send', [ + 'target' => $nohp, + 'message' => $pesan, + ]); + } + + return redirect()->route('iuran.index') + ->with('success', 'Data iuran berhasil ditambahkan'); + } + public function edit($id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + $penghuni = Penghuni::where('rt_id', Auth::id())->get(); + + return view('admin.iuran.edit', compact('iuran', 'penghuni')); + } + + public function update(Request $request, $id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + + $request->validate([ + 'penghuni_id' => 'required', + 'bulan' => 'required', + 'tahun' => 'required', + 'jumlah' => 'required', + 'jenis_iuran' => 'required', + 'keterangan' => 'required', + 'status' => 'required', + ]); + + $iuran->update([ + 'penghuni_id' => $request->penghuni_id, + 'bulan' => $request->bulan, + 'tahun' => $request->tahun, + 'jumlah' => $request->jumlah, + 'jenis_iuran' => $request->jenis_iuran, + 'keterangan' => $request->keterangan, + 'status' => $request->status, + 'tanggal_bayar' => $request->status == 'lunas' ? now() : null, + ]); + + return redirect()->route('iuran.index')->with('success', 'Data berhasil diupdate'); + } + + public function destroy($id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + $iuran->delete(); + + return back()->with('success', 'Data berhasil dihapus'); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalPenghuni = Penghuni::count(); + $totalRumah = Rumah::count(); + $totalIuran = Iuran::count(); + $totalPengaduan = Layanan::count(); + + $menungguRT = Iuran::where('rt_id', $rtId) + ->where('status', 'belum') + ->count(); + + $menungguAdmin = Iuran::where('rt_id', $rtId) + ->where('status', 'proses') + ->count(); + + return view('rt.dashboard', compact( + 'totalPenghuni', + 'totalRumah', + 'totalIuran', + 'totalPengaduan', + 'menungguRT', + 'menungguAdmin' + )); + } + + public function approveRT($id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + + $iuran->update([ + 'status' => 'menunggu', + 'tanggal_bayar' => now() + ]); + + return back()->with('success', 'Dikirim ke Admin'); + } + + public function approveAdmin($id) + { + $iuran = Iuran::findOrFail($id); + + $iuran->update([ + 'status' => 'lunas', + 'tanggal_bayar' => now() + ]); + + return back()->with('success', 'Iuran disetujui admin'); + } +} diff --git a/.history/app/Http/Controllers/IuranController_20260615104208.php b/.history/app/Http/Controllers/IuranController_20260615104208.php new file mode 100644 index 0000000..2a5afa3 --- /dev/null +++ b/.history/app/Http/Controllers/IuranController_20260615104208.php @@ -0,0 +1,185 @@ +role == 'admin') { + $iuran = Iuran::with('penghuni')->get(); + } else { + $iuran = Iuran::with('penghuni') + ->where('rt_id', $user->id) + ->get(); + } + + return view('admin.iuran.index', compact('iuran')); + } + + public function create() + { + $rtId = Auth::id(); + + $penghuni = Penghuni::where('rt_id', $rtId)->get(); + + return view('admin.iuran.create', compact('penghuni')); + } + + public function store(Request $request) + { + $request->validate([ + 'penghuni_id' => 'required', + 'bulan' => 'required', + 'tahun' => 'required', + 'jumlah' => 'required', + 'jenis_iuran' => 'required', + 'keterangan' => 'required', + ]); + + // 🔥 ambil penghuni + $penghuni = Penghuni::findOrFail($request->penghuni_id); + + Iuran::create([ + 'penghuni_id' => $request->penghuni_id, + + // 🔥 FIX UTAMA (ambil dari penghuni) + 'rt_id' => $penghuni->rt_id, + + 'bulan' => $request->bulan, + 'tahun' => $request->tahun, + 'jumlah' => $request->jumlah, + 'jenis_iuran' => $request->jenis_iuran, + 'keterangan' => $request->keterangan, + 'status' => 'belum', + ]); + + // 🔥 WHATSAPP + $penghuni = Penghuni::find($request->penghuni_id); + + if ($penghuni && $penghuni->telepon) { + $nohp = preg_replace('/^0/', '62', $penghuni->telepon); + + $pesan = "Halo {$penghuni->nama},\n"; + $pesan .= "Iuran baru ditambahkan:\n"; + $pesan .= "Bulan: {$request->bulan} {$request->tahun}\n"; + $pesan .= "Jumlah: Rp " . number_format($request->jumlah,0,',','.') . "\n"; + $pesan .= "Jenis: {$request->jenis_iuran}\n"; + $pesan .= "Terima kasih 🙏"; + + Http::withHeaders([ + 'Authorization' => env('FONNTE_TOKEN') + ])->post('https://api.fonnte.com/send', [ + 'target' => $nohp, + 'message' => $pesan, + ]); + } + + return redirect()->route('iuran.index') + ->with('success', 'Data iuran berhasil ditambahkan'); + } + public function edit($id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + $penghuni = Penghuni::where('rt_id', Auth::id())->get(); + + return view('admin.iuran.edit', compact('iuran', 'penghuni')); + } + + public function update(Request $request, $id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + + $request->validate([ + 'penghuni_id' => 'required', + 'bulan' => 'required', + 'tahun' => 'required', + 'jumlah' => 'required', + 'jenis_iuran' => 'required', + 'keterangan' => 'required', + 'status' => 'required', + ]); + + $iuran->update([ + 'penghuni_id' => $request->penghuni_id, + 'bulan' => $request->bulan, + 'tahun' => $request->tahun, + 'jumlah' => $request->jumlah, + 'jenis_iuran' => $request->jenis_iuran, + 'keterangan' => $request->keterangan, + 'status' => $request->status, + 'tanggal_bayar' => $request->status == 'lunas' ? now() : null, + ]); + + return redirect()->route('iuran.index')->with('success', 'Data berhasil diupdate'); + } + + public function destroy($id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + $iuran->delete(); + + return back()->with('success', 'Data berhasil dihapus'); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalPenghuni = Penghuni::count(); + $totalRumah = Rumah::count(); + $totalIuran = Iuran::count(); + $totalPengaduan = Layanan::count(); + + $menungguRT = Iuran::where('rt_id', $rtId) + ->where('status', 'belum') + ->count(); + + $menungguAdmin = Iuran::where('rt_id', $rtId) + ->where('status', 'proses') + ->count(); + + return view('rt.dashboard', compact( + 'totalPenghuni', + 'totalRumah', + 'totalIuran', + 'totalPengaduan', + 'menungguRT', + 'menungguAdmin' + )); + } + + public function approveRT($id) +{ + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + + $iuran->update([ + 'status' => 'lunas', // ✅ langsung lunas + 'tanggal_bayar' => now() + ]); + + return back()->with('success', 'Iuran telah disetujui dan dinyatakan lunas'); +} + + public function approveAdmin($id) + { + $iuran = Iuran::findOrFail($id); + + $iuran->update([ + 'status' => 'lunas', + 'tanggal_bayar' => now() + ]); + + return back()->with('success', 'Iuran disetujui admin'); + } +} diff --git a/.history/app/Http/Controllers/IuranController_20260615104211.php b/.history/app/Http/Controllers/IuranController_20260615104211.php new file mode 100644 index 0000000..093c6da --- /dev/null +++ b/.history/app/Http/Controllers/IuranController_20260615104211.php @@ -0,0 +1,185 @@ +role == 'admin') { + $iuran = Iuran::with('penghuni')->get(); + } else { + $iuran = Iuran::with('penghuni') + ->where('rt_id', $user->id) + ->get(); + } + + return view('admin.iuran.index', compact('iuran')); + } + + public function create() + { + $rtId = Auth::id(); + + $penghuni = Penghuni::where('rt_id', $rtId)->get(); + + return view('admin.iuran.create', compact('penghuni')); + } + + public function store(Request $request) + { + $request->validate([ + 'penghuni_id' => 'required', + 'bulan' => 'required', + 'tahun' => 'required', + 'jumlah' => 'required', + 'jenis_iuran' => 'required', + 'keterangan' => 'required', + ]); + + // 🔥 ambil penghuni + $penghuni = Penghuni::findOrFail($request->penghuni_id); + + Iuran::create([ + 'penghuni_id' => $request->penghuni_id, + + // 🔥 FIX UTAMA (ambil dari penghuni) + 'rt_id' => $penghuni->rt_id, + + 'bulan' => $request->bulan, + 'tahun' => $request->tahun, + 'jumlah' => $request->jumlah, + 'jenis_iuran' => $request->jenis_iuran, + 'keterangan' => $request->keterangan, + 'status' => 'belum', + ]); + + // 🔥 WHATSAPP + $penghuni = Penghuni::find($request->penghuni_id); + + if ($penghuni && $penghuni->telepon) { + $nohp = preg_replace('/^0/', '62', $penghuni->telepon); + + $pesan = "Halo {$penghuni->nama},\n"; + $pesan .= "Iuran baru ditambahkan:\n"; + $pesan .= "Bulan: {$request->bulan} {$request->tahun}\n"; + $pesan .= "Jumlah: Rp " . number_format($request->jumlah,0,',','.') . "\n"; + $pesan .= "Jenis: {$request->jenis_iuran}\n"; + $pesan .= "Terima kasih 🙏"; + + Http::withHeaders([ + 'Authorization' => env('FONNTE_TOKEN') + ])->post('https://api.fonnte.com/send', [ + 'target' => $nohp, + 'message' => $pesan, + ]); + } + + return redirect()->route('iuran.index') + ->with('success', 'Data iuran berhasil ditambahkan'); + } + public function edit($id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + $penghuni = Penghuni::where('rt_id', Auth::id())->get(); + + return view('admin.iuran.edit', compact('iuran', 'penghuni')); + } + + public function update(Request $request, $id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + + $request->validate([ + 'penghuni_id' => 'required', + 'bulan' => 'required', + 'tahun' => 'required', + 'jumlah' => 'required', + 'jenis_iuran' => 'required', + 'keterangan' => 'required', + 'status' => 'required', + ]); + + $iuran->update([ + 'penghuni_id' => $request->penghuni_id, + 'bulan' => $request->bulan, + 'tahun' => $request->tahun, + 'jumlah' => $request->jumlah, + 'jenis_iuran' => $request->jenis_iuran, + 'keterangan' => $request->keterangan, + 'status' => $request->status, + 'tanggal_bayar' => $request->status == 'lunas' ? now() : null, + ]); + + return redirect()->route('iuran.index')->with('success', 'Data berhasil diupdate'); + } + + public function destroy($id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + $iuran->delete(); + + return back()->with('success', 'Data berhasil dihapus'); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalPenghuni = Penghuni::count(); + $totalRumah = Rumah::count(); + $totalIuran = Iuran::count(); + $totalPengaduan = Layanan::count(); + + $menungguRT = Iuran::where('rt_id', $rtId) + ->where('status', 'belum') + ->count(); + + $menungguAdmin = Iuran::where('rt_id', $rtId) + ->where('status', 'proses') + ->count(); + + return view('rt.dashboard', compact( + 'totalPenghuni', + 'totalRumah', + 'totalIuran', + 'totalPengaduan', + 'menungguRT', + 'menungguAdmin' + )); + } + + public function approveRT($id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + + $iuran->update([ + 'status' => 'lunas', // ✅ langsung lunas + 'tanggal_bayar' => now() + ]); + + return back()->with('success', 'Iuran telah disetujui dan dinyatakan lunas'); + } + + public function approveAdmin($id) + { + $iuran = Iuran::findOrFail($id); + + $iuran->update([ + 'status' => 'lunas', + 'tanggal_bayar' => now() + ]); + + return back()->with('success', 'Iuran disetujui admin'); + } +} diff --git a/.history/app/Http/Controllers/IuranController_20260615104218.php b/.history/app/Http/Controllers/IuranController_20260615104218.php new file mode 100644 index 0000000..8142423 --- /dev/null +++ b/.history/app/Http/Controllers/IuranController_20260615104218.php @@ -0,0 +1,185 @@ +role == 'admin') { + $iuran = Iuran::with('penghuni')->get(); + } else { + $iuran = Iuran::with('penghuni') + ->where('rt_id', $user->id) + ->get(); + } + + return view('admin.iuran.index', compact('iuran')); + } + + public function create() + { + $rtId = Auth::id(); + + $penghuni = Penghuni::where('rt_id', $rtId)->get(); + + return view('admin.iuran.create', compact('penghuni')); + } + + public function store(Request $request) + { + $request->validate([ + 'penghuni_id' => 'required', + 'bulan' => 'required', + 'tahun' => 'required', + 'jumlah' => 'required', + 'jenis_iuran' => 'required', + 'keterangan' => 'required', + ]); + + // 🔥 ambil penghuni + $penghuni = Penghuni::findOrFail($request->penghuni_id); + + Iuran::create([ + 'penghuni_id' => $request->penghuni_id, + + // 🔥 FIX UTAMA (ambil dari penghuni) + 'rt_id' => $penghuni->rt_id, + + 'bulan' => $request->bulan, + 'tahun' => $request->tahun, + 'jumlah' => $request->jumlah, + 'jenis_iuran' => $request->jenis_iuran, + 'keterangan' => $request->keterangan, + 'status' => 'belum', + ]); + + // 🔥 WHATSAPP + $penghuni = Penghuni::find($request->penghuni_id); + + if ($penghuni && $penghuni->telepon) { + $nohp = preg_replace('/^0/', '62', $penghuni->telepon); + + $pesan = "Halo {$penghuni->nama},\n"; + $pesan .= "Iuran baru ditambahkan:\n"; + $pesan .= "Bulan: {$request->bulan} {$request->tahun}\n"; + $pesan .= "Jumlah: Rp " . number_format($request->jumlah,0,',','.') . "\n"; + $pesan .= "Jenis: {$request->jenis_iuran}\n"; + $pesan .= "Terima kasih 🙏"; + + Http::withHeaders([ + 'Authorization' => env('FONNTE_TOKEN') + ])->post('https://api.fonnte.com/send', [ + 'target' => $nohp, + 'message' => $pesan, + ]); + } + + return redirect()->route('iuran.index') + ->with('success', 'Data iuran berhasil ditambahkan'); + } + public function edit($id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + $penghuni = Penghuni::where('rt_id', Auth::id())->get(); + + return view('admin.iuran.edit', compact('iuran', 'penghuni')); + } + + public function update(Request $request, $id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + + $request->validate([ + 'penghuni_id' => 'required', + 'bulan' => 'required', + 'tahun' => 'required', + 'jumlah' => 'required', + 'jenis_iuran' => 'required', + 'keterangan' => 'required', + 'status' => 'required', + ]); + + $iuran->update([ + 'penghuni_id' => $request->penghuni_id, + 'bulan' => $request->bulan, + 'tahun' => $request->tahun, + 'jumlah' => $request->jumlah, + 'jenis_iuran' => $request->jenis_iuran, + 'keterangan' => $request->keterangan, + 'status' => $request->status, + 'tanggal_bayar' => $request->status == 'lunas' ? now() : null, + ]); + + return redirect()->route('iuran.index')->with('success', 'Data berhasil diupdate'); + } + + public function destroy($id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + $iuran->delete(); + + return back()->with('success', 'Data berhasil dihapus'); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalPenghuni = Penghuni::count(); + $totalRumah = Rumah::count(); + $totalIuran = Iuran::count(); + $totalPengaduan = Layanan::count(); + + $menungguRT = Iuran::where('rt_id', $rtId) + ->where('status', 'belum') + ->count(); + + $menungguAdmin = Iuran::where('rt_id', $rtId) + ->where('status', 'proses') + ->count(); + + return view('rt.dashboard', compact( + 'totalPenghuni', + 'totalRumah', + 'totalIuran', + 'totalPengaduan', + 'menungguRT', + 'menungguAdmin' + )); + } + + public function approveRT($id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + + $iuran->update([ + 'status' => 'lunas', // ✅ langsung lunas + 'tanggal_bayar' => now() + ]); + + return back()->with('success', 'Iuran telah disetujui dan dinyatakan lunas'); + } + + // public function approveAdmin($id) + // { + // $iuran = Iuran::findOrFail($id); + + // $iuran->update([ + // 'status' => 'lunas', + // 'tanggal_bayar' => now() + // ]); + + // return back()->with('success', 'Iuran disetujui admin'); + // } +} diff --git a/.history/app/Http/Controllers/IuranController_20260615175424.php b/.history/app/Http/Controllers/IuranController_20260615175424.php new file mode 100644 index 0000000..a475b83 --- /dev/null +++ b/.history/app/Http/Controllers/IuranController_20260615175424.php @@ -0,0 +1,208 @@ +role == 'admin') { + $iuran = Iuran::with('penghuni')->get(); + } else { + $iuran = Iuran::with('penghuni') + ->where('rt_id', $user->id) + ->get(); + } + + return view('admin.iuran.index', compact('iuran')); + } + + public function create() + { + $rtId = Auth::id(); + + $penghuni = Penghuni::where('rt_id', $rtId)->get(); + + return view('admin.iuran.create', compact('penghuni')); + } + + public function store(Request $request) + { + $request->validate([ + 'penghuni_id' => 'required', + 'bulan' => 'required', + 'tahun' => 'required', + 'jumlah' => 'required', + 'jenis_iuran' => 'required', + 'keterangan' => 'required', + ]); + + // 🔥 ambil penghuni + $penghuni = Penghuni::findOrFail($request->penghuni_id); + + Iuran::create([ + 'penghuni_id' => $request->penghuni_id, + + // 🔥 FIX UTAMA (ambil dari penghuni) + 'rt_id' => $penghuni->rt_id, + + 'bulan' => $request->bulan, + 'tahun' => $request->tahun, + 'jumlah' => $request->jumlah, + 'jenis_iuran' => $request->jenis_iuran, + 'keterangan' => $request->keterangan, + 'status' => 'belum', + ]); + + // 🔥 WHATSAPP + $penghuni = Penghuni::find($request->penghuni_id); + + if ($penghuni && $penghuni->telepon) { + $nohp = preg_replace('/^0/', '62', $penghuni->telepon); + + $pesan = "Halo {$penghuni->nama},\n"; + $pesan .= "Iuran baru ditambahkan:\n"; + $pesan .= "Bulan: {$request->bulan} {$request->tahun}\n"; + $pesan .= "Jumlah: Rp " . number_format($request->jumlah,0,',','.') . "\n"; + $pesan .= "Jenis: {$request->jenis_iuran}\n"; + $pesan .= "Terima kasih 🙏"; + + Http::withHeaders([ + 'Authorization' => env('FONNTE_TOKEN') + ])->post('https://api.fonnte.com/send', [ + 'target' => $nohp, + 'message' => $pesan, + ]); + } + + return redirect()->route('iuran.index') + ->with('success', 'Data iuran berhasil ditambahkan'); + } + public function edit($id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + $penghuni = Penghuni::where('rt_id', Auth::id())->get(); + + return view('admin.iuran.edit', compact('iuran', 'penghuni')); + } + + public function update(Request $request, $id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + + $request->validate([ + 'penghuni_id' => 'required', + 'bulan' => 'required', + 'tahun' => 'required', + 'jumlah' => 'required', + 'jenis_iuran' => 'required', + 'keterangan' => 'required', + 'status' => 'required', + ]); + + $iuran->update([ + 'penghuni_id' => $request->penghuni_id, + 'bulan' => $request->bulan, + 'tahun' => $request->tahun, + 'jumlah' => $request->jumlah, + 'jenis_iuran' => $request->jenis_iuran, + 'keterangan' => $request->keterangan, + 'status' => $request->status, + 'tanggal_bayar' => $request->status == 'lunas' ? now() : null, + ]); + + return redirect()->route('iuran.index')->with('success', 'Data berhasil diupdate'); + } + + public function destroy($id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + $iuran->delete(); + + return back()->with('success', 'Data berhasil dihapus'); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalPenghuni = Penghuni::count(); + $totalRumah = Rumah::count(); + $totalIuran = Iuran::count(); + $totalPengaduan = Layanan::count(); + + $menungguRT = Iuran::where('rt_id', $rtId) + ->where('status', 'belum') + ->count(); + + $menungguAdmin = Iuran::where('rt_id', $rtId) + ->where('status', 'proses') + ->count(); + + return view('rt.dashboard', compact( + 'totalPenghuni', + 'totalRumah', + 'totalIuran', + 'totalPengaduan', + 'menungguRT', + 'menungguAdmin' + )); + } + +public function approveRT($id) +{ + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + + // Pastikan ada bukti sebelum approve + if (!$iuran->bukti_pembayaran) { + return back()->with('error', 'Tidak bisa approve, belum ada bukti pembayaran!'); + } + + $iuran->update([ + 'status' => 'lunas', + 'tanggal_bayar' => now() + ]); + + // Kirim notif WA ke penghuni + $penghuni = $iuran->penghuni; + if ($penghuni && $penghuni->telepon) { + $nohp = preg_replace('/^0/', '62', $penghuni->telepon); + $pesan = "Halo {$penghuni->nama},\n"; + $pesan .= "Pembayaran iuran Anda telah diverifikasi RT.\n"; + $pesan .= "Bulan: {$iuran->bulan} {$iuran->tahun}\n"; + $pesan .= "Jumlah: Rp " . number_format($iuran->jumlah,0,',','.') . "\n"; + $pesan .= "Status: LUNAS ✅\nTerima kasih 🙏"; + + \Illuminate\Support\Facades\Http::withHeaders([ + 'Authorization' => env('FONNTE_TOKEN') + ])->post('https://api.fonnte.com/send', [ + 'target' => $nohp, + 'message' => $pesan, + ]); + } + + return back()->with('success', 'Iuran disetujui dan dinyatakan lunas'); +} + + // public function approveAdmin($id) + // { + // $iuran = Iuran::findOrFail($id); + + // $iuran->update([ + // 'status' => 'lunas', + // 'tanggal_bayar' => now() + // ]); + + // return back()->with('success', 'Iuran disetujui admin'); + // } +} diff --git a/.history/app/Http/Controllers/IuranController_20260615175433.php b/.history/app/Http/Controllers/IuranController_20260615175433.php new file mode 100644 index 0000000..fc46927 --- /dev/null +++ b/.history/app/Http/Controllers/IuranController_20260615175433.php @@ -0,0 +1,208 @@ +role == 'admin') { + $iuran = Iuran::with('penghuni')->get(); + } else { + $iuran = Iuran::with('penghuni') + ->where('rt_id', $user->id) + ->get(); + } + + return view('admin.iuran.index', compact('iuran')); + } + + public function create() + { + $rtId = Auth::id(); + + $penghuni = Penghuni::where('rt_id', $rtId)->get(); + + return view('admin.iuran.create', compact('penghuni')); + } + + public function store(Request $request) + { + $request->validate([ + 'penghuni_id' => 'required', + 'bulan' => 'required', + 'tahun' => 'required', + 'jumlah' => 'required', + 'jenis_iuran' => 'required', + 'keterangan' => 'required', + ]); + + // 🔥 ambil penghuni + $penghuni = Penghuni::findOrFail($request->penghuni_id); + + Iuran::create([ + 'penghuni_id' => $request->penghuni_id, + + // 🔥 FIX UTAMA (ambil dari penghuni) + 'rt_id' => $penghuni->rt_id, + + 'bulan' => $request->bulan, + 'tahun' => $request->tahun, + 'jumlah' => $request->jumlah, + 'jenis_iuran' => $request->jenis_iuran, + 'keterangan' => $request->keterangan, + 'status' => 'belum', + ]); + + // 🔥 WHATSAPP + $penghuni = Penghuni::find($request->penghuni_id); + + if ($penghuni && $penghuni->telepon) { + $nohp = preg_replace('/^0/', '62', $penghuni->telepon); + + $pesan = "Halo {$penghuni->nama},\n"; + $pesan .= "Iuran baru ditambahkan:\n"; + $pesan .= "Bulan: {$request->bulan} {$request->tahun}\n"; + $pesan .= "Jumlah: Rp " . number_format($request->jumlah,0,',','.') . "\n"; + $pesan .= "Jenis: {$request->jenis_iuran}\n"; + $pesan .= "Terima kasih 🙏"; + + Http::withHeaders([ + 'Authorization' => env('FONNTE_TOKEN') + ])->post('https://api.fonnte.com/send', [ + 'target' => $nohp, + 'message' => $pesan, + ]); + } + + return redirect()->route('iuran.index') + ->with('success', 'Data iuran berhasil ditambahkan'); + } + public function edit($id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + $penghuni = Penghuni::where('rt_id', Auth::id())->get(); + + return view('admin.iuran.edit', compact('iuran', 'penghuni')); + } + + public function update(Request $request, $id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + + $request->validate([ + 'penghuni_id' => 'required', + 'bulan' => 'required', + 'tahun' => 'required', + 'jumlah' => 'required', + 'jenis_iuran' => 'required', + 'keterangan' => 'required', + 'status' => 'required', + ]); + + $iuran->update([ + 'penghuni_id' => $request->penghuni_id, + 'bulan' => $request->bulan, + 'tahun' => $request->tahun, + 'jumlah' => $request->jumlah, + 'jenis_iuran' => $request->jenis_iuran, + 'keterangan' => $request->keterangan, + 'status' => $request->status, + 'tanggal_bayar' => $request->status == 'lunas' ? now() : null, + ]); + + return redirect()->route('iuran.index')->with('success', 'Data berhasil diupdate'); + } + + public function destroy($id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + $iuran->delete(); + + return back()->with('success', 'Data berhasil dihapus'); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalPenghuni = Penghuni::count(); + $totalRumah = Rumah::count(); + $totalIuran = Iuran::count(); + $totalPengaduan = Layanan::count(); + + $menungguRT = Iuran::where('rt_id', $rtId) + ->where('status', 'belum') + ->count(); + + $menungguAdmin = Iuran::where('rt_id', $rtId) + ->where('status', 'proses') + ->count(); + + return view('rt.dashboard', compact( + 'totalPenghuni', + 'totalRumah', + 'totalIuran', + 'totalPengaduan', + 'menungguRT', + 'menungguAdmin' + )); + } + + public function approveRT($id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + + // Pastikan ada bukti sebelum approve + if (!$iuran->bukti_pembayaran) { + return back()->with('error', 'Tidak bisa approve, belum ada bukti pembayaran!'); + } + + $iuran->update([ + 'status' => 'lunas', + 'tanggal_bayar' => now() + ]); + + // Kirim notif WA ke penghuni + $penghuni = $iuran->penghuni; + if ($penghuni && $penghuni->telepon) { + $nohp = preg_replace('/^0/', '62', $penghuni->telepon); + $pesan = "Halo {$penghuni->nama},\n"; + $pesan .= "Pembayaran iuran Anda telah diverifikasi RT.\n"; + $pesan .= "Bulan: {$iuran->bulan} {$iuran->tahun}\n"; + $pesan .= "Jumlah: Rp " . number_format($iuran->jumlah,0,',','.') . "\n"; + $pesan .= "Status: LUNAS ✅\nTerima kasih 🙏"; + + \Illuminate\Support\Facades\Http::withHeaders([ + 'Authorization' => env('FONNTE_TOKEN') + ])->post('https://api.fonnte.com/send', [ + 'target' => $nohp, + 'message' => $pesan, + ]); + } + + return back()->with('success', 'Iuran disetujui dan dinyatakan lunas'); + } + + // public function approveAdmin($id) + // { + // $iuran = Iuran::findOrFail($id); + + // $iuran->update([ + // 'status' => 'lunas', + // 'tanggal_bayar' => now() + // ]); + + // return back()->with('success', 'Iuran disetujui admin'); + // } +} diff --git a/.history/app/Http/Controllers/IuranController_20260615175446.php b/.history/app/Http/Controllers/IuranController_20260615175446.php new file mode 100644 index 0000000..6f455f1 --- /dev/null +++ b/.history/app/Http/Controllers/IuranController_20260615175446.php @@ -0,0 +1,262 @@ +role == 'admin') { + $iuran = Iuran::with('penghuni')->get(); + } else { + $iuran = Iuran::with('penghuni') + ->where('rt_id', $user->id) + ->get(); + } + + return view('admin.iuran.index', compact('iuran')); + } + + public function create() + { + $rtId = Auth::id(); + + $penghuni = Penghuni::where('rt_id', $rtId)->get(); + + return view('admin.iuran.create', compact('penghuni')); + } + + public function store(Request $request) + { + $request->validate([ + 'penghuni_id' => 'required', + 'bulan' => 'required', + 'tahun' => 'required', + 'jumlah' => 'required', + 'jenis_iuran' => 'required', + 'keterangan' => 'required', + ]); + + // 🔥 ambil penghuni + $penghuni = Penghuni::findOrFail($request->penghuni_id); + + Iuran::create([ + 'penghuni_id' => $request->penghuni_id, + + // 🔥 FIX UTAMA (ambil dari penghuni) + 'rt_id' => $penghuni->rt_id, + + 'bulan' => $request->bulan, + 'tahun' => $request->tahun, + 'jumlah' => $request->jumlah, + 'jenis_iuran' => $request->jenis_iuran, + 'keterangan' => $request->keterangan, + 'status' => 'belum', + ]); + + // 🔥 WHATSAPP + $penghuni = Penghuni::find($request->penghuni_id); + + if ($penghuni && $penghuni->telepon) { + $nohp = preg_replace('/^0/', '62', $penghuni->telepon); + + $pesan = "Halo {$penghuni->nama},\n"; + $pesan .= "Iuran baru ditambahkan:\n"; + $pesan .= "Bulan: {$request->bulan} {$request->tahun}\n"; + $pesan .= "Jumlah: Rp " . number_format($request->jumlah,0,',','.') . "\n"; + $pesan .= "Jenis: {$request->jenis_iuran}\n"; + $pesan .= "Terima kasih 🙏"; + + Http::withHeaders([ + 'Authorization' => env('FONNTE_TOKEN') + ])->post('https://api.fonnte.com/send', [ + 'target' => $nohp, + 'message' => $pesan, + ]); + } + + return redirect()->route('iuran.index') + ->with('success', 'Data iuran berhasil ditambahkan'); + } + public function edit($id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + $penghuni = Penghuni::where('rt_id', Auth::id())->get(); + + return view('admin.iuran.edit', compact('iuran', 'penghuni')); + } + + public function update(Request $request, $id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + + $request->validate([ + 'penghuni_id' => 'required', + 'bulan' => 'required', + 'tahun' => 'required', + 'jumlah' => 'required', + 'jenis_iuran' => 'required', + 'keterangan' => 'required', + 'status' => 'required', + ]); + + $iuran->update([ + 'penghuni_id' => $request->penghuni_id, + 'bulan' => $request->bulan, + 'tahun' => $request->tahun, + 'jumlah' => $request->jumlah, + 'jenis_iuran' => $request->jenis_iuran, + 'keterangan' => $request->keterangan, + 'status' => $request->status, + 'tanggal_bayar' => $request->status == 'lunas' ? now() : null, + ]); + + return redirect()->route('iuran.index')->with('success', 'Data berhasil diupdate'); + } + + public function destroy($id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + $iuran->delete(); + + return back()->with('success', 'Data berhasil dihapus'); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalPenghuni = Penghuni::count(); + $totalRumah = Rumah::count(); + $totalIuran = Iuran::count(); + $totalPengaduan = Layanan::count(); + + $menungguRT = Iuran::where('rt_id', $rtId) + ->where('status', 'belum') + ->count(); + + $menungguAdmin = Iuran::where('rt_id', $rtId) + ->where('status', 'proses') + ->count(); + + return view('rt.dashboard', compact( + 'totalPenghuni', + 'totalRumah', + 'totalIuran', + 'totalPengaduan', + 'menungguRT', + 'menungguAdmin' + )); + } + + public function approveRT($id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + + // Pastikan ada bukti sebelum approve + if (!$iuran->bukti_pembayaran) { + return back()->with('error', 'Tidak bisa approve, belum ada bukti pembayaran!'); + } + + $iuran->update([ + 'status' => 'lunas', + 'tanggal_bayar' => now() + ]); + + // Kirim notif WA ke penghuni + $penghuni = $iuran->penghuni; + if ($penghuni && $penghuni->telepon) { + $nohp = preg_replace('/^0/', '62', $penghuni->telepon); + $pesan = "Halo {$penghuni->nama},\n"; + $pesan .= "Pembayaran iuran Anda telah diverifikasi RT.\n"; + $pesan .= "Bulan: {$iuran->bulan} {$iuran->tahun}\n"; + $pesan .= "Jumlah: Rp " . number_format($iuran->jumlah,0,',','.') . "\n"; + $pesan .= "Status: LUNAS ✅\nTerima kasih 🙏"; + + \Illuminate\Support\Facades\Http::withHeaders([ + 'Authorization' => env('FONNTE_TOKEN') + ])->post('https://api.fonnte.com/send', [ + 'target' => $nohp, + 'message' => $pesan, + ]); + } + + return back()->with('success', 'Iuran disetujui dan dinyatakan lunas'); + } + + public function generateMassal(Request $request) +{ + $request->validate([ + 'bulan' => 'required', + 'tahun' => 'required', + 'jumlah' => 'required|numeric', + 'jenis_iuran'=> 'required', + 'keterangan' => 'nullable', + ]); + + $rtId = Auth::id(); + $penghuni = \App\Models\Penghuni::where('rt_id', $rtId)->get(); + + $dibuat = 0; + foreach ($penghuni as $p) { + // Cek agar tidak double generate bulan yang sama + $sudahAda = Iuran::where('penghuni_id', $p->id) + ->where('bulan', $request->bulan) + ->where('tahun', $request->tahun) + ->where('jenis_iuran', $request->jenis_iuran) + ->exists(); + + if (!$sudahAda) { + Iuran::create([ + 'penghuni_id' => $p->id, + 'rt_id' => $rtId, + 'bulan' => $request->bulan, + 'tahun' => $request->tahun, + 'jumlah' => $request->jumlah, + 'jenis_iuran' => $request->jenis_iuran, + 'keterangan' => $request->keterangan, + 'status' => 'belum', + ]); + $dibuat++; + + // Kirim WA notifikasi + if ($p->telepon) { + $nohp = preg_replace('/^0/', '62', $p->telepon); + $pesan = "Halo {$p->nama},\nTagihan iuran baru:\nBulan: {$request->bulan} {$request->tahun}\nJumlah: Rp " . number_format($request->jumlah,0,',','.') . "\nJenis: {$request->jenis_iuran}\nSilakan bayar via QRIS. Terima kasih 🙏"; + + \Illuminate\Support\Facades\Http::withHeaders([ + 'Authorization' => env('FONNTE_TOKEN') + ])->post('https://api.fonnte.com/send', [ + 'target' => $nohp, + 'message' => $pesan, + ]); + } + } + } + + return redirect()->route('iuran.index') + ->with('success', "Berhasil generate {$dibuat} tagihan iuran untuk semua penghuni RT"); +} + + // public function approveAdmin($id) + // { + // $iuran = Iuran::findOrFail($id); + + // $iuran->update([ + // 'status' => 'lunas', + // 'tanggal_bayar' => now() + // ]); + + // return back()->with('success', 'Iuran disetujui admin'); + // } +} diff --git a/.history/app/Http/Controllers/IuranController_20260615175452.php b/.history/app/Http/Controllers/IuranController_20260615175452.php new file mode 100644 index 0000000..e291e12 --- /dev/null +++ b/.history/app/Http/Controllers/IuranController_20260615175452.php @@ -0,0 +1,262 @@ +role == 'admin') { + $iuran = Iuran::with('penghuni')->get(); + } else { + $iuran = Iuran::with('penghuni') + ->where('rt_id', $user->id) + ->get(); + } + + return view('admin.iuran.index', compact('iuran')); + } + + public function create() + { + $rtId = Auth::id(); + + $penghuni = Penghuni::where('rt_id', $rtId)->get(); + + return view('admin.iuran.create', compact('penghuni')); + } + + public function store(Request $request) + { + $request->validate([ + 'penghuni_id' => 'required', + 'bulan' => 'required', + 'tahun' => 'required', + 'jumlah' => 'required', + 'jenis_iuran' => 'required', + 'keterangan' => 'required', + ]); + + // 🔥 ambil penghuni + $penghuni = Penghuni::findOrFail($request->penghuni_id); + + Iuran::create([ + 'penghuni_id' => $request->penghuni_id, + + // 🔥 FIX UTAMA (ambil dari penghuni) + 'rt_id' => $penghuni->rt_id, + + 'bulan' => $request->bulan, + 'tahun' => $request->tahun, + 'jumlah' => $request->jumlah, + 'jenis_iuran' => $request->jenis_iuran, + 'keterangan' => $request->keterangan, + 'status' => 'belum', + ]); + + // 🔥 WHATSAPP + $penghuni = Penghuni::find($request->penghuni_id); + + if ($penghuni && $penghuni->telepon) { + $nohp = preg_replace('/^0/', '62', $penghuni->telepon); + + $pesan = "Halo {$penghuni->nama},\n"; + $pesan .= "Iuran baru ditambahkan:\n"; + $pesan .= "Bulan: {$request->bulan} {$request->tahun}\n"; + $pesan .= "Jumlah: Rp " . number_format($request->jumlah,0,',','.') . "\n"; + $pesan .= "Jenis: {$request->jenis_iuran}\n"; + $pesan .= "Terima kasih 🙏"; + + Http::withHeaders([ + 'Authorization' => env('FONNTE_TOKEN') + ])->post('https://api.fonnte.com/send', [ + 'target' => $nohp, + 'message' => $pesan, + ]); + } + + return redirect()->route('iuran.index') + ->with('success', 'Data iuran berhasil ditambahkan'); + } + public function edit($id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + $penghuni = Penghuni::where('rt_id', Auth::id())->get(); + + return view('admin.iuran.edit', compact('iuran', 'penghuni')); + } + + public function update(Request $request, $id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + + $request->validate([ + 'penghuni_id' => 'required', + 'bulan' => 'required', + 'tahun' => 'required', + 'jumlah' => 'required', + 'jenis_iuran' => 'required', + 'keterangan' => 'required', + 'status' => 'required', + ]); + + $iuran->update([ + 'penghuni_id' => $request->penghuni_id, + 'bulan' => $request->bulan, + 'tahun' => $request->tahun, + 'jumlah' => $request->jumlah, + 'jenis_iuran' => $request->jenis_iuran, + 'keterangan' => $request->keterangan, + 'status' => $request->status, + 'tanggal_bayar' => $request->status == 'lunas' ? now() : null, + ]); + + return redirect()->route('iuran.index')->with('success', 'Data berhasil diupdate'); + } + + public function destroy($id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + $iuran->delete(); + + return back()->with('success', 'Data berhasil dihapus'); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalPenghuni = Penghuni::count(); + $totalRumah = Rumah::count(); + $totalIuran = Iuran::count(); + $totalPengaduan = Layanan::count(); + + $menungguRT = Iuran::where('rt_id', $rtId) + ->where('status', 'belum') + ->count(); + + $menungguAdmin = Iuran::where('rt_id', $rtId) + ->where('status', 'proses') + ->count(); + + return view('rt.dashboard', compact( + 'totalPenghuni', + 'totalRumah', + 'totalIuran', + 'totalPengaduan', + 'menungguRT', + 'menungguAdmin' + )); + } + + public function approveRT($id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + + // Pastikan ada bukti sebelum approve + if (!$iuran->bukti_pembayaran) { + return back()->with('error', 'Tidak bisa approve, belum ada bukti pembayaran!'); + } + + $iuran->update([ + 'status' => 'lunas', + 'tanggal_bayar' => now() + ]); + + // Kirim notif WA ke penghuni + $penghuni = $iuran->penghuni; + if ($penghuni && $penghuni->telepon) { + $nohp = preg_replace('/^0/', '62', $penghuni->telepon); + $pesan = "Halo {$penghuni->nama},\n"; + $pesan .= "Pembayaran iuran Anda telah diverifikasi RT.\n"; + $pesan .= "Bulan: {$iuran->bulan} {$iuran->tahun}\n"; + $pesan .= "Jumlah: Rp " . number_format($iuran->jumlah,0,',','.') . "\n"; + $pesan .= "Status: LUNAS ✅\nTerima kasih 🙏"; + + \Illuminate\Support\Facades\Http::withHeaders([ + 'Authorization' => env('FONNTE_TOKEN') + ])->post('https://api.fonnte.com/send', [ + 'target' => $nohp, + 'message' => $pesan, + ]); + } + + return back()->with('success', 'Iuran disetujui dan dinyatakan lunas'); + } + + public function generateMassal(Request $request) + { + $request->validate([ + 'bulan' => 'required', + 'tahun' => 'required', + 'jumlah' => 'required|numeric', + 'jenis_iuran'=> 'required', + 'keterangan' => 'nullable', + ]); + + $rtId = Auth::id(); + $penghuni = \App\Models\Penghuni::where('rt_id', $rtId)->get(); + + $dibuat = 0; + foreach ($penghuni as $p) { + // Cek agar tidak double generate bulan yang sama + $sudahAda = Iuran::where('penghuni_id', $p->id) + ->where('bulan', $request->bulan) + ->where('tahun', $request->tahun) + ->where('jenis_iuran', $request->jenis_iuran) + ->exists(); + + if (!$sudahAda) { + Iuran::create([ + 'penghuni_id' => $p->id, + 'rt_id' => $rtId, + 'bulan' => $request->bulan, + 'tahun' => $request->tahun, + 'jumlah' => $request->jumlah, + 'jenis_iuran' => $request->jenis_iuran, + 'keterangan' => $request->keterangan, + 'status' => 'belum', + ]); + $dibuat++; + + // Kirim WA notifikasi + if ($p->telepon) { + $nohp = preg_replace('/^0/', '62', $p->telepon); + $pesan = "Halo {$p->nama},\nTagihan iuran baru:\nBulan: {$request->bulan} {$request->tahun}\nJumlah: Rp " . number_format($request->jumlah,0,',','.') . "\nJenis: {$request->jenis_iuran}\nSilakan bayar via QRIS. Terima kasih 🙏"; + + \Illuminate\Support\Facades\Http::withHeaders([ + 'Authorization' => env('FONNTE_TOKEN') + ])->post('https://api.fonnte.com/send', [ + 'target' => $nohp, + 'message' => $pesan, + ]); + } + } + } + + return redirect()->route('iuran.index') + ->with('success', "Berhasil generate {$dibuat} tagihan iuran untuk semua penghuni RT"); + } + + // public function approveAdmin($id) + // { + // $iuran = Iuran::findOrFail($id); + + // $iuran->update([ + // 'status' => 'lunas', + // 'tanggal_bayar' => now() + // ]); + + // return back()->with('success', 'Iuran disetujui admin'); + // } +} diff --git a/.history/app/Http/Controllers/IuranController_20260615180801.php b/.history/app/Http/Controllers/IuranController_20260615180801.php new file mode 100644 index 0000000..04e49d3 --- /dev/null +++ b/.history/app/Http/Controllers/IuranController_20260615180801.php @@ -0,0 +1,267 @@ +role == 'admin') { + $iuran = Iuran::with('penghuni')->get(); + } else { + $iuran = Iuran::with('penghuni') + ->where('rt_id', $user->id) + ->get(); + } + + return view('admin.iuran.index', compact('iuran')); + } + + public function create() + { + $rtId = Auth::id(); + + $penghuni = Penghuni::where('rt_id', $rtId)->get(); + + return view('admin.iuran.create', compact('penghuni')); + } + + public function store(Request $request) + { + $request->validate([ + 'penghuni_id' => 'required', + 'bulan' => 'required', + 'tahun' => 'required', + 'jumlah' => 'required', + 'jenis_iuran' => 'required', + 'keterangan' => 'required', + ]); + + // 🔥 ambil penghuni + $penghuni = Penghuni::findOrFail($request->penghuni_id); + + Iuran::create([ + 'penghuni_id' => $request->penghuni_id, + + // 🔥 FIX UTAMA (ambil dari penghuni) + 'rt_id' => $penghuni->rt_id, + + 'bulan' => $request->bulan, + 'tahun' => $request->tahun, + 'jumlah' => $request->jumlah, + 'jenis_iuran' => $request->jenis_iuran, + 'keterangan' => $request->keterangan, + 'status' => 'belum', + ]); + + // 🔥 WHATSAPP + $penghuni = Penghuni::find($request->penghuni_id); + + if ($penghuni && $penghuni->telepon) { + $nohp = preg_replace('/^0/', '62', $penghuni->telepon); + + $pesan = "🏠 *GREEN VIEW - Tagihan Iuran Baru*\n\n"; +$pesan .= "Halo *{$penghuni->nama}*,\n"; +$pesan .= "Anda memiliki tagihan iuran baru:\n\n"; +$pesan .= "📅 Bulan : {$request->bulan} {$request->tahun}\n"; +$pesan .= "💰 Jumlah : Rp " . number_format($request->jumlah,0,',','.') . "\n"; +$pesan .= "📋 Jenis : {$request->jenis_iuran}\n"; +$pesan .= "📝 Keterangan: " . ($request->keterangan ?? '-') . "\n\n"; +$pesan .= "Silakan bayar via QRIS yang tersedia di aplikasi.\n"; +$pesan .= "Setelah bayar, upload bukti pembayaran di halaman Iuran.\n\n"; +$pesan .= "_Terima kasih_ 🙏\n"; +$pesan .= "— RT Green View"; + + Http::withHeaders([ + 'Authorization' => env('FONNTE_TOKEN') + ])->post('https://api.fonnte.com/send', [ + 'target' => $nohp, + 'message' => $pesan, + ]); + } + + return redirect()->route('iuran.index') + ->with('success', 'Data iuran berhasil ditambahkan'); + } + public function edit($id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + $penghuni = Penghuni::where('rt_id', Auth::id())->get(); + + return view('admin.iuran.edit', compact('iuran', 'penghuni')); + } + + public function update(Request $request, $id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + + $request->validate([ + 'penghuni_id' => 'required', + 'bulan' => 'required', + 'tahun' => 'required', + 'jumlah' => 'required', + 'jenis_iuran' => 'required', + 'keterangan' => 'required', + 'status' => 'required', + ]); + + $iuran->update([ + 'penghuni_id' => $request->penghuni_id, + 'bulan' => $request->bulan, + 'tahun' => $request->tahun, + 'jumlah' => $request->jumlah, + 'jenis_iuran' => $request->jenis_iuran, + 'keterangan' => $request->keterangan, + 'status' => $request->status, + 'tanggal_bayar' => $request->status == 'lunas' ? now() : null, + ]); + + return redirect()->route('iuran.index')->with('success', 'Data berhasil diupdate'); + } + + public function destroy($id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + $iuran->delete(); + + return back()->with('success', 'Data berhasil dihapus'); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalPenghuni = Penghuni::count(); + $totalRumah = Rumah::count(); + $totalIuran = Iuran::count(); + $totalPengaduan = Layanan::count(); + + $menungguRT = Iuran::where('rt_id', $rtId) + ->where('status', 'belum') + ->count(); + + $menungguAdmin = Iuran::where('rt_id', $rtId) + ->where('status', 'proses') + ->count(); + + return view('rt.dashboard', compact( + 'totalPenghuni', + 'totalRumah', + 'totalIuran', + 'totalPengaduan', + 'menungguRT', + 'menungguAdmin' + )); + } + + public function approveRT($id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + + // Pastikan ada bukti sebelum approve + if (!$iuran->bukti_pembayaran) { + return back()->with('error', 'Tidak bisa approve, belum ada bukti pembayaran!'); + } + + $iuran->update([ + 'status' => 'lunas', + 'tanggal_bayar' => now() + ]); + + // Kirim notif WA ke penghuni + $penghuni = $iuran->penghuni; + if ($penghuni && $penghuni->telepon) { + $nohp = preg_replace('/^0/', '62', $penghuni->telepon); + $pesan = "Halo {$penghuni->nama},\n"; + $pesan .= "Pembayaran iuran Anda telah diverifikasi RT.\n"; + $pesan .= "Bulan: {$iuran->bulan} {$iuran->tahun}\n"; + $pesan .= "Jumlah: Rp " . number_format($iuran->jumlah,0,',','.') . "\n"; + $pesan .= "Status: LUNAS ✅\nTerima kasih 🙏"; + + \Illuminate\Support\Facades\Http::withHeaders([ + 'Authorization' => env('FONNTE_TOKEN') + ])->post('https://api.fonnte.com/send', [ + 'target' => $nohp, + 'message' => $pesan, + ]); + } + + return back()->with('success', 'Iuran disetujui dan dinyatakan lunas'); + } + + public function generateMassal(Request $request) + { + $request->validate([ + 'bulan' => 'required', + 'tahun' => 'required', + 'jumlah' => 'required|numeric', + 'jenis_iuran'=> 'required', + 'keterangan' => 'nullable', + ]); + + $rtId = Auth::id(); + $penghuni = \App\Models\Penghuni::where('rt_id', $rtId)->get(); + + $dibuat = 0; + foreach ($penghuni as $p) { + // Cek agar tidak double generate bulan yang sama + $sudahAda = Iuran::where('penghuni_id', $p->id) + ->where('bulan', $request->bulan) + ->where('tahun', $request->tahun) + ->where('jenis_iuran', $request->jenis_iuran) + ->exists(); + + if (!$sudahAda) { + Iuran::create([ + 'penghuni_id' => $p->id, + 'rt_id' => $rtId, + 'bulan' => $request->bulan, + 'tahun' => $request->tahun, + 'jumlah' => $request->jumlah, + 'jenis_iuran' => $request->jenis_iuran, + 'keterangan' => $request->keterangan, + 'status' => 'belum', + ]); + $dibuat++; + + // Kirim WA notifikasi + if ($p->telepon) { + $nohp = preg_replace('/^0/', '62', $p->telepon); + $pesan = "Halo {$p->nama},\nTagihan iuran baru:\nBulan: {$request->bulan} {$request->tahun}\nJumlah: Rp " . number_format($request->jumlah,0,',','.') . "\nJenis: {$request->jenis_iuran}\nSilakan bayar via QRIS. Terima kasih 🙏"; + + \Illuminate\Support\Facades\Http::withHeaders([ + 'Authorization' => env('FONNTE_TOKEN') + ])->post('https://api.fonnte.com/send', [ + 'target' => $nohp, + 'message' => $pesan, + ]); + } + } + } + + return redirect()->route('iuran.index') + ->with('success', "Berhasil generate {$dibuat} tagihan iuran untuk semua penghuni RT"); + } + + // public function approveAdmin($id) + // { + // $iuran = Iuran::findOrFail($id); + + // $iuran->update([ + // 'status' => 'lunas', + // 'tanggal_bayar' => now() + // ]); + + // return back()->with('success', 'Iuran disetujui admin'); + // } +} diff --git a/.history/app/Http/Controllers/IuranController_20260615180806.php b/.history/app/Http/Controllers/IuranController_20260615180806.php new file mode 100644 index 0000000..7520f72 --- /dev/null +++ b/.history/app/Http/Controllers/IuranController_20260615180806.php @@ -0,0 +1,267 @@ +role == 'admin') { + $iuran = Iuran::with('penghuni')->get(); + } else { + $iuran = Iuran::with('penghuni') + ->where('rt_id', $user->id) + ->get(); + } + + return view('admin.iuran.index', compact('iuran')); + } + + public function create() + { + $rtId = Auth::id(); + + $penghuni = Penghuni::where('rt_id', $rtId)->get(); + + return view('admin.iuran.create', compact('penghuni')); + } + + public function store(Request $request) + { + $request->validate([ + 'penghuni_id' => 'required', + 'bulan' => 'required', + 'tahun' => 'required', + 'jumlah' => 'required', + 'jenis_iuran' => 'required', + 'keterangan' => 'required', + ]); + + // 🔥 ambil penghuni + $penghuni = Penghuni::findOrFail($request->penghuni_id); + + Iuran::create([ + 'penghuni_id' => $request->penghuni_id, + + // 🔥 FIX UTAMA (ambil dari penghuni) + 'rt_id' => $penghuni->rt_id, + + 'bulan' => $request->bulan, + 'tahun' => $request->tahun, + 'jumlah' => $request->jumlah, + 'jenis_iuran' => $request->jenis_iuran, + 'keterangan' => $request->keterangan, + 'status' => 'belum', + ]); + + // 🔥 WHATSAPP + $penghuni = Penghuni::find($request->penghuni_id); + + if ($penghuni && $penghuni->telepon) { + $nohp = preg_replace('/^0/', '62', $penghuni->telepon); + + $pesan = "🏠 *GREEN VIEW - Tagihan Iuran Baru*\n\n"; + $pesan .= "Halo *{$penghuni->nama}*,\n"; + $pesan .= "Anda memiliki tagihan iuran baru:\n\n"; + $pesan .= "📅 Bulan : {$request->bulan} {$request->tahun}\n"; + $pesan .= "💰 Jumlah : Rp " . number_format($request->jumlah,0,',','.') . "\n"; + $pesan .= "📋 Jenis : {$request->jenis_iuran}\n"; + $pesan .= "📝 Keterangan: " . ($request->keterangan ?? '-') . "\n\n"; + $pesan .= "Silakan bayar via QRIS yang tersedia di aplikasi.\n"; + $pesan .= "Setelah bayar, upload bukti pembayaran di halaman Iuran.\n\n"; + $pesan .= "_Terima kasih_ 🙏\n"; + $pesan .= "— RT Green View"; + + Http::withHeaders([ + 'Authorization' => env('FONNTE_TOKEN') + ])->post('https://api.fonnte.com/send', [ + 'target' => $nohp, + 'message' => $pesan, + ]); + } + + return redirect()->route('iuran.index') + ->with('success', 'Data iuran berhasil ditambahkan'); + } + public function edit($id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + $penghuni = Penghuni::where('rt_id', Auth::id())->get(); + + return view('admin.iuran.edit', compact('iuran', 'penghuni')); + } + + public function update(Request $request, $id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + + $request->validate([ + 'penghuni_id' => 'required', + 'bulan' => 'required', + 'tahun' => 'required', + 'jumlah' => 'required', + 'jenis_iuran' => 'required', + 'keterangan' => 'required', + 'status' => 'required', + ]); + + $iuran->update([ + 'penghuni_id' => $request->penghuni_id, + 'bulan' => $request->bulan, + 'tahun' => $request->tahun, + 'jumlah' => $request->jumlah, + 'jenis_iuran' => $request->jenis_iuran, + 'keterangan' => $request->keterangan, + 'status' => $request->status, + 'tanggal_bayar' => $request->status == 'lunas' ? now() : null, + ]); + + return redirect()->route('iuran.index')->with('success', 'Data berhasil diupdate'); + } + + public function destroy($id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + $iuran->delete(); + + return back()->with('success', 'Data berhasil dihapus'); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalPenghuni = Penghuni::count(); + $totalRumah = Rumah::count(); + $totalIuran = Iuran::count(); + $totalPengaduan = Layanan::count(); + + $menungguRT = Iuran::where('rt_id', $rtId) + ->where('status', 'belum') + ->count(); + + $menungguAdmin = Iuran::where('rt_id', $rtId) + ->where('status', 'proses') + ->count(); + + return view('rt.dashboard', compact( + 'totalPenghuni', + 'totalRumah', + 'totalIuran', + 'totalPengaduan', + 'menungguRT', + 'menungguAdmin' + )); + } + + public function approveRT($id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + + // Pastikan ada bukti sebelum approve + if (!$iuran->bukti_pembayaran) { + return back()->with('error', 'Tidak bisa approve, belum ada bukti pembayaran!'); + } + + $iuran->update([ + 'status' => 'lunas', + 'tanggal_bayar' => now() + ]); + + // Kirim notif WA ke penghuni + $penghuni = $iuran->penghuni; + if ($penghuni && $penghuni->telepon) { + $nohp = preg_replace('/^0/', '62', $penghuni->telepon); + $pesan = "Halo {$penghuni->nama},\n"; + $pesan .= "Pembayaran iuran Anda telah diverifikasi RT.\n"; + $pesan .= "Bulan: {$iuran->bulan} {$iuran->tahun}\n"; + $pesan .= "Jumlah: Rp " . number_format($iuran->jumlah,0,',','.') . "\n"; + $pesan .= "Status: LUNAS ✅\nTerima kasih 🙏"; + + \Illuminate\Support\Facades\Http::withHeaders([ + 'Authorization' => env('FONNTE_TOKEN') + ])->post('https://api.fonnte.com/send', [ + 'target' => $nohp, + 'message' => $pesan, + ]); + } + + return back()->with('success', 'Iuran disetujui dan dinyatakan lunas'); + } + + public function generateMassal(Request $request) + { + $request->validate([ + 'bulan' => 'required', + 'tahun' => 'required', + 'jumlah' => 'required|numeric', + 'jenis_iuran'=> 'required', + 'keterangan' => 'nullable', + ]); + + $rtId = Auth::id(); + $penghuni = \App\Models\Penghuni::where('rt_id', $rtId)->get(); + + $dibuat = 0; + foreach ($penghuni as $p) { + // Cek agar tidak double generate bulan yang sama + $sudahAda = Iuran::where('penghuni_id', $p->id) + ->where('bulan', $request->bulan) + ->where('tahun', $request->tahun) + ->where('jenis_iuran', $request->jenis_iuran) + ->exists(); + + if (!$sudahAda) { + Iuran::create([ + 'penghuni_id' => $p->id, + 'rt_id' => $rtId, + 'bulan' => $request->bulan, + 'tahun' => $request->tahun, + 'jumlah' => $request->jumlah, + 'jenis_iuran' => $request->jenis_iuran, + 'keterangan' => $request->keterangan, + 'status' => 'belum', + ]); + $dibuat++; + + // Kirim WA notifikasi + if ($p->telepon) { + $nohp = preg_replace('/^0/', '62', $p->telepon); + $pesan = "Halo {$p->nama},\nTagihan iuran baru:\nBulan: {$request->bulan} {$request->tahun}\nJumlah: Rp " . number_format($request->jumlah,0,',','.') . "\nJenis: {$request->jenis_iuran}\nSilakan bayar via QRIS. Terima kasih 🙏"; + + \Illuminate\Support\Facades\Http::withHeaders([ + 'Authorization' => env('FONNTE_TOKEN') + ])->post('https://api.fonnte.com/send', [ + 'target' => $nohp, + 'message' => $pesan, + ]); + } + } + } + + return redirect()->route('iuran.index') + ->with('success', "Berhasil generate {$dibuat} tagihan iuran untuk semua penghuni RT"); + } + + // public function approveAdmin($id) + // { + // $iuran = Iuran::findOrFail($id); + + // $iuran->update([ + // 'status' => 'lunas', + // 'tanggal_bayar' => now() + // ]); + + // return back()->with('success', 'Iuran disetujui admin'); + // } +} diff --git a/.history/app/Http/Controllers/IuranController_20260615180826.php b/.history/app/Http/Controllers/IuranController_20260615180826.php new file mode 100644 index 0000000..113bedf --- /dev/null +++ b/.history/app/Http/Controllers/IuranController_20260615180826.php @@ -0,0 +1,273 @@ +role == 'admin') { + $iuran = Iuran::with('penghuni')->get(); + } else { + $iuran = Iuran::with('penghuni') + ->where('rt_id', $user->id) + ->get(); + } + + return view('admin.iuran.index', compact('iuran')); + } + + public function create() + { + $rtId = Auth::id(); + + $penghuni = Penghuni::where('rt_id', $rtId)->get(); + + return view('admin.iuran.create', compact('penghuni')); + } + + public function store(Request $request) + { + $request->validate([ + 'penghuni_id' => 'required', + 'bulan' => 'required', + 'tahun' => 'required', + 'jumlah' => 'required', + 'jenis_iuran' => 'required', + 'keterangan' => 'required', + ]); + + // 🔥 ambil penghuni + $penghuni = Penghuni::findOrFail($request->penghuni_id); + + Iuran::create([ + 'penghuni_id' => $request->penghuni_id, + + // 🔥 FIX UTAMA (ambil dari penghuni) + 'rt_id' => $penghuni->rt_id, + + 'bulan' => $request->bulan, + 'tahun' => $request->tahun, + 'jumlah' => $request->jumlah, + 'jenis_iuran' => $request->jenis_iuran, + 'keterangan' => $request->keterangan, + 'status' => 'belum', + ]); + + // 🔥 WHATSAPP + $penghuni = Penghuni::find($request->penghuni_id); + + if ($penghuni && $penghuni->telepon) { + $nohp = preg_replace('/^0/', '62', $penghuni->telepon); + + $pesan = "🏠 *GREEN VIEW - Tagihan Iuran Baru*\n\n"; + $pesan .= "Halo *{$penghuni->nama}*,\n"; + $pesan .= "Anda memiliki tagihan iuran baru:\n\n"; + $pesan .= "📅 Bulan : {$request->bulan} {$request->tahun}\n"; + $pesan .= "💰 Jumlah : Rp " . number_format($request->jumlah,0,',','.') . "\n"; + $pesan .= "📋 Jenis : {$request->jenis_iuran}\n"; + $pesan .= "📝 Keterangan: " . ($request->keterangan ?? '-') . "\n\n"; + $pesan .= "Silakan bayar via QRIS yang tersedia di aplikasi.\n"; + $pesan .= "Setelah bayar, upload bukti pembayaran di halaman Iuran.\n\n"; + $pesan .= "_Terima kasih_ 🙏\n"; + $pesan .= "— RT Green View"; + + Http::withHeaders([ + 'Authorization' => env('FONNTE_TOKEN') + ])->post('https://api.fonnte.com/send', [ + 'target' => $nohp, + 'message' => $pesan, + ]); + } + + return redirect()->route('iuran.index') + ->with('success', 'Data iuran berhasil ditambahkan'); + } + public function edit($id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + $penghuni = Penghuni::where('rt_id', Auth::id())->get(); + + return view('admin.iuran.edit', compact('iuran', 'penghuni')); + } + + public function update(Request $request, $id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + + $request->validate([ + 'penghuni_id' => 'required', + 'bulan' => 'required', + 'tahun' => 'required', + 'jumlah' => 'required', + 'jenis_iuran' => 'required', + 'keterangan' => 'required', + 'status' => 'required', + ]); + + $iuran->update([ + 'penghuni_id' => $request->penghuni_id, + 'bulan' => $request->bulan, + 'tahun' => $request->tahun, + 'jumlah' => $request->jumlah, + 'jenis_iuran' => $request->jenis_iuran, + 'keterangan' => $request->keterangan, + 'status' => $request->status, + 'tanggal_bayar' => $request->status == 'lunas' ? now() : null, + ]); + + return redirect()->route('iuran.index')->with('success', 'Data berhasil diupdate'); + } + + public function destroy($id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + $iuran->delete(); + + return back()->with('success', 'Data berhasil dihapus'); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalPenghuni = Penghuni::count(); + $totalRumah = Rumah::count(); + $totalIuran = Iuran::count(); + $totalPengaduan = Layanan::count(); + + $menungguRT = Iuran::where('rt_id', $rtId) + ->where('status', 'belum') + ->count(); + + $menungguAdmin = Iuran::where('rt_id', $rtId) + ->where('status', 'proses') + ->count(); + + return view('rt.dashboard', compact( + 'totalPenghuni', + 'totalRumah', + 'totalIuran', + 'totalPengaduan', + 'menungguRT', + 'menungguAdmin' + )); + } + + public function approveRT($id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + + // Pastikan ada bukti sebelum approve + if (!$iuran->bukti_pembayaran) { + return back()->with('error', 'Tidak bisa approve, belum ada bukti pembayaran!'); + } + + $iuran->update([ + 'status' => 'lunas', + 'tanggal_bayar' => now() + ]); + + // Kirim notif WA ke penghuni + $penghuni = $iuran->penghuni; + if ($penghuni && $penghuni->telepon) { + $nohp = preg_replace('/^0/', '62', $penghuni->telepon); + $pesan = "✅ *GREEN VIEW - Pembayaran Dikonfirmasi*\n\n"; +$pesan .= "Halo *{$penghuni->nama}*,\n"; +$pesan .= "Pembayaran iuran Anda telah *diverifikasi* oleh RT.\n\n"; +$pesan .= "📅 Bulan : {$iuran->bulan} {$iuran->tahun}\n"; +$pesan .= "💰 Jumlah : Rp " . number_format($iuran->jumlah,0,',','.') . "\n"; +$pesan .= "📋 Jenis : {$iuran->jenis_iuran}\n"; +$pesan .= "📝 Keterangan: " . ($iuran->keterangan ?? '-') . "\n"; +$pesan .= "📆 Tgl Lunas: " . now()->format('d M Y') . "\n\n"; +$pesan .= "Status pembayaran: *LUNAS* ✅\n\n"; +$pesan .= "_Terima kasih telah membayar tepat waktu_ 🙏\n"; +$pesan .= "— RT Green View"; + + \Illuminate\Support\Facades\Http::withHeaders([ + 'Authorization' => env('FONNTE_TOKEN') + ])->post('https://api.fonnte.com/send', [ + 'target' => $nohp, + 'message' => $pesan, + ]); + } + + return back()->with('success', 'Iuran disetujui dan dinyatakan lunas'); + } + + public function generateMassal(Request $request) + { + $request->validate([ + 'bulan' => 'required', + 'tahun' => 'required', + 'jumlah' => 'required|numeric', + 'jenis_iuran'=> 'required', + 'keterangan' => 'nullable', + ]); + + $rtId = Auth::id(); + $penghuni = \App\Models\Penghuni::where('rt_id', $rtId)->get(); + + $dibuat = 0; + foreach ($penghuni as $p) { + // Cek agar tidak double generate bulan yang sama + $sudahAda = Iuran::where('penghuni_id', $p->id) + ->where('bulan', $request->bulan) + ->where('tahun', $request->tahun) + ->where('jenis_iuran', $request->jenis_iuran) + ->exists(); + + if (!$sudahAda) { + Iuran::create([ + 'penghuni_id' => $p->id, + 'rt_id' => $rtId, + 'bulan' => $request->bulan, + 'tahun' => $request->tahun, + 'jumlah' => $request->jumlah, + 'jenis_iuran' => $request->jenis_iuran, + 'keterangan' => $request->keterangan, + 'status' => 'belum', + ]); + $dibuat++; + + // Kirim WA notifikasi + if ($p->telepon) { + $nohp = preg_replace('/^0/', '62', $p->telepon); + $pesan = "Halo {$p->nama},\nTagihan iuran baru:\nBulan: {$request->bulan} {$request->tahun}\nJumlah: Rp " . number_format($request->jumlah,0,',','.') . "\nJenis: {$request->jenis_iuran}\nSilakan bayar via QRIS. Terima kasih 🙏"; + + \Illuminate\Support\Facades\Http::withHeaders([ + 'Authorization' => env('FONNTE_TOKEN') + ])->post('https://api.fonnte.com/send', [ + 'target' => $nohp, + 'message' => $pesan, + ]); + } + } + } + + return redirect()->route('iuran.index') + ->with('success', "Berhasil generate {$dibuat} tagihan iuran untuk semua penghuni RT"); + } + + // public function approveAdmin($id) + // { + // $iuran = Iuran::findOrFail($id); + + // $iuran->update([ + // 'status' => 'lunas', + // 'tanggal_bayar' => now() + // ]); + + // return back()->with('success', 'Iuran disetujui admin'); + // } +} diff --git a/.history/app/Http/Controllers/IuranController_20260615180830.php b/.history/app/Http/Controllers/IuranController_20260615180830.php new file mode 100644 index 0000000..76e1b21 --- /dev/null +++ b/.history/app/Http/Controllers/IuranController_20260615180830.php @@ -0,0 +1,273 @@ +role == 'admin') { + $iuran = Iuran::with('penghuni')->get(); + } else { + $iuran = Iuran::with('penghuni') + ->where('rt_id', $user->id) + ->get(); + } + + return view('admin.iuran.index', compact('iuran')); + } + + public function create() + { + $rtId = Auth::id(); + + $penghuni = Penghuni::where('rt_id', $rtId)->get(); + + return view('admin.iuran.create', compact('penghuni')); + } + + public function store(Request $request) + { + $request->validate([ + 'penghuni_id' => 'required', + 'bulan' => 'required', + 'tahun' => 'required', + 'jumlah' => 'required', + 'jenis_iuran' => 'required', + 'keterangan' => 'required', + ]); + + // 🔥 ambil penghuni + $penghuni = Penghuni::findOrFail($request->penghuni_id); + + Iuran::create([ + 'penghuni_id' => $request->penghuni_id, + + // 🔥 FIX UTAMA (ambil dari penghuni) + 'rt_id' => $penghuni->rt_id, + + 'bulan' => $request->bulan, + 'tahun' => $request->tahun, + 'jumlah' => $request->jumlah, + 'jenis_iuran' => $request->jenis_iuran, + 'keterangan' => $request->keterangan, + 'status' => 'belum', + ]); + + // 🔥 WHATSAPP + $penghuni = Penghuni::find($request->penghuni_id); + + if ($penghuni && $penghuni->telepon) { + $nohp = preg_replace('/^0/', '62', $penghuni->telepon); + + $pesan = "🏠 *GREEN VIEW - Tagihan Iuran Baru*\n\n"; + $pesan .= "Halo *{$penghuni->nama}*,\n"; + $pesan .= "Anda memiliki tagihan iuran baru:\n\n"; + $pesan .= "📅 Bulan : {$request->bulan} {$request->tahun}\n"; + $pesan .= "💰 Jumlah : Rp " . number_format($request->jumlah,0,',','.') . "\n"; + $pesan .= "📋 Jenis : {$request->jenis_iuran}\n"; + $pesan .= "📝 Keterangan: " . ($request->keterangan ?? '-') . "\n\n"; + $pesan .= "Silakan bayar via QRIS yang tersedia di aplikasi.\n"; + $pesan .= "Setelah bayar, upload bukti pembayaran di halaman Iuran.\n\n"; + $pesan .= "_Terima kasih_ 🙏\n"; + $pesan .= "— RT Green View"; + + Http::withHeaders([ + 'Authorization' => env('FONNTE_TOKEN') + ])->post('https://api.fonnte.com/send', [ + 'target' => $nohp, + 'message' => $pesan, + ]); + } + + return redirect()->route('iuran.index') + ->with('success', 'Data iuran berhasil ditambahkan'); + } + public function edit($id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + $penghuni = Penghuni::where('rt_id', Auth::id())->get(); + + return view('admin.iuran.edit', compact('iuran', 'penghuni')); + } + + public function update(Request $request, $id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + + $request->validate([ + 'penghuni_id' => 'required', + 'bulan' => 'required', + 'tahun' => 'required', + 'jumlah' => 'required', + 'jenis_iuran' => 'required', + 'keterangan' => 'required', + 'status' => 'required', + ]); + + $iuran->update([ + 'penghuni_id' => $request->penghuni_id, + 'bulan' => $request->bulan, + 'tahun' => $request->tahun, + 'jumlah' => $request->jumlah, + 'jenis_iuran' => $request->jenis_iuran, + 'keterangan' => $request->keterangan, + 'status' => $request->status, + 'tanggal_bayar' => $request->status == 'lunas' ? now() : null, + ]); + + return redirect()->route('iuran.index')->with('success', 'Data berhasil diupdate'); + } + + public function destroy($id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + $iuran->delete(); + + return back()->with('success', 'Data berhasil dihapus'); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalPenghuni = Penghuni::count(); + $totalRumah = Rumah::count(); + $totalIuran = Iuran::count(); + $totalPengaduan = Layanan::count(); + + $menungguRT = Iuran::where('rt_id', $rtId) + ->where('status', 'belum') + ->count(); + + $menungguAdmin = Iuran::where('rt_id', $rtId) + ->where('status', 'proses') + ->count(); + + return view('rt.dashboard', compact( + 'totalPenghuni', + 'totalRumah', + 'totalIuran', + 'totalPengaduan', + 'menungguRT', + 'menungguAdmin' + )); + } + + public function approveRT($id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + + // Pastikan ada bukti sebelum approve + if (!$iuran->bukti_pembayaran) { + return back()->with('error', 'Tidak bisa approve, belum ada bukti pembayaran!'); + } + + $iuran->update([ + 'status' => 'lunas', + 'tanggal_bayar' => now() + ]); + + // Kirim notif WA ke penghuni + $penghuni = $iuran->penghuni; + if ($penghuni && $penghuni->telepon) { + $nohp = preg_replace('/^0/', '62', $penghuni->telepon); + $pesan = "✅ *GREEN VIEW - Pembayaran Dikonfirmasi*\n\n"; + $pesan .= "Halo *{$penghuni->nama}*,\n"; + $pesan .= "Pembayaran iuran Anda telah *diverifikasi* oleh RT.\n\n"; + $pesan .= "📅 Bulan : {$iuran->bulan} {$iuran->tahun}\n"; + $pesan .= "💰 Jumlah : Rp " . number_format($iuran->jumlah,0,',','.') . "\n"; + $pesan .= "📋 Jenis : {$iuran->jenis_iuran}\n"; + $pesan .= "📝 Keterangan: " . ($iuran->keterangan ?? '-') . "\n"; + $pesan .= "📆 Tgl Lunas: " . now()->format('d M Y') . "\n\n"; + $pesan .= "Status pembayaran: *LUNAS* ✅\n\n"; + $pesan .= "_Terima kasih telah membayar tepat waktu_ 🙏\n"; + $pesan .= "— RT Green View"; + + \Illuminate\Support\Facades\Http::withHeaders([ + 'Authorization' => env('FONNTE_TOKEN') + ])->post('https://api.fonnte.com/send', [ + 'target' => $nohp, + 'message' => $pesan, + ]); + } + + return back()->with('success', 'Iuran disetujui dan dinyatakan lunas'); + } + + public function generateMassal(Request $request) + { + $request->validate([ + 'bulan' => 'required', + 'tahun' => 'required', + 'jumlah' => 'required|numeric', + 'jenis_iuran'=> 'required', + 'keterangan' => 'nullable', + ]); + + $rtId = Auth::id(); + $penghuni = \App\Models\Penghuni::where('rt_id', $rtId)->get(); + + $dibuat = 0; + foreach ($penghuni as $p) { + // Cek agar tidak double generate bulan yang sama + $sudahAda = Iuran::where('penghuni_id', $p->id) + ->where('bulan', $request->bulan) + ->where('tahun', $request->tahun) + ->where('jenis_iuran', $request->jenis_iuran) + ->exists(); + + if (!$sudahAda) { + Iuran::create([ + 'penghuni_id' => $p->id, + 'rt_id' => $rtId, + 'bulan' => $request->bulan, + 'tahun' => $request->tahun, + 'jumlah' => $request->jumlah, + 'jenis_iuran' => $request->jenis_iuran, + 'keterangan' => $request->keterangan, + 'status' => 'belum', + ]); + $dibuat++; + + // Kirim WA notifikasi + if ($p->telepon) { + $nohp = preg_replace('/^0/', '62', $p->telepon); + $pesan = "Halo {$p->nama},\nTagihan iuran baru:\nBulan: {$request->bulan} {$request->tahun}\nJumlah: Rp " . number_format($request->jumlah,0,',','.') . "\nJenis: {$request->jenis_iuran}\nSilakan bayar via QRIS. Terima kasih 🙏"; + + \Illuminate\Support\Facades\Http::withHeaders([ + 'Authorization' => env('FONNTE_TOKEN') + ])->post('https://api.fonnte.com/send', [ + 'target' => $nohp, + 'message' => $pesan, + ]); + } + } + } + + return redirect()->route('iuran.index') + ->with('success', "Berhasil generate {$dibuat} tagihan iuran untuk semua penghuni RT"); + } + + // public function approveAdmin($id) + // { + // $iuran = Iuran::findOrFail($id); + + // $iuran->update([ + // 'status' => 'lunas', + // 'tanggal_bayar' => now() + // ]); + + // return back()->with('success', 'Iuran disetujui admin'); + // } +} diff --git a/.history/app/Http/Controllers/IuranController_20260615180832.php b/.history/app/Http/Controllers/IuranController_20260615180832.php new file mode 100644 index 0000000..b33933c --- /dev/null +++ b/.history/app/Http/Controllers/IuranController_20260615180832.php @@ -0,0 +1,273 @@ +role == 'admin') { + $iuran = Iuran::with('penghuni')->get(); + } else { + $iuran = Iuran::with('penghuni') + ->where('rt_id', $user->id) + ->get(); + } + + return view('admin.iuran.index', compact('iuran')); + } + + public function create() + { + $rtId = Auth::id(); + + $penghuni = Penghuni::where('rt_id', $rtId)->get(); + + return view('admin.iuran.create', compact('penghuni')); + } + + public function store(Request $request) + { + $request->validate([ + 'penghuni_id' => 'required', + 'bulan' => 'required', + 'tahun' => 'required', + 'jumlah' => 'required', + 'jenis_iuran' => 'required', + 'keterangan' => 'required', + ]); + + // 🔥 ambil penghuni + $penghuni = Penghuni::findOrFail($request->penghuni_id); + + Iuran::create([ + 'penghuni_id' => $request->penghuni_id, + + // 🔥 FIX UTAMA (ambil dari penghuni) + 'rt_id' => $penghuni->rt_id, + + 'bulan' => $request->bulan, + 'tahun' => $request->tahun, + 'jumlah' => $request->jumlah, + 'jenis_iuran' => $request->jenis_iuran, + 'keterangan' => $request->keterangan, + 'status' => 'belum', + ]); + + // 🔥 WHATSAPP + $penghuni = Penghuni::find($request->penghuni_id); + + if ($penghuni && $penghuni->telepon) { + $nohp = preg_replace('/^0/', '62', $penghuni->telepon); + + $pesan = "🏠 *GREEN VIEW - Tagihan Iuran Baru*\n\n"; + $pesan .= "Halo *{$penghuni->nama}*,\n"; + $pesan .= "Anda memiliki tagihan iuran baru:\n\n"; + $pesan .= "📅 Bulan : {$request->bulan} {$request->tahun}\n"; + $pesan .= "💰 Jumlah : Rp " . number_format($request->jumlah,0,',','.') . "\n"; + $pesan .= "📋 Jenis : {$request->jenis_iuran}\n"; + $pesan .= "📝 Keterangan: " . ($request->keterangan ?? '-') . "\n\n"; + $pesan .= "Silakan bayar via QRIS yang tersedia di aplikasi.\n"; + $pesan .= "Setelah bayar, upload bukti pembayaran di halaman Iuran.\n\n"; + $pesan .= "_Terima kasih_ 🙏\n"; + $pesan .= "— RT Green View"; + + Http::withHeaders([ + 'Authorization' => env('FONNTE_TOKEN') + ])->post('https://api.fonnte.com/send', [ + 'target' => $nohp, + 'message' => $pesan, + ]); + } + + return redirect()->route('iuran.index') + ->with('success', 'Data iuran berhasil ditambahkan'); + } + public function edit($id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + $penghuni = Penghuni::where('rt_id', Auth::id())->get(); + + return view('admin.iuran.edit', compact('iuran', 'penghuni')); + } + + public function update(Request $request, $id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + + $request->validate([ + 'penghuni_id' => 'required', + 'bulan' => 'required', + 'tahun' => 'required', + 'jumlah' => 'required', + 'jenis_iuran' => 'required', + 'keterangan' => 'required', + 'status' => 'required', + ]); + + $iuran->update([ + 'penghuni_id' => $request->penghuni_id, + 'bulan' => $request->bulan, + 'tahun' => $request->tahun, + 'jumlah' => $request->jumlah, + 'jenis_iuran' => $request->jenis_iuran, + 'keterangan' => $request->keterangan, + 'status' => $request->status, + 'tanggal_bayar' => $request->status == 'lunas' ? now() : null, + ]); + + return redirect()->route('iuran.index')->with('success', 'Data berhasil diupdate'); + } + + public function destroy($id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + $iuran->delete(); + + return back()->with('success', 'Data berhasil dihapus'); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalPenghuni = Penghuni::count(); + $totalRumah = Rumah::count(); + $totalIuran = Iuran::count(); + $totalPengaduan = Layanan::count(); + + $menungguRT = Iuran::where('rt_id', $rtId) + ->where('status', 'belum') + ->count(); + + $menungguAdmin = Iuran::where('rt_id', $rtId) + ->where('status', 'proses') + ->count(); + + return view('rt.dashboard', compact( + 'totalPenghuni', + 'totalRumah', + 'totalIuran', + 'totalPengaduan', + 'menungguRT', + 'menungguAdmin' + )); + } + + public function approveRT($id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + + // Pastikan ada bukti sebelum approve + if (!$iuran->bukti_pembayaran) { + return back()->with('error', 'Tidak bisa approve, belum ada bukti pembayaran!'); + } + + $iuran->update([ + 'status' => 'lunas', + 'tanggal_bayar' => now() + ]); + + // Kirim notif WA ke penghuni + $penghuni = $iuran->penghuni; + if ($penghuni && $penghuni->telepon) { + $nohp = preg_replace('/^0/', '62', $penghuni->telepon); + $pesan = "✅ *GREEN VIEW - Pembayaran Dikonfirmasi*\n\n"; + $pesan .= "Halo *{$penghuni->nama}*,\n"; + $pesan .= "Pembayaran iuran Anda telah *diverifikasi* oleh RT.\n\n"; + $pesan .= "📅 Bulan : {$iuran->bulan} {$iuran->tahun}\n"; + $pesan .= "💰 Jumlah : Rp " . number_format($iuran->jumlah,0,',','.') . "\n"; + $pesan .= "📋 Jenis : {$iuran->jenis_iuran}\n"; + $pesan .= "📝 Keterangan: " . ($iuran->keterangan ?? '-') . "\n"; + $pesan .= "📆 Tgl Lunas: " . now()->format('d M Y') . "\n\n"; + $pesan .= "Status pembayaran: *LUNAS* ✅\n\n"; + $pesan .= "_Terima kasih telah membayar tepat waktu_ 🙏\n"; + $pesan .= "— RT Green View"; + + \Illuminate\Support\Facades\Http::withHeaders([ + 'Authorization' => env('FONNTE_TOKEN') + ])->post('https://api.fonnte.com/send', [ + 'target' => $nohp, + 'message' => $pesan, + ]); + } + + return back()->with('success', 'Iuran disetujui dan dinyatakan lunas'); + } + + public function generateMassal(Request $request) + { + $request->validate([ + 'bulan' => 'required', + 'tahun' => 'required', + 'jumlah' => 'required|numeric', + 'jenis_iuran'=> 'required', + 'keterangan' => 'nullable', + ]); + + $rtId = Auth::id(); + $penghuni = \App\Models\Penghuni::where('rt_id', $rtId)->get(); + + $dibuat = 0; + foreach ($penghuni as $p) { + // Cek agar tidak double generate bulan yang sama + $sudahAda = Iuran::where('penghuni_id', $p->id) + ->where('bulan', $request->bulan) + ->where('tahun', $request->tahun) + ->where('jenis_iuran', $request->jenis_iuran) + ->exists(); + + if (!$sudahAda) { + Iuran::create([ + 'penghuni_id' => $p->id, + 'rt_id' => $rtId, + 'bulan' => $request->bulan, + 'tahun' => $request->tahun, + 'jumlah' => $request->jumlah, + 'jenis_iuran' => $request->jenis_iuran, + 'keterangan' => $request->keterangan, + 'status' => 'belum', + ]); + $dibuat++; + + // Kirim WA notifikasi + if ($p->telepon) { + $nohp = preg_replace('/^0/', '62', $p->telepon); + $pesan = "Halo {$p->nama},\nTagihan iuran baru:\nBulan: {$request->bulan} {$request->tahun}\nJumlah: Rp " . number_format($request->jumlah,0,',','.') . "\nJenis: {$request->jenis_iuran}\nSilakan bayar via QRIS. Terima kasih 🙏"; + + \Illuminate\Support\Facades\Http::withHeaders([ + 'Authorization' => env('FONNTE_TOKEN') + ])->post('https://api.fonnte.com/send', [ + 'target' => $nohp, + 'message' => $pesan, + ]); + } + } + } + + return redirect()->route('iuran.index') + ->with('success', "Berhasil generate {$dibuat} tagihan iuran untuk semua penghuni RT"); + } + + // public function approveAdmin($id) + // { + // $iuran = Iuran::findOrFail($id); + + // $iuran->update([ + // 'status' => 'lunas', + // 'tanggal_bayar' => now() + // ]); + + // return back()->with('success', 'Iuran disetujui admin'); + // } +} diff --git a/.history/app/Http/Controllers/IuranController_20260615181323.php b/.history/app/Http/Controllers/IuranController_20260615181323.php new file mode 100644 index 0000000..8bb89fa --- /dev/null +++ b/.history/app/Http/Controllers/IuranController_20260615181323.php @@ -0,0 +1,272 @@ +role == 'admin') { + $iuran = Iuran::with('penghuni')->get(); + } else { + $iuran = Iuran::with('penghuni') + ->where('rt_id', $user->id) + ->get(); + } + + return view('admin.iuran.index', compact('iuran')); + } + + public function create() + { + $rtId = Auth::id(); + + $penghuni = Penghuni::where('rt_id', $rtId)->get(); + + return view('admin.iuran.create', compact('penghuni')); + } + + public function store(Request $request) + { + $request->validate([ + 'penghuni_id' => 'required', + 'bulan' => 'required', + 'tahun' => 'required', + 'jumlah' => 'required', + 'jenis_iuran' => 'required', + 'keterangan' => 'required', + ]); + + // 🔥 ambil penghuni + $penghuni = Penghuni::findOrFail($request->penghuni_id); + + Iuran::create([ + 'penghuni_id' => $request->penghuni_id, + + // 🔥 FIX UTAMA (ambil dari penghuni) + 'rt_id' => $penghuni->rt_id, + + 'bulan' => $request->bulan, + 'tahun' => $request->tahun, + 'jumlah' => $request->jumlah, + 'jenis_iuran' => $request->jenis_iuran, + 'keterangan' => $request->keterangan, + 'status' => 'belum', + ]); + + // 🔥 WHATSAPP + $penghuni = Penghuni::find($request->penghuni_id); + + if ($penghuni && $penghuni->telepon) { + $nohp = preg_replace('/^0/', '62', $penghuni->telepon); + + $pesan = "GREEN VIEW - Tagihan Iuran Baru\n\n"; +$pesan .= "Halo {$penghuni->nama},\n"; +$pesan .= "Anda memiliki tagihan iuran baru:\n\n"; +$pesan .= "Bulan : {$request->bulan} {$request->tahun}\n"; +$pesan .= "Jumlah : Rp " . number_format($request->jumlah,0,',','.') . "\n"; +$pesan .= "Jenis : {$request->jenis_iuran}\n"; +$pesan .= "Keterangan : " . ($request->keterangan ?? '-') . "\n\n"; +$pesan .= "Silakan bayar via QRIS yang tersedia di aplikasi.\n"; +$pesan .= "Setelah bayar, upload bukti pembayaran di halaman Iuran.\n\n"; +$pesan .= "Terima kasih.\n"; +$pesan .= "- RT Green View"; + Http::withHeaders([ + 'Authorization' => env('FONNTE_TOKEN') + ])->post('https://api.fonnte.com/send', [ + 'target' => $nohp, + 'message' => $pesan, + ]); + } + + return redirect()->route('iuran.index') + ->with('success', 'Data iuran berhasil ditambahkan'); + } + public function edit($id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + $penghuni = Penghuni::where('rt_id', Auth::id())->get(); + + return view('admin.iuran.edit', compact('iuran', 'penghuni')); + } + + public function update(Request $request, $id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + + $request->validate([ + 'penghuni_id' => 'required', + 'bulan' => 'required', + 'tahun' => 'required', + 'jumlah' => 'required', + 'jenis_iuran' => 'required', + 'keterangan' => 'required', + 'status' => 'required', + ]); + + $iuran->update([ + 'penghuni_id' => $request->penghuni_id, + 'bulan' => $request->bulan, + 'tahun' => $request->tahun, + 'jumlah' => $request->jumlah, + 'jenis_iuran' => $request->jenis_iuran, + 'keterangan' => $request->keterangan, + 'status' => $request->status, + 'tanggal_bayar' => $request->status == 'lunas' ? now() : null, + ]); + + return redirect()->route('iuran.index')->with('success', 'Data berhasil diupdate'); + } + + public function destroy($id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + $iuran->delete(); + + return back()->with('success', 'Data berhasil dihapus'); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalPenghuni = Penghuni::count(); + $totalRumah = Rumah::count(); + $totalIuran = Iuran::count(); + $totalPengaduan = Layanan::count(); + + $menungguRT = Iuran::where('rt_id', $rtId) + ->where('status', 'belum') + ->count(); + + $menungguAdmin = Iuran::where('rt_id', $rtId) + ->where('status', 'proses') + ->count(); + + return view('rt.dashboard', compact( + 'totalPenghuni', + 'totalRumah', + 'totalIuran', + 'totalPengaduan', + 'menungguRT', + 'menungguAdmin' + )); + } + + public function approveRT($id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + + // Pastikan ada bukti sebelum approve + if (!$iuran->bukti_pembayaran) { + return back()->with('error', 'Tidak bisa approve, belum ada bukti pembayaran!'); + } + + $iuran->update([ + 'status' => 'lunas', + 'tanggal_bayar' => now() + ]); + + // Kirim notif WA ke penghuni + $penghuni = $iuran->penghuni; + if ($penghuni && $penghuni->telepon) { + $nohp = preg_replace('/^0/', '62', $penghuni->telepon); + $pesan = "✅ *GREEN VIEW - Pembayaran Dikonfirmasi*\n\n"; + $pesan .= "Halo *{$penghuni->nama}*,\n"; + $pesan .= "Pembayaran iuran Anda telah *diverifikasi* oleh RT.\n\n"; + $pesan .= "📅 Bulan : {$iuran->bulan} {$iuran->tahun}\n"; + $pesan .= "💰 Jumlah : Rp " . number_format($iuran->jumlah,0,',','.') . "\n"; + $pesan .= "📋 Jenis : {$iuran->jenis_iuran}\n"; + $pesan .= "📝 Keterangan: " . ($iuran->keterangan ?? '-') . "\n"; + $pesan .= "📆 Tgl Lunas: " . now()->format('d M Y') . "\n\n"; + $pesan .= "Status pembayaran: *LUNAS* ✅\n\n"; + $pesan .= "_Terima kasih telah membayar tepat waktu_ 🙏\n"; + $pesan .= "— RT Green View"; + + \Illuminate\Support\Facades\Http::withHeaders([ + 'Authorization' => env('FONNTE_TOKEN') + ])->post('https://api.fonnte.com/send', [ + 'target' => $nohp, + 'message' => $pesan, + ]); + } + + return back()->with('success', 'Iuran disetujui dan dinyatakan lunas'); + } + + public function generateMassal(Request $request) + { + $request->validate([ + 'bulan' => 'required', + 'tahun' => 'required', + 'jumlah' => 'required|numeric', + 'jenis_iuran'=> 'required', + 'keterangan' => 'nullable', + ]); + + $rtId = Auth::id(); + $penghuni = \App\Models\Penghuni::where('rt_id', $rtId)->get(); + + $dibuat = 0; + foreach ($penghuni as $p) { + // Cek agar tidak double generate bulan yang sama + $sudahAda = Iuran::where('penghuni_id', $p->id) + ->where('bulan', $request->bulan) + ->where('tahun', $request->tahun) + ->where('jenis_iuran', $request->jenis_iuran) + ->exists(); + + if (!$sudahAda) { + Iuran::create([ + 'penghuni_id' => $p->id, + 'rt_id' => $rtId, + 'bulan' => $request->bulan, + 'tahun' => $request->tahun, + 'jumlah' => $request->jumlah, + 'jenis_iuran' => $request->jenis_iuran, + 'keterangan' => $request->keterangan, + 'status' => 'belum', + ]); + $dibuat++; + + // Kirim WA notifikasi + if ($p->telepon) { + $nohp = preg_replace('/^0/', '62', $p->telepon); + $pesan = "Halo {$p->nama},\nTagihan iuran baru:\nBulan: {$request->bulan} {$request->tahun}\nJumlah: Rp " . number_format($request->jumlah,0,',','.') . "\nJenis: {$request->jenis_iuran}\nSilakan bayar via QRIS. Terima kasih 🙏"; + + \Illuminate\Support\Facades\Http::withHeaders([ + 'Authorization' => env('FONNTE_TOKEN') + ])->post('https://api.fonnte.com/send', [ + 'target' => $nohp, + 'message' => $pesan, + ]); + } + } + } + + return redirect()->route('iuran.index') + ->with('success', "Berhasil generate {$dibuat} tagihan iuran untuk semua penghuni RT"); + } + + // public function approveAdmin($id) + // { + // $iuran = Iuran::findOrFail($id); + + // $iuran->update([ + // 'status' => 'lunas', + // 'tanggal_bayar' => now() + // ]); + + // return back()->with('success', 'Iuran disetujui admin'); + // } +} diff --git a/.history/app/Http/Controllers/IuranController_20260615181330.php b/.history/app/Http/Controllers/IuranController_20260615181330.php new file mode 100644 index 0000000..8e7397e --- /dev/null +++ b/.history/app/Http/Controllers/IuranController_20260615181330.php @@ -0,0 +1,272 @@ +role == 'admin') { + $iuran = Iuran::with('penghuni')->get(); + } else { + $iuran = Iuran::with('penghuni') + ->where('rt_id', $user->id) + ->get(); + } + + return view('admin.iuran.index', compact('iuran')); + } + + public function create() + { + $rtId = Auth::id(); + + $penghuni = Penghuni::where('rt_id', $rtId)->get(); + + return view('admin.iuran.create', compact('penghuni')); + } + + public function store(Request $request) + { + $request->validate([ + 'penghuni_id' => 'required', + 'bulan' => 'required', + 'tahun' => 'required', + 'jumlah' => 'required', + 'jenis_iuran' => 'required', + 'keterangan' => 'required', + ]); + + // 🔥 ambil penghuni + $penghuni = Penghuni::findOrFail($request->penghuni_id); + + Iuran::create([ + 'penghuni_id' => $request->penghuni_id, + + // 🔥 FIX UTAMA (ambil dari penghuni) + 'rt_id' => $penghuni->rt_id, + + 'bulan' => $request->bulan, + 'tahun' => $request->tahun, + 'jumlah' => $request->jumlah, + 'jenis_iuran' => $request->jenis_iuran, + 'keterangan' => $request->keterangan, + 'status' => 'belum', + ]); + + // 🔥 WHATSAPP + $penghuni = Penghuni::find($request->penghuni_id); + + if ($penghuni && $penghuni->telepon) { + $nohp = preg_replace('/^0/', '62', $penghuni->telepon); + + $pesan = "GREEN VIEW - Tagihan Iuran Baru\n\n"; + $pesan .= "Halo {$penghuni->nama},\n"; + $pesan .= "Anda memiliki tagihan iuran baru:\n\n"; + $pesan .= "Bulan : {$request->bulan} {$request->tahun}\n"; + $pesan .= "Jumlah : Rp " . number_format($request->jumlah,0,',','.') . "\n"; + $pesan .= "Jenis : {$request->jenis_iuran}\n"; + $pesan .= "Keterangan : " . ($request->keterangan ?? '-') . "\n\n"; + $pesan .= "Silakan bayar via QRIS yang tersedia di aplikasi.\n"; + $pesan .= "Setelah bayar, upload bukti pembayaran di halaman Iuran.\n\n"; + $pesan .= "Terima kasih.\n"; + $pesan .= "- RT Green View"; + Http::withHeaders([ + 'Authorization' => env('FONNTE_TOKEN') + ])->post('https://api.fonnte.com/send', [ + 'target' => $nohp, + 'message' => $pesan, + ]); + } + + return redirect()->route('iuran.index') + ->with('success', 'Data iuran berhasil ditambahkan'); + } + public function edit($id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + $penghuni = Penghuni::where('rt_id', Auth::id())->get(); + + return view('admin.iuran.edit', compact('iuran', 'penghuni')); + } + + public function update(Request $request, $id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + + $request->validate([ + 'penghuni_id' => 'required', + 'bulan' => 'required', + 'tahun' => 'required', + 'jumlah' => 'required', + 'jenis_iuran' => 'required', + 'keterangan' => 'required', + 'status' => 'required', + ]); + + $iuran->update([ + 'penghuni_id' => $request->penghuni_id, + 'bulan' => $request->bulan, + 'tahun' => $request->tahun, + 'jumlah' => $request->jumlah, + 'jenis_iuran' => $request->jenis_iuran, + 'keterangan' => $request->keterangan, + 'status' => $request->status, + 'tanggal_bayar' => $request->status == 'lunas' ? now() : null, + ]); + + return redirect()->route('iuran.index')->with('success', 'Data berhasil diupdate'); + } + + public function destroy($id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + $iuran->delete(); + + return back()->with('success', 'Data berhasil dihapus'); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalPenghuni = Penghuni::count(); + $totalRumah = Rumah::count(); + $totalIuran = Iuran::count(); + $totalPengaduan = Layanan::count(); + + $menungguRT = Iuran::where('rt_id', $rtId) + ->where('status', 'belum') + ->count(); + + $menungguAdmin = Iuran::where('rt_id', $rtId) + ->where('status', 'proses') + ->count(); + + return view('rt.dashboard', compact( + 'totalPenghuni', + 'totalRumah', + 'totalIuran', + 'totalPengaduan', + 'menungguRT', + 'menungguAdmin' + )); + } + + public function approveRT($id) + { + $iuran = Iuran::where('rt_id', Auth::id())->findOrFail($id); + + // Pastikan ada bukti sebelum approve + if (!$iuran->bukti_pembayaran) { + return back()->with('error', 'Tidak bisa approve, belum ada bukti pembayaran!'); + } + + $iuran->update([ + 'status' => 'lunas', + 'tanggal_bayar' => now() + ]); + + // Kirim notif WA ke penghuni + $penghuni = $iuran->penghuni; + if ($penghuni && $penghuni->telepon) { + $nohp = preg_replace('/^0/', '62', $penghuni->telepon); + $pesan = "✅ *GREEN VIEW - Pembayaran Dikonfirmasi*\n\n"; + $pesan .= "Halo *{$penghuni->nama}*,\n"; + $pesan .= "Pembayaran iuran Anda telah *diverifikasi* oleh RT.\n\n"; + $pesan .= "📅 Bulan : {$iuran->bulan} {$iuran->tahun}\n"; + $pesan .= "💰 Jumlah : Rp " . number_format($iuran->jumlah,0,',','.') . "\n"; + $pesan .= "📋 Jenis : {$iuran->jenis_iuran}\n"; + $pesan .= "📝 Keterangan: " . ($iuran->keterangan ?? '-') . "\n"; + $pesan .= "📆 Tgl Lunas: " . now()->format('d M Y') . "\n\n"; + $pesan .= "Status pembayaran: *LUNAS* ✅\n\n"; + $pesan .= "_Terima kasih telah membayar tepat waktu_ 🙏\n"; + $pesan .= "— RT Green View"; + + \Illuminate\Support\Facades\Http::withHeaders([ + 'Authorization' => env('FONNTE_TOKEN') + ])->post('https://api.fonnte.com/send', [ + 'target' => $nohp, + 'message' => $pesan, + ]); + } + + return back()->with('success', 'Iuran disetujui dan dinyatakan lunas'); + } + + public function generateMassal(Request $request) + { + $request->validate([ + 'bulan' => 'required', + 'tahun' => 'required', + 'jumlah' => 'required|numeric', + 'jenis_iuran'=> 'required', + 'keterangan' => 'nullable', + ]); + + $rtId = Auth::id(); + $penghuni = \App\Models\Penghuni::where('rt_id', $rtId)->get(); + + $dibuat = 0; + foreach ($penghuni as $p) { + // Cek agar tidak double generate bulan yang sama + $sudahAda = Iuran::where('penghuni_id', $p->id) + ->where('bulan', $request->bulan) + ->where('tahun', $request->tahun) + ->where('jenis_iuran', $request->jenis_iuran) + ->exists(); + + if (!$sudahAda) { + Iuran::create([ + 'penghuni_id' => $p->id, + 'rt_id' => $rtId, + 'bulan' => $request->bulan, + 'tahun' => $request->tahun, + 'jumlah' => $request->jumlah, + 'jenis_iuran' => $request->jenis_iuran, + 'keterangan' => $request->keterangan, + 'status' => 'belum', + ]); + $dibuat++; + + // Kirim WA notifikasi + if ($p->telepon) { + $nohp = preg_replace('/^0/', '62', $p->telepon); + $pesan = "Halo {$p->nama},\nTagihan iuran baru:\nBulan: {$request->bulan} {$request->tahun}\nJumlah: Rp " . number_format($request->jumlah,0,',','.') . "\nJenis: {$request->jenis_iuran}\nSilakan bayar via QRIS. Terima kasih 🙏"; + + \Illuminate\Support\Facades\Http::withHeaders([ + 'Authorization' => env('FONNTE_TOKEN') + ])->post('https://api.fonnte.com/send', [ + 'target' => $nohp, + 'message' => $pesan, + ]); + } + } + } + + return redirect()->route('iuran.index') + ->with('success', "Berhasil generate {$dibuat} tagihan iuran untuk semua penghuni RT"); + } + + // public function approveAdmin($id) + // { + // $iuran = Iuran::findOrFail($id); + + // $iuran->update([ + // 'status' => 'lunas', + // 'tanggal_bayar' => now() + // ]); + + // return back()->with('success', 'Iuran disetujui admin'); + // } +} diff --git a/.history/app/Http/Controllers/LaporanController_20260504203010.php b/.history/app/Http/Controllers/LaporanController_20260504203010.php deleted file mode 100644 index 0ca1bd0..0000000 --- a/.history/app/Http/Controllers/LaporanController_20260504203010.php +++ /dev/null @@ -1,67 +0,0 @@ -bulan ?? now()->month; - - // 🔥 DATA PENGADUAN - $dataPengaduan = Layanan::whereMonth('created_at', $bulan)->get(); - - $sukses = $dataPengaduan->where('status', 'selesai')->count(); - $gagal = $dataPengaduan->where('status', 'diajukan')->count(); - - // 🔥 DATA TAMBAHAN - $totalRumah = Rumah::count(); - $totalPenghuni= Penghuni::count(); - - $totalIuran = Iuran::whereMonth('created_at', $bulan)->sum('jumlah'); - - return view('admin.laporan.index', compact( - 'bulan', - 'sukses', - 'gagal', - 'totalRumah', - 'totalPenghuni', - 'totalIuran' - )); - } - - public function cetak(Request $request) - { - $bulan = $request->bulan ?? now()->month; - - // 🔥 DATA PENGADUAN - $dataPengaduan = Layanan::whereMonth('created_at', $bulan)->get(); - - $sukses = $dataPengaduan->where('status', 'selesai')->count(); - $gagal = $dataPengaduan->where('status', 'diajukan')->count(); - - // 🔥 DATA TAMBAHAN - $totalRumah = Rumah::count(); - $totalPenghuni= Penghuni::count(); - $totalIuran = Iuran::whereMonth('created_at', $bulan)->sum('jumlah'); - - return view('admin.laporan.cetak', [ - 'bulan' => $bulan, - 'sukses' => $sukses, - 'gagal' => $gagal, - - // 🔥 TAMBAHAN INI - 'penghuni' => Penghuni::count(), - 'rumah' => Rumah::count(), - 'iuran' => Iuran::sum('jumlah'), - - 'data' => $dataPengaduan - ]); - } -} diff --git a/.history/app/Http/Controllers/LaporanController_20260507090744.php b/.history/app/Http/Controllers/LaporanController_20260507090744.php deleted file mode 100644 index f63fef4..0000000 --- a/.history/app/Http/Controllers/LaporanController_20260507090744.php +++ /dev/null @@ -1,95 +0,0 @@ -role === 'admin') { - // Admin → semua data - $pengaduanQuery = Layanan::whereMonth('created_at', $bulan); - $totalRumah = Rumah::count(); - $totalPenghuni = Penghuni::count(); - $totalIuran = Iuran::whereMonth('created_at', $bulan)->sum('jumlah'); - $penghuni = Penghuni::with('rumah')->get(); - $dataPengaduan = $pengaduanQuery->get(); - - } else { - // RT → hanya wilayahnya - $rtId = $user->id; - - $pengaduanQuery = Layanan::whereMonth('created_at', $bulan) - ->whereHas('penghuni.rumah', fn($q) => $q->where('rt_id', $rtId)); - - $totalRumah = Rumah::where('rt_id', $rtId)->count(); - $totalPenghuni = Penghuni::whereHas('rumah', fn($q) => $q->where('rt_id', $rtId))->count(); - $totalIuran = Iuran::whereHas('penghuni.rumah', fn($q) => $q->where('rt_id', $rtId)) - ->whereMonth('created_at', $bulan)->sum('jumlah'); - $penghuni = Penghuni::with('rumah') - ->whereHas('rumah', fn($q) => $q->where('rt_id', $rtId)) - ->get(); - $dataPengaduan = $pengaduanQuery->get(); - } - - return [ - 'totalRumah' => $totalRumah, - 'totalPenghuni' => $totalPenghuni, - 'totalIuran' => $totalIuran, - 'penghuni' => $penghuni, - 'dataPengaduan' => $dataPengaduan, - 'sukses' => $dataPengaduan->where('status', 'selesai')->count(), - 'gagal' => $dataPengaduan->where('status', 'diajukan')->count(), - ]; - } - - // ======================== - // INDEX - // ======================== - public function index(Request $request) - { - $bulan = $request->bulan ?? now()->month; - $data = $this->getFilteredData($bulan); - - // Tentukan view berdasarkan role - $view = Auth::user()->role === 'admin' - ? 'admin.laporan.index' - : 'rt.laporan.index'; - - return view($view, array_merge($data, ['bulan' => $bulan])); - } - - // ======================== - // CETAK PDF - // ======================== - public function cetak(Request $request) - { - $bulan = $request->bulan ?? now()->month; - $tahun = $request->tahun ?? now()->year; - $data = $this->getFilteredData($bulan); - $user = Auth::user(); - - return view('laporan.cetak', array_merge($data, [ - 'bulan' => $bulan, - 'tahun' => $tahun, - 'user' => $user, - // alias supaya blade cetak lama tetap jalan - 'penghuni' => $data['totalPenghuni'], - 'rumah' => $data['totalRumah'], - 'iuran' => $data['totalIuran'], - 'data' => $data['dataPengaduan'], - ])); - } -} diff --git a/.history/app/Http/Controllers/LaporanController_20260507091544.php b/.history/app/Http/Controllers/LaporanController_20260507091544.php deleted file mode 100644 index 64c4ef7..0000000 --- a/.history/app/Http/Controllers/LaporanController_20260507091544.php +++ /dev/null @@ -1,95 +0,0 @@ -role === 'admin') { - // Admin → semua data - $pengaduanQuery = Layanan::whereMonth('created_at', $bulan); - $totalRumah = Rumah::count(); - $totalPenghuni = Penghuni::count(); - $totalIuran = Iuran::whereMonth('created_at', $bulan)->sum('jumlah'); - $penghuni = Penghuni::with('rumah')->get(); - $dataPengaduan = $pengaduanQuery->get(); - - } else { - // RT → hanya wilayahnya - $rtId = $user->id; - - $pengaduanQuery = Layanan::whereMonth('created_at', $bulan) - ->whereHas('penghuni.rumah', fn($q) => $q->where('rt_id', $rtId)); - - $totalRumah = Rumah::where('rt_id', $rtId)->count(); - $totalPenghuni = Penghuni::whereHas('rumah', fn($q) => $q->where('rt_id', $rtId))->count(); - $totalIuran = Iuran::whereHas('penghuni.rumah', fn($q) => $q->where('rt_id', $rtId)) - ->whereMonth('created_at', $bulan)->sum('jumlah'); - $penghuni = Penghuni::with('rumah') - ->whereHas('rumah', fn($q) => $q->where('rt_id', $rtId)) - ->get(); - $dataPengaduan = $pengaduanQuery->get(); - } - - return [ - 'totalRumah' => $totalRumah, - 'totalPenghuni' => $totalPenghuni, - 'totalIuran' => $totalIuran, - 'penghuni' => $penghuni, - 'dataPengaduan' => $dataPengaduan, - 'sukses' => $dataPengaduan->where('status', 'selesai')->count(), - 'gagal' => $dataPengaduan->where('status', 'diajukan')->count(), - ]; - } - - // ======================== - // INDEX - // ======================== - public function index(Request $request) - { - $bulan = $request->bulan ?? now()->month; - $data = $this->getFilteredData($bulan); - - // Tentukan view berdasarkan role - $view = Auth::user()->role === 'admin' - ? 'admin.laporan.index' - : 'rt.laporan.index'; - - return view('admin.laporan.index', array_merge($data, ['bulan' => $bulan])); - } - - // ======================== - // CETAK PDF - // ======================== - public function cetak(Request $request) - { - $bulan = $request->bulan ?? now()->month; - $tahun = $request->tahun ?? now()->year; - $data = $this->getFilteredData($bulan); - $user = Auth::user(); - - return view('laporan.cetak', array_merge($data, [ - 'bulan' => $bulan, - 'tahun' => $tahun, - 'user' => $user, - // alias supaya blade cetak lama tetap jalan - 'penghuni' => $data['totalPenghuni'], - 'rumah' => $data['totalRumah'], - 'iuran' => $data['totalIuran'], - 'data' => $data['dataPengaduan'], - ])); - } -} diff --git a/.history/app/Http/Controllers/LaporanController_20260507153841.php b/.history/app/Http/Controllers/LaporanController_20260507153841.php deleted file mode 100644 index 1d66c4d..0000000 --- a/.history/app/Http/Controllers/LaporanController_20260507153841.php +++ /dev/null @@ -1,94 +0,0 @@ -role === 'admin') { - // Admin → semua data - $pengaduanQuery = Layanan::whereMonth('created_at', $bulan); - $totalRumah = Rumah::count(); - $totalPenghuni = Penghuni::count(); - $totalIuran = Iuran::whereMonth('created_at', $bulan)->sum('jumlah'); - $penghuni = Penghuni::with('rumah')->get(); - $dataPengaduan = $pengaduanQuery->get(); - - } else { - // RT → hanya wilayahnya - $rtId = $user->id; - - $pengaduanQuery = Layanan::whereMonth('created_at', $bulan) - ->whereHas('penghuni.rumah', fn($q) => $q->where('rt_id', $rtId)); - - $totalRumah = Rumah::where('rt_id', $rtId)->count(); - $totalPenghuni = Penghuni::whereHas('rumah', fn($q) => $q->where('rt_id', $rtId))->count(); - $totalIuran = Iuran::whereHas('penghuni.rumah', fn($q) => $q->where('rt_id', $rtId)) - ->whereMonth('created_at', $bulan)->sum('jumlah'); - $penghuni = Penghuni::with('rumah') - ->whereHas('rumah', fn($q) => $q->where('rt_id', $rtId)) - ->get(); - $dataPengaduan = $pengaduanQuery->get(); - } - - return [ - 'totalRumah' => $totalRumah, - 'totalPenghuni' => $totalPenghuni, - 'totalIuran' => $totalIuran, - 'penghuni' => $penghuni, - 'dataPengaduan' => $dataPengaduan, - 'sukses' => $dataPengaduan->where('status', 'selesai')->count(), - 'gagal' => $dataPengaduan->where('status', 'diajukan')->count(), - ]; - } - - // ======================== - // INDEX - // ======================== - public function index(Request $request) - { - $bulan = $request->bulan ?? now()->month; - $data = $this->getFilteredData($bulan); - - // Tentukan view berdasarkan role - $view = Auth::user()->role === 'admin' - ? 'admin.laporan.index' - : 'rt.laporan.index'; - - return view('admin.laporan.index', array_merge($data, ['bulan' => $bulan])); - } - - // ======================== - // CETAK PDF - // ======================== - public function cetak(Request $request) -{ - $bulan = $request->bulan ?? now()->month; - $tahun = $request->tahun ?? now()->year; - $data = $this->getFilteredData($bulan); - $user = Auth::user(); - - return view('admin.laporan.cetak', array_merge($data, [ - 'bulan' => $bulan, - 'tahun' => $tahun, - 'user' => $user, - 'penghuni' => $data['totalPenghuni'], - 'rumah' => $data['totalRumah'], - 'iuran' => $data['totalIuran'], - 'data' => $data['dataPengaduan'], - ])); -} -} diff --git a/.history/app/Http/Controllers/LaporanController_20260507153850.php b/.history/app/Http/Controllers/LaporanController_20260507153850.php deleted file mode 100644 index d1953cc..0000000 --- a/.history/app/Http/Controllers/LaporanController_20260507153850.php +++ /dev/null @@ -1,94 +0,0 @@ -role === 'admin') { - // Admin → semua data - $pengaduanQuery = Layanan::whereMonth('created_at', $bulan); - $totalRumah = Rumah::count(); - $totalPenghuni = Penghuni::count(); - $totalIuran = Iuran::whereMonth('created_at', $bulan)->sum('jumlah'); - $penghuni = Penghuni::with('rumah')->get(); - $dataPengaduan = $pengaduanQuery->get(); - - } else { - // RT → hanya wilayahnya - $rtId = $user->id; - - $pengaduanQuery = Layanan::whereMonth('created_at', $bulan) - ->whereHas('penghuni.rumah', fn($q) => $q->where('rt_id', $rtId)); - - $totalRumah = Rumah::where('rt_id', $rtId)->count(); - $totalPenghuni = Penghuni::whereHas('rumah', fn($q) => $q->where('rt_id', $rtId))->count(); - $totalIuran = Iuran::whereHas('penghuni.rumah', fn($q) => $q->where('rt_id', $rtId)) - ->whereMonth('created_at', $bulan)->sum('jumlah'); - $penghuni = Penghuni::with('rumah') - ->whereHas('rumah', fn($q) => $q->where('rt_id', $rtId)) - ->get(); - $dataPengaduan = $pengaduanQuery->get(); - } - - return [ - 'totalRumah' => $totalRumah, - 'totalPenghuni' => $totalPenghuni, - 'totalIuran' => $totalIuran, - 'penghuni' => $penghuni, - 'dataPengaduan' => $dataPengaduan, - 'sukses' => $dataPengaduan->where('status', 'selesai')->count(), - 'gagal' => $dataPengaduan->where('status', 'diajukan')->count(), - ]; - } - - // ======================== - // INDEX - // ======================== - public function index(Request $request) - { - $bulan = $request->bulan ?? now()->month; - $data = $this->getFilteredData($bulan); - - // Tentukan view berdasarkan role - $view = Auth::user()->role === 'admin' - ? 'admin.laporan.index' - : 'rt.laporan.index'; - - return view('admin.laporan.index', array_merge($data, ['bulan' => $bulan])); - } - - // ======================== - // CETAK PDF - // ======================== - public function cetak(Request $request) - { - $bulan = $request->bulan ?? now()->month; - $tahun = $request->tahun ?? now()->year; - $data = $this->getFilteredData($bulan); - $user = Auth::user(); - - return view('admin.laporan.cetak', array_merge($data, [ - 'bulan' => $bulan, - 'tahun' => $tahun, - 'user' => $user, - 'penghuni' => $data['totalPenghuni'], - 'rumah' => $data['totalRumah'], - 'iuran' => $data['totalIuran'], - 'data' => $data['dataPengaduan'], - ])); - } -} diff --git a/.history/app/Http/Controllers/LaporanController_20260623182610.php b/.history/app/Http/Controllers/LaporanController_20260623182610.php new file mode 100644 index 0000000..676151f --- /dev/null +++ b/.history/app/Http/Controllers/LaporanController_20260623182610.php @@ -0,0 +1,107 @@ +role === 'admin') { + $dataPengaduan = Layanan::whereMonth('created_at', $bulan) + ->whereYear('created_at', $tahun) + ->get(); + return [ + 'dataPengaduan' => $dataPengaduan, + 'sukses' => $dataPengaduan->where('status', 'selesai')->count(), + 'gagal' => $dataPengaduan->where('status', 'diajukan')->count(), + ]; + + } else { + // RT + $rtId = $user->id; + + $dataPengaduan = Layanan::whereMonth('created_at', $bulan) + ->whereYear('created_at', $tahun) + ->whereHas('penghuni.rumah', fn($q) => $q->where('rt_id', $rtId)) + ->get(); + + $totalRumah = Rumah::where('rt_id', $rtId)->count(); + $totalPenghuni = Penghuni::whereHas('rumah', fn($q) => $q->where('rt_id', $rtId))->count(); + + $dataIuran = Iuran::where('rt_id', $rtId) + ->whereMonth('created_at', $bulan) + ->whereYear('created_at', $tahun) + ->with('penghuni') + ->get(); + + // Kas bendahara aktif + $bendaharaAktif = User::where('rt_id', $rtId) + ->where('role', 'bendahara') + ->where('status_akun', 'aktif') + ->first(); + + $dataKas = collect(); + $saldoKas = 0; + if ($bendaharaAktif) { + $dataKas = KasBendahara::where('bendahara_id', $bendaharaAktif->id) + ->whereMonth('created_at', $bulan) + ->whereYear('created_at', $tahun) + ->get(); + $kasAll = KasBendahara::where('bendahara_id', $bendaharaAktif->id) + ->whereIn('status', ['manual', 'lunas']) + ->get(); + $saldoKas = $kasAll->where('jenis','masuk')->sum('jumlah') + - $kasAll->where('jenis','keluar')->sum('jumlah'); + } + + return [ + 'totalRumah' => $totalRumah, + 'totalPenghuni' => $totalPenghuni, + 'totalIuran' => $dataIuran->sum('jumlah'), + 'dataIuran' => $dataIuran, + 'dataKas' => $dataKas, + 'saldoKas' => $saldoKas, + 'dataPengaduan' => $dataPengaduan, + 'sukses' => $dataPengaduan->where('status', 'selesai')->count(), + 'gagal' => $dataPengaduan->where('status', 'diajukan')->count(), + 'bendaharaAktif' => $bendaharaAktif, + ]; + } + } + + public function index(Request $request) + { + $bulan = $request->bulan ?? now()->month; + $tahun = $request->tahun ?? now()->year; + $data = $this->getFilteredData($bulan, $tahun); + $view = Auth::user()->role === 'admin' ? 'admin.laporan.index' : 'rt.laporan.index'; + + return view($view, array_merge($data, ['bulan' => $bulan, 'tahun' => $tahun])); + } + + public function cetak(Request $request) + { + $bulan = $request->bulan ?? now()->month; + $tahun = $request->tahun ?? now()->year; + $data = $this->getFilteredData($bulan, $tahun); + $user = Auth::user(); + $view = $user->role === 'admin' ? 'admin.laporan.cetak' : 'rt.laporan.cetak'; + + return view($view, array_merge($data, [ + 'bulan' => $bulan, + 'tahun' => $tahun, + 'user' => $user, + ])); + } +} diff --git a/.history/app/Http/Controllers/LayananController_20260610222522.php b/.history/app/Http/Controllers/LayananController_20260610222522.php new file mode 100644 index 0000000..cd4e9cc --- /dev/null +++ b/.history/app/Http/Controllers/LayananController_20260610222522.php @@ -0,0 +1,173 @@ +role == 'admin') { + $layanan = Layanan::with('penghuni') + ->whereIn('status', ['menunggu', 'selesai']) + ->latest() + ->get(); + } else { + $rtId = $user->id; + $layanan = Layanan::with('penghuni') + ->whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + }) + ->latest() + ->get(); + } + + return view('admin.layanan.index', compact('layanan')); + } + + public function store(Request $request) + { + Layanan::create([ + 'penghuni_id' => $request->penghuni_id, + 'tanggal_pengaduan' => now(), + 'kategori_masalah' => $request->kategori_masalah, + 'deskripsi' => $request->deskripsi, + 'status' => 'diajukan' + ]); + + return back()->with('success', 'Pengaduan berhasil ditambahkan'); + } + + public function tanggapi(Request $request, $id) + { + $request->validate([ + 'tanggapan_admin' => 'required|string', + 'status' => 'required|in:diproses,selesai' + ]); + + $layanan = Layanan::with('penghuni')->find($id); + + if (!$layanan) { + return back()->with('error', 'Data tidak ditemukan'); + } + + $layanan->tanggapan_admin = $request->tanggapan_admin; + $layanan->status = $request->status; + $layanan->save(); + + // ✅ Kirim notif WA + Email + $this->kirimNotif($layanan); + + return redirect()->route('layanan.index') + ->with('success', 'Tanggapan berhasil dikirim & notifikasi terkirim.'); + } + + public function destroy($id) + { + Layanan::findOrFail($id)->delete(); + return back()->with('success', 'Data berhasil dihapus'); + } + + public function tanggapiRT(Request $request, $id) + { + $request->validate([ + 'tanggapan_admin' => 'required' + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->tanggapan_admin = $request->tanggapan_admin; + $layanan->status = 'menunggu'; // diteruskan ke admin + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Berhasil ditanggapi RT & notifikasi terkirim.'); + } + + public function approveAdmin($id) + { + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->status = 'selesai'; + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Disetujui Admin & notifikasi terkirim.'); + } + + public function indexAdmin() + { + $layanan = Layanan::with('penghuni') + ->where('status', 'menunggu') + ->latest() + ->get(); + + return view('admin.layanan.index', compact('layanan')); + } + + // ========================================================= + // ✅ PRIVATE: Kirim Notifikasi WA + Email sekaligus + // ========================================================= + private function kirimNotif($layanan) + { + if (!$layanan->penghuni) return; + + $nama = $layanan->penghuni->nama; + $statusText = $layanan->status === 'selesai' ? '✅ SELESAI' : '⏳ SEDANG DIPROSES'; + $tanggapan = $layanan->tanggapan_admin ?? '-'; + $tanggal = now()->format('d-m-Y H:i'); + + // ===================== + // 📱 WHATSAPP via WhatsappService (Fix Fonnte) + // ===================== + if (!empty($layanan->penghuni->telepon)) { + + $pesan = "🏡 *GREEN VIEW RESIDENCE*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "📢 *NOTIFIKASI PENGADUAN*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n\n"; + $pesan .= "Halo *{$nama}* 👋\n\n"; + $pesan .= "Pengaduan Anda telah mendapatkan update terbaru.\n\n"; + $pesan .= "📌 *DETAIL PENGADUAN*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "🗂️ Status : *{$statusText}*\n"; + $pesan .= "📅 Tanggal : {$tanggal}\n\n"; + $pesan .= "💬 *TANGGAPAN*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "{$tanggapan}\n\n"; + $pesan .= "📲 Cek detail: " . url('/') . "\n\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "🙏 Terima kasih atas kepercayaan Anda\n"; + $pesan .= "🏡 *Green View Residence*"; + + // ✅ Pakai WhatsappService (sudah ada normalizePhone & config token) + $terkirim = WhatsappService::send($layanan->penghuni->telepon, $pesan); + + if (!$terkirim) { + \Log::warning('[Layanan] WA gagal ke: ' . $layanan->penghuni->telepon); + } + } + + // ===================== + // 📧 EMAIL + // ===================== + if (!empty($layanan->penghuni->email)) { + try { + Mail::to($layanan->penghuni->email) + ->send(new NotifPengaduan($layanan)); + } catch (\Exception $e) { + \Log::error('[Layanan] Email gagal: ' . $e->getMessage()); + } + } + } +} diff --git a/.history/app/Http/Controllers/LayananController_20260610222606.php b/.history/app/Http/Controllers/LayananController_20260610222606.php new file mode 100644 index 0000000..1544810 --- /dev/null +++ b/.history/app/Http/Controllers/LayananController_20260610222606.php @@ -0,0 +1,173 @@ +role == 'admin') { + $layanan = Layanan::with('penghuni') + ->whereIn('status', ['menunggu', 'selesai']) + ->latest() + ->get(); + } else { + $rtId = $user->id; + $layanan = Layanan::with('penghuni') + ->whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + }) + ->latest() + ->get(); + } + + return view('admin.layanan.index', compact('layanan')); + } + + public function store(Request $request) + { + Layanan::create([ + 'penghuni_id' => $request->penghuni_id, + 'tanggal_pengaduan' => now(), + 'kategori_masalah' => $request->kategori_masalah, + 'deskripsi' => $request->deskripsi, + 'status' => 'diajukan' + ]); + + return back()->with('success', 'Pengaduan berhasil ditambahkan'); + } + + public function tanggapi(Request $request, $id) + { + $request->validate([ + 'tanggapan_admin' => 'required|string', + 'status' => 'required|in:diproses,selesai' + ]); + + $layanan = Layanan::with('penghuni')->find($id); + + if (!$layanan) { + return back()->with('error', 'Data tidak ditemukan'); + } + + $layanan->tanggapan_admin = $request->tanggapan_admin; + $layanan->status = $request->status; + $layanan->save(); + + // ✅ Kirim notif WA + Email + $this->kirimNotif($layanan); + + return redirect()->route('layanan.index') + ->with('success', 'Tanggapan berhasil dikirim & notifikasi terkirim.'); + } + + public function destroy($id) + { + Layanan::findOrFail($id)->delete(); + return back()->with('success', 'Data berhasil dihapus'); + } + + public function tanggapiRT(Request $request, $id) + { + $request->validate([ + 'tanggapan_admin' => 'required' + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->tanggapan_admin = $request->tanggapan_admin; + $layanan->status = 'menunggu'; // diteruskan ke admin + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Berhasil ditanggapi RT & notifikasi terkirim.'); + } + + public function approveAdmin($id) + { + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->status = 'selesai'; + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Disetujui Admin & notifikasi terkirim.'); + } + + public function indexAdmin() + { + $layanan = Layanan::with('penghuni') + ->where('status', 'menunggu') + ->latest() + ->get(); + + return view('admin.layanan.index', compact('layanan')); + } + + // ========================================================= + // ✅ PRIVATE: Kirim Notifikasi WA + Email sekaligus + // ========================================================= + private function kirimNotif($layanan) + { + if (!$layanan->penghuni) return; + + $nama = $layanan->penghuni->nama; + $statusText = $layanan->status === 'selesai' ? '✅ SELESAI' : '⏳ SEDANG DIPROSES'; + $tanggapan = $layanan->tanggapan_admin ?? '-'; + $tanggal = now()->format('d-m-Y H:i'); + + // ===================== + // 📱 WHATSAPP via WhatsappService (Fix Fonnte) + // ===================== + if (!empty($layanan->penghuni->telepon)) { + + $pesan = "🏡 *GREEN VIEW RESIDENCE*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "📢 *NOTIFIKASI PENGADUAN*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n\n"; + $pesan .= "Halo *{$nama}* 👋\n\n"; + $pesan .= "Pengaduan Anda telah mendapatkan update terbaru.\n\n"; + $pesan .= "📌 *DETAIL PENGADUAN*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "🗂️ Status : *{$statusText}*\n"; + $pesan .= "📅 Tanggal : {$tanggal}\n\n"; + $pesan .= "💬 *TANGGAPAN*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "{$tanggapan}\n\n"; + $pesan .= "📲 Cek detail: " . url('/') . "\n\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "🙏 Terima kasih atas kepercayaan Anda\n"; + $pesan .= "🏡 *Green View Residence*"; + + // ✅ Pakai WhatsappService (sudah ada normalizePhone & config token) + $terkirim = WhatsappService::send($layanan->penghuni->telepon, $pesan); + + if (!$terkirim) { + Log::warning('[Layanan] WA gagal ke: ' . $layanan->penghuni->telepon); + } + } + + // ===================== + // 📧 EMAIL + // ===================== + if (!empty($layanan->penghuni->email)) { + try { + Mail::to($layanan->penghuni->email) + ->send(new NotifPengaduan($layanan)); + } catch (\Exception $e) { + \Log::error('[Layanan] Email gagal: ' . $e->getMessage()); + } + } + } +} diff --git a/.history/app/Http/Controllers/LayananController_20260610222608.php b/.history/app/Http/Controllers/LayananController_20260610222608.php new file mode 100644 index 0000000..6f5c7d7 --- /dev/null +++ b/.history/app/Http/Controllers/LayananController_20260610222608.php @@ -0,0 +1,173 @@ +role == 'admin') { + $layanan = Layanan::with('penghuni') + ->whereIn('status', ['menunggu', 'selesai']) + ->latest() + ->get(); + } else { + $rtId = $user->id; + $layanan = Layanan::with('penghuni') + ->whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + }) + ->latest() + ->get(); + } + + return view('admin.layanan.index', compact('layanan')); + } + + public function store(Request $request) + { + Layanan::create([ + 'penghuni_id' => $request->penghuni_id, + 'tanggal_pengaduan' => now(), + 'kategori_masalah' => $request->kategori_masalah, + 'deskripsi' => $request->deskripsi, + 'status' => 'diajukan' + ]); + + return back()->with('success', 'Pengaduan berhasil ditambahkan'); + } + + public function tanggapi(Request $request, $id) + { + $request->validate([ + 'tanggapan_admin' => 'required|string', + 'status' => 'required|in:diproses,selesai' + ]); + + $layanan = Layanan::with('penghuni')->find($id); + + if (!$layanan) { + return back()->with('error', 'Data tidak ditemukan'); + } + + $layanan->tanggapan_admin = $request->tanggapan_admin; + $layanan->status = $request->status; + $layanan->save(); + + // ✅ Kirim notif WA + Email + $this->kirimNotif($layanan); + + return redirect()->route('layanan.index') + ->with('success', 'Tanggapan berhasil dikirim & notifikasi terkirim.'); + } + + public function destroy($id) + { + Layanan::findOrFail($id)->delete(); + return back()->with('success', 'Data berhasil dihapus'); + } + + public function tanggapiRT(Request $request, $id) + { + $request->validate([ + 'tanggapan_admin' => 'required' + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->tanggapan_admin = $request->tanggapan_admin; + $layanan->status = 'menunggu'; // diteruskan ke admin + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Berhasil ditanggapi RT & notifikasi terkirim.'); + } + + public function approveAdmin($id) + { + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->status = 'selesai'; + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Disetujui Admin & notifikasi terkirim.'); + } + + public function indexAdmin() + { + $layanan = Layanan::with('penghuni') + ->where('status', 'menunggu') + ->latest() + ->get(); + + return view('admin.layanan.index', compact('layanan')); + } + + // ========================================================= + // ✅ PRIVATE: Kirim Notifikasi WA + Email sekaligus + // ========================================================= + private function kirimNotif($layanan) + { + if (!$layanan->penghuni) return; + + $nama = $layanan->penghuni->nama; + $statusText = $layanan->status === 'selesai' ? '✅ SELESAI' : '⏳ SEDANG DIPROSES'; + $tanggapan = $layanan->tanggapan_admin ?? '-'; + $tanggal = now()->format('d-m-Y H:i'); + + // ===================== + // 📱 WHATSAPP via WhatsappService (Fix Fonnte) + // ===================== + if (!empty($layanan->penghuni->telepon)) { + + $pesan = "🏡 *GREEN VIEW RESIDENCE*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "📢 *NOTIFIKASI PENGADUAN*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n\n"; + $pesan .= "Halo *{$nama}* 👋\n\n"; + $pesan .= "Pengaduan Anda telah mendapatkan update terbaru.\n\n"; + $pesan .= "📌 *DETAIL PENGADUAN*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "🗂️ Status : *{$statusText}*\n"; + $pesan .= "📅 Tanggal : {$tanggal}\n\n"; + $pesan .= "💬 *TANGGAPAN*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "{$tanggapan}\n\n"; + $pesan .= "📲 Cek detail: " . url('/') . "\n\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "🙏 Terima kasih atas kepercayaan Anda\n"; + $pesan .= "🏡 *Green View Residence*"; + + // ✅ Pakai WhatsappService (sudah ada normalizePhone & config token) + $terkirim = WhatsappService::send($layanan->penghuni->telepon, $pesan); + + if (!$terkirim) { + Log::warning('[Layanan] WA gagal ke: ' . $layanan->penghuni->telepon); + } + } + + // ===================== + // 📧 EMAIL + // ===================== + if (!empty($layanan->penghuni->email)) { + try { + Mail::to($layanan->penghuni->email) + ->send(new NotifPengaduan($layanan)); + } catch (\Exception $e) { + Log::error('[Layanan] Email gagal: ' . $e->getMessage()); + } + } + } +} diff --git a/.history/app/Http/Controllers/LayananController_20260610222623.php b/.history/app/Http/Controllers/LayananController_20260610222623.php new file mode 100644 index 0000000..1544810 --- /dev/null +++ b/.history/app/Http/Controllers/LayananController_20260610222623.php @@ -0,0 +1,173 @@ +role == 'admin') { + $layanan = Layanan::with('penghuni') + ->whereIn('status', ['menunggu', 'selesai']) + ->latest() + ->get(); + } else { + $rtId = $user->id; + $layanan = Layanan::with('penghuni') + ->whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + }) + ->latest() + ->get(); + } + + return view('admin.layanan.index', compact('layanan')); + } + + public function store(Request $request) + { + Layanan::create([ + 'penghuni_id' => $request->penghuni_id, + 'tanggal_pengaduan' => now(), + 'kategori_masalah' => $request->kategori_masalah, + 'deskripsi' => $request->deskripsi, + 'status' => 'diajukan' + ]); + + return back()->with('success', 'Pengaduan berhasil ditambahkan'); + } + + public function tanggapi(Request $request, $id) + { + $request->validate([ + 'tanggapan_admin' => 'required|string', + 'status' => 'required|in:diproses,selesai' + ]); + + $layanan = Layanan::with('penghuni')->find($id); + + if (!$layanan) { + return back()->with('error', 'Data tidak ditemukan'); + } + + $layanan->tanggapan_admin = $request->tanggapan_admin; + $layanan->status = $request->status; + $layanan->save(); + + // ✅ Kirim notif WA + Email + $this->kirimNotif($layanan); + + return redirect()->route('layanan.index') + ->with('success', 'Tanggapan berhasil dikirim & notifikasi terkirim.'); + } + + public function destroy($id) + { + Layanan::findOrFail($id)->delete(); + return back()->with('success', 'Data berhasil dihapus'); + } + + public function tanggapiRT(Request $request, $id) + { + $request->validate([ + 'tanggapan_admin' => 'required' + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->tanggapan_admin = $request->tanggapan_admin; + $layanan->status = 'menunggu'; // diteruskan ke admin + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Berhasil ditanggapi RT & notifikasi terkirim.'); + } + + public function approveAdmin($id) + { + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->status = 'selesai'; + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Disetujui Admin & notifikasi terkirim.'); + } + + public function indexAdmin() + { + $layanan = Layanan::with('penghuni') + ->where('status', 'menunggu') + ->latest() + ->get(); + + return view('admin.layanan.index', compact('layanan')); + } + + // ========================================================= + // ✅ PRIVATE: Kirim Notifikasi WA + Email sekaligus + // ========================================================= + private function kirimNotif($layanan) + { + if (!$layanan->penghuni) return; + + $nama = $layanan->penghuni->nama; + $statusText = $layanan->status === 'selesai' ? '✅ SELESAI' : '⏳ SEDANG DIPROSES'; + $tanggapan = $layanan->tanggapan_admin ?? '-'; + $tanggal = now()->format('d-m-Y H:i'); + + // ===================== + // 📱 WHATSAPP via WhatsappService (Fix Fonnte) + // ===================== + if (!empty($layanan->penghuni->telepon)) { + + $pesan = "🏡 *GREEN VIEW RESIDENCE*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "📢 *NOTIFIKASI PENGADUAN*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n\n"; + $pesan .= "Halo *{$nama}* 👋\n\n"; + $pesan .= "Pengaduan Anda telah mendapatkan update terbaru.\n\n"; + $pesan .= "📌 *DETAIL PENGADUAN*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "🗂️ Status : *{$statusText}*\n"; + $pesan .= "📅 Tanggal : {$tanggal}\n\n"; + $pesan .= "💬 *TANGGAPAN*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "{$tanggapan}\n\n"; + $pesan .= "📲 Cek detail: " . url('/') . "\n\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "🙏 Terima kasih atas kepercayaan Anda\n"; + $pesan .= "🏡 *Green View Residence*"; + + // ✅ Pakai WhatsappService (sudah ada normalizePhone & config token) + $terkirim = WhatsappService::send($layanan->penghuni->telepon, $pesan); + + if (!$terkirim) { + Log::warning('[Layanan] WA gagal ke: ' . $layanan->penghuni->telepon); + } + } + + // ===================== + // 📧 EMAIL + // ===================== + if (!empty($layanan->penghuni->email)) { + try { + Mail::to($layanan->penghuni->email) + ->send(new NotifPengaduan($layanan)); + } catch (\Exception $e) { + \Log::error('[Layanan] Email gagal: ' . $e->getMessage()); + } + } + } +} diff --git a/.history/app/Http/Controllers/LayananController_20260610222625.php b/.history/app/Http/Controllers/LayananController_20260610222625.php new file mode 100644 index 0000000..6f5c7d7 --- /dev/null +++ b/.history/app/Http/Controllers/LayananController_20260610222625.php @@ -0,0 +1,173 @@ +role == 'admin') { + $layanan = Layanan::with('penghuni') + ->whereIn('status', ['menunggu', 'selesai']) + ->latest() + ->get(); + } else { + $rtId = $user->id; + $layanan = Layanan::with('penghuni') + ->whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + }) + ->latest() + ->get(); + } + + return view('admin.layanan.index', compact('layanan')); + } + + public function store(Request $request) + { + Layanan::create([ + 'penghuni_id' => $request->penghuni_id, + 'tanggal_pengaduan' => now(), + 'kategori_masalah' => $request->kategori_masalah, + 'deskripsi' => $request->deskripsi, + 'status' => 'diajukan' + ]); + + return back()->with('success', 'Pengaduan berhasil ditambahkan'); + } + + public function tanggapi(Request $request, $id) + { + $request->validate([ + 'tanggapan_admin' => 'required|string', + 'status' => 'required|in:diproses,selesai' + ]); + + $layanan = Layanan::with('penghuni')->find($id); + + if (!$layanan) { + return back()->with('error', 'Data tidak ditemukan'); + } + + $layanan->tanggapan_admin = $request->tanggapan_admin; + $layanan->status = $request->status; + $layanan->save(); + + // ✅ Kirim notif WA + Email + $this->kirimNotif($layanan); + + return redirect()->route('layanan.index') + ->with('success', 'Tanggapan berhasil dikirim & notifikasi terkirim.'); + } + + public function destroy($id) + { + Layanan::findOrFail($id)->delete(); + return back()->with('success', 'Data berhasil dihapus'); + } + + public function tanggapiRT(Request $request, $id) + { + $request->validate([ + 'tanggapan_admin' => 'required' + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->tanggapan_admin = $request->tanggapan_admin; + $layanan->status = 'menunggu'; // diteruskan ke admin + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Berhasil ditanggapi RT & notifikasi terkirim.'); + } + + public function approveAdmin($id) + { + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->status = 'selesai'; + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Disetujui Admin & notifikasi terkirim.'); + } + + public function indexAdmin() + { + $layanan = Layanan::with('penghuni') + ->where('status', 'menunggu') + ->latest() + ->get(); + + return view('admin.layanan.index', compact('layanan')); + } + + // ========================================================= + // ✅ PRIVATE: Kirim Notifikasi WA + Email sekaligus + // ========================================================= + private function kirimNotif($layanan) + { + if (!$layanan->penghuni) return; + + $nama = $layanan->penghuni->nama; + $statusText = $layanan->status === 'selesai' ? '✅ SELESAI' : '⏳ SEDANG DIPROSES'; + $tanggapan = $layanan->tanggapan_admin ?? '-'; + $tanggal = now()->format('d-m-Y H:i'); + + // ===================== + // 📱 WHATSAPP via WhatsappService (Fix Fonnte) + // ===================== + if (!empty($layanan->penghuni->telepon)) { + + $pesan = "🏡 *GREEN VIEW RESIDENCE*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "📢 *NOTIFIKASI PENGADUAN*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n\n"; + $pesan .= "Halo *{$nama}* 👋\n\n"; + $pesan .= "Pengaduan Anda telah mendapatkan update terbaru.\n\n"; + $pesan .= "📌 *DETAIL PENGADUAN*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "🗂️ Status : *{$statusText}*\n"; + $pesan .= "📅 Tanggal : {$tanggal}\n\n"; + $pesan .= "💬 *TANGGAPAN*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "{$tanggapan}\n\n"; + $pesan .= "📲 Cek detail: " . url('/') . "\n\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "🙏 Terima kasih atas kepercayaan Anda\n"; + $pesan .= "🏡 *Green View Residence*"; + + // ✅ Pakai WhatsappService (sudah ada normalizePhone & config token) + $terkirim = WhatsappService::send($layanan->penghuni->telepon, $pesan); + + if (!$terkirim) { + Log::warning('[Layanan] WA gagal ke: ' . $layanan->penghuni->telepon); + } + } + + // ===================== + // 📧 EMAIL + // ===================== + if (!empty($layanan->penghuni->email)) { + try { + Mail::to($layanan->penghuni->email) + ->send(new NotifPengaduan($layanan)); + } catch (\Exception $e) { + Log::error('[Layanan] Email gagal: ' . $e->getMessage()); + } + } + } +} diff --git a/.history/app/Http/Controllers/LayananController_20260624223324.php b/.history/app/Http/Controllers/LayananController_20260624223324.php new file mode 100644 index 0000000..4132443 --- /dev/null +++ b/.history/app/Http/Controllers/LayananController_20260624223324.php @@ -0,0 +1,197 @@ +role == 'admin') { + $layanan = Layanan::with('penghuni') + ->whereIn('status', ['menunggu', 'selesai']) + ->latest() + ->get(); + } else { + $rtId = $user->id; + $layanan = Layanan::with('penghuni') + ->whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + }) + ->latest() + ->get(); + } + + return view('admin.layanan.index', compact('layanan')); + } + + public function store(Request $request) + { + Layanan::create([ + 'penghuni_id' => $request->penghuni_id, + 'tanggal_pengaduan' => now(), + 'kategori_masalah' => $request->kategori_masalah, + 'deskripsi' => $request->deskripsi, + 'status' => 'diajukan' + ]); + + return back()->with('success', 'Pengaduan berhasil ditambahkan'); + } + + public function tanggapiRT(Request $request, $id) +{ + $request->validate([ + 'tanggapan_admin' => 'required' + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->tanggapan_admin = $request->tanggapan_admin; + $layanan->status = 'diproses'; // RT yang menangani langsung, tanpa admin + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Berhasil ditanggapi RT & notifikasi terkirim.'); +} + +// ========================================================= +// ✅ RT KONFIRMASI SELESAI (gantikan approve admin) +// Manual: catatan penyelesaian + foto bukti +// Tidak perlu kolom/migration baru: +// - tanggapan_admin dipakai utk gabungkan catatan RT awal + catatan selesai +// - foto digabung koma (foto pengaduan awal tetap ada, foto bukti selesai ditambahkan) +// ========================================================= +public function konfirmasiRT(Request $request, $id) +{ + $request->validate([ + 'catatan_selesai' => 'required|string', + 'foto_bukti' => 'nullable|image|mimes:jpg,jpeg,png|max:2048', + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + + $catatanLama = $layanan->tanggapan_admin ? $layanan->tanggapan_admin . "\n\n" : ''; + $layanan->tanggapan_admin = $catatanLama . '✅ Konfirmasi Selesai (RT): ' . $request->catatan_selesai; + + if ($request->hasFile('foto_bukti')) { + $path = $request->file('foto_bukti')->store('pengaduan', 'public'); + $layanan->foto = $layanan->foto ? $layanan->foto . ',' . $path : $path; + } + + $layanan->status = 'selesai'; + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Pengaduan dikonfirmasi selesai oleh RT & notifikasi terkirim.'); +} + + public function destroy($id) + { + Layanan::findOrFail($id)->delete(); + return back()->with('success', 'Data berhasil dihapus'); + } + + public function tanggapiRT(Request $request, $id) + { + $request->validate([ + 'tanggapan_admin' => 'required' + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->tanggapan_admin = $request->tanggapan_admin; + $layanan->status = 'menunggu'; // diteruskan ke admin + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Berhasil ditanggapi RT & notifikasi terkirim.'); + } + + public function approveAdmin($id) + { + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->status = 'selesai'; + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Disetujui Admin & notifikasi terkirim.'); + } + + public function indexAdmin() + { + $layanan = Layanan::with('penghuni') + ->where('status', 'menunggu') + ->latest() + ->get(); + + return view('admin.layanan.index', compact('layanan')); + } + + // ========================================================= + // ✅ PRIVATE: Kirim Notifikasi WA + Email sekaligus + // ========================================================= + private function kirimNotif($layanan) + { + if (!$layanan->penghuni) return; + + $nama = $layanan->penghuni->nama; + $statusText = $layanan->status === 'selesai' ? '✅ SELESAI' : '⏳ SEDANG DIPROSES'; + $tanggapan = $layanan->tanggapan_admin ?? '-'; + $tanggal = now()->format('d-m-Y H:i'); + + // ===================== + // 📱 WHATSAPP via WhatsappService (Fix Fonnte) + // ===================== + if (!empty($layanan->penghuni->telepon)) { + + $pesan = "🏡 *GREEN VIEW RESIDENCE*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "📢 *NOTIFIKASI PENGADUAN*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n\n"; + $pesan .= "Halo *{$nama}* 👋\n\n"; + $pesan .= "Pengaduan Anda telah mendapatkan update terbaru.\n\n"; + $pesan .= "📌 *DETAIL PENGADUAN*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "🗂️ Status : *{$statusText}*\n"; + $pesan .= "📅 Tanggal : {$tanggal}\n\n"; + $pesan .= "💬 *TANGGAPAN*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "{$tanggapan}\n\n"; + $pesan .= "📲 Cek detail: " . url('/') . "\n\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "🙏 Terima kasih atas kepercayaan Anda\n"; + $pesan .= "🏡 *Green View Residence*"; + + // ✅ Pakai WhatsappService (sudah ada normalizePhone & config token) + $terkirim = WhatsappService::send($layanan->penghuni->telepon, $pesan); + + if (!$terkirim) { + Log::warning('[Layanan] WA gagal ke: ' . $layanan->penghuni->telepon); + } + } + + // ===================== + // 📧 EMAIL + // ===================== + if (!empty($layanan->penghuni->email)) { + try { + Mail::to($layanan->penghuni->email) + ->send(new NotifPengaduan($layanan)); + } catch (\Exception $e) { + Log::error('[Layanan] Email gagal: ' . $e->getMessage()); + } + } + } +} diff --git a/.history/app/Http/Controllers/LayananController_20260624223327.php b/.history/app/Http/Controllers/LayananController_20260624223327.php new file mode 100644 index 0000000..de5012d --- /dev/null +++ b/.history/app/Http/Controllers/LayananController_20260624223327.php @@ -0,0 +1,196 @@ +role == 'admin') { + $layanan = Layanan::with('penghuni') + ->whereIn('status', ['menunggu', 'selesai']) + ->latest() + ->get(); + } else { + $rtId = $user->id; + $layanan = Layanan::with('penghuni') + ->whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + }) + ->latest() + ->get(); + } + + return view('admin.layanan.index', compact('layanan')); + } + + public function store(Request $request) + { + Layanan::create([ + 'penghuni_id' => $request->penghuni_id, + 'tanggal_pengaduan' => now(), + 'kategori_masalah' => $request->kategori_masalah, + 'deskripsi' => $request->deskripsi, + 'status' => 'diajukan' + ]); + + return back()->with('success', 'Pengaduan berhasil ditambahkan'); + } + + public function tanggapiRT(Request $request, $id) +{ + $request->validate([ + 'tanggapan_admin' => 'required' + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->tanggapan_admin = $request->tanggapan_admin; + $layanan->status = 'diproses'; // RT yang menangani langsung, tanpa admin + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Berhasil ditanggapi RT & notifikasi terkirim.'); +} + +// ========================================================= +// ✅ RT KONFIRMASI SELESAI (gantikan approve admin) +// Manual: catatan penyelesaian + foto bukti +// Tidak perlu kolom/migration baru: +// - tanggapan_admin dipakai utk gabungkan catatan RT awal + catatan selesai +// - foto digabung koma (foto pengaduan awal tetap ada, foto bukti selesai ditambahkan) +// ========================================================= +public function konfirmasiRT(Request $request, $id) +{ + $request->validate([ + 'catatan_selesai' => 'required|string', + 'foto_bukti' => 'nullable|image|mimes:jpg,jpeg,png|max:2048', + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + + $catatanLama = $layanan->tanggapan_admin ? $layanan->tanggapan_admin . "\n\n" : ''; + $layanan->tanggapan_admin = $catatanLama . '✅ Konfirmasi Selesai (RT): ' . $request->catatan_selesai; + + if ($request->hasFile('foto_bukti')) { + $path = $request->file('foto_bukti')->store('pengaduan', 'public'); + $layanan->foto = $layanan->foto ? $layanan->foto . ',' . $path : $path; + } + + $layanan->status = 'selesai'; + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Pengaduan dikonfirmasi selesai oleh RT & notifikasi terkirim.'); + + public function destroy($id) + { + Layanan::findOrFail($id)->delete(); + return back()->with('success', 'Data berhasil dihapus'); + } + + public function tanggapiRT(Request $request, $id) + { + $request->validate([ + 'tanggapan_admin' => 'required' + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->tanggapan_admin = $request->tanggapan_admin; + $layanan->status = 'menunggu'; // diteruskan ke admin + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Berhasil ditanggapi RT & notifikasi terkirim.'); + } + + public function approveAdmin($id) + { + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->status = 'selesai'; + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Disetujui Admin & notifikasi terkirim.'); + } + + public function indexAdmin() + { + $layanan = Layanan::with('penghuni') + ->where('status', 'menunggu') + ->latest() + ->get(); + + return view('admin.layanan.index', compact('layanan')); + } + + // ========================================================= + // ✅ PRIVATE: Kirim Notifikasi WA + Email sekaligus + // ========================================================= + private function kirimNotif($layanan) + { + if (!$layanan->penghuni) return; + + $nama = $layanan->penghuni->nama; + $statusText = $layanan->status === 'selesai' ? '✅ SELESAI' : '⏳ SEDANG DIPROSES'; + $tanggapan = $layanan->tanggapan_admin ?? '-'; + $tanggal = now()->format('d-m-Y H:i'); + + // ===================== + // 📱 WHATSAPP via WhatsappService (Fix Fonnte) + // ===================== + if (!empty($layanan->penghuni->telepon)) { + + $pesan = "🏡 *GREEN VIEW RESIDENCE*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "📢 *NOTIFIKASI PENGADUAN*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n\n"; + $pesan .= "Halo *{$nama}* 👋\n\n"; + $pesan .= "Pengaduan Anda telah mendapatkan update terbaru.\n\n"; + $pesan .= "📌 *DETAIL PENGADUAN*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "🗂️ Status : *{$statusText}*\n"; + $pesan .= "📅 Tanggal : {$tanggal}\n\n"; + $pesan .= "💬 *TANGGAPAN*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "{$tanggapan}\n\n"; + $pesan .= "📲 Cek detail: " . url('/') . "\n\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "🙏 Terima kasih atas kepercayaan Anda\n"; + $pesan .= "🏡 *Green View Residence*"; + + // ✅ Pakai WhatsappService (sudah ada normalizePhone & config token) + $terkirim = WhatsappService::send($layanan->penghuni->telepon, $pesan); + + if (!$terkirim) { + Log::warning('[Layanan] WA gagal ke: ' . $layanan->penghuni->telepon); + } + } + + // ===================== + // 📧 EMAIL + // ===================== + if (!empty($layanan->penghuni->email)) { + try { + Mail::to($layanan->penghuni->email) + ->send(new NotifPengaduan($layanan)); + } catch (\Exception $e) { + Log::error('[Layanan] Email gagal: ' . $e->getMessage()); + } + } + } +} diff --git a/.history/app/Http/Controllers/LayananController_20260624223329.php b/.history/app/Http/Controllers/LayananController_20260624223329.php new file mode 100644 index 0000000..6f5c7d7 --- /dev/null +++ b/.history/app/Http/Controllers/LayananController_20260624223329.php @@ -0,0 +1,173 @@ +role == 'admin') { + $layanan = Layanan::with('penghuni') + ->whereIn('status', ['menunggu', 'selesai']) + ->latest() + ->get(); + } else { + $rtId = $user->id; + $layanan = Layanan::with('penghuni') + ->whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + }) + ->latest() + ->get(); + } + + return view('admin.layanan.index', compact('layanan')); + } + + public function store(Request $request) + { + Layanan::create([ + 'penghuni_id' => $request->penghuni_id, + 'tanggal_pengaduan' => now(), + 'kategori_masalah' => $request->kategori_masalah, + 'deskripsi' => $request->deskripsi, + 'status' => 'diajukan' + ]); + + return back()->with('success', 'Pengaduan berhasil ditambahkan'); + } + + public function tanggapi(Request $request, $id) + { + $request->validate([ + 'tanggapan_admin' => 'required|string', + 'status' => 'required|in:diproses,selesai' + ]); + + $layanan = Layanan::with('penghuni')->find($id); + + if (!$layanan) { + return back()->with('error', 'Data tidak ditemukan'); + } + + $layanan->tanggapan_admin = $request->tanggapan_admin; + $layanan->status = $request->status; + $layanan->save(); + + // ✅ Kirim notif WA + Email + $this->kirimNotif($layanan); + + return redirect()->route('layanan.index') + ->with('success', 'Tanggapan berhasil dikirim & notifikasi terkirim.'); + } + + public function destroy($id) + { + Layanan::findOrFail($id)->delete(); + return back()->with('success', 'Data berhasil dihapus'); + } + + public function tanggapiRT(Request $request, $id) + { + $request->validate([ + 'tanggapan_admin' => 'required' + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->tanggapan_admin = $request->tanggapan_admin; + $layanan->status = 'menunggu'; // diteruskan ke admin + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Berhasil ditanggapi RT & notifikasi terkirim.'); + } + + public function approveAdmin($id) + { + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->status = 'selesai'; + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Disetujui Admin & notifikasi terkirim.'); + } + + public function indexAdmin() + { + $layanan = Layanan::with('penghuni') + ->where('status', 'menunggu') + ->latest() + ->get(); + + return view('admin.layanan.index', compact('layanan')); + } + + // ========================================================= + // ✅ PRIVATE: Kirim Notifikasi WA + Email sekaligus + // ========================================================= + private function kirimNotif($layanan) + { + if (!$layanan->penghuni) return; + + $nama = $layanan->penghuni->nama; + $statusText = $layanan->status === 'selesai' ? '✅ SELESAI' : '⏳ SEDANG DIPROSES'; + $tanggapan = $layanan->tanggapan_admin ?? '-'; + $tanggal = now()->format('d-m-Y H:i'); + + // ===================== + // 📱 WHATSAPP via WhatsappService (Fix Fonnte) + // ===================== + if (!empty($layanan->penghuni->telepon)) { + + $pesan = "🏡 *GREEN VIEW RESIDENCE*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "📢 *NOTIFIKASI PENGADUAN*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n\n"; + $pesan .= "Halo *{$nama}* 👋\n\n"; + $pesan .= "Pengaduan Anda telah mendapatkan update terbaru.\n\n"; + $pesan .= "📌 *DETAIL PENGADUAN*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "🗂️ Status : *{$statusText}*\n"; + $pesan .= "📅 Tanggal : {$tanggal}\n\n"; + $pesan .= "💬 *TANGGAPAN*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "{$tanggapan}\n\n"; + $pesan .= "📲 Cek detail: " . url('/') . "\n\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "🙏 Terima kasih atas kepercayaan Anda\n"; + $pesan .= "🏡 *Green View Residence*"; + + // ✅ Pakai WhatsappService (sudah ada normalizePhone & config token) + $terkirim = WhatsappService::send($layanan->penghuni->telepon, $pesan); + + if (!$terkirim) { + Log::warning('[Layanan] WA gagal ke: ' . $layanan->penghuni->telepon); + } + } + + // ===================== + // 📧 EMAIL + // ===================== + if (!empty($layanan->penghuni->email)) { + try { + Mail::to($layanan->penghuni->email) + ->send(new NotifPengaduan($layanan)); + } catch (\Exception $e) { + Log::error('[Layanan] Email gagal: ' . $e->getMessage()); + } + } + } +} diff --git a/.history/app/Http/Controllers/LayananController_20260624223344.php b/.history/app/Http/Controllers/LayananController_20260624223344.php new file mode 100644 index 0000000..35228f0 --- /dev/null +++ b/.history/app/Http/Controllers/LayananController_20260624223344.php @@ -0,0 +1,196 @@ +role == 'admin') { + $layanan = Layanan::with('penghuni') + ->whereIn('status', ['menunggu', 'selesai']) + ->latest() + ->get(); + } else { + $rtId = $user->id; + $layanan = Layanan::with('penghuni') + ->whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + }) + ->latest() + ->get(); + } + + return view('admin.layanan.index', compact('layanan')); + } + + public function store(Request $request) + { + Layanan::create([ + 'penghuni_id' => $request->penghuni_id, + 'tanggal_pengaduan' => now(), + 'kategori_masalah' => $request->kategori_masalah, + 'deskripsi' => $request->deskripsi, + 'status' => 'diajukan' + ]); + + return back()->with('success', 'Pengaduan berhasil ditambahkan'); + } + + public function tanggapiRT(Request $request, $id) +{ + $request->validate([ + 'tanggapan_admin' => 'required' + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->tanggapan_admin = $request->tanggapan_admin; + $layanan->status = 'diproses'; // RT yang menangani langsung, tanpa admin + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Berhasil ditanggapi RT & notifikasi terkirim.'); +} + +// ========================================================= +// ✅ RT KONFIRMASI SELESAI (gantikan approve admin) +// Manual: catatan penyelesaian + foto bukti +// Tidak perlu kolom/migration baru: +// - tanggapan_admin dipakai utk gabungkan catatan RT awal + catatan selesai +// - foto digabung koma (foto pengaduan awal tetap ada, foto bukti selesai ditambahkan) +// ========================================================= +public function konfirmasiRT(Request $request, $id) +{ + $request->validate([ + 'catatan_selesai' => 'required|string', + 'foto_bukti' => 'nullable|image|mimes:jpg,jpeg,png|max:2048', + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + + $catatanLama = $layanan->tanggapan_admin ? $layanan->tanggapan_admin . "\n\n" : ''; + $layanan->tanggapan_admin = $catatanLama . '✅ Konfirmasi Selesai (RT): ' . $request->catatan_selesai; + + if ($request->hasFile('foto_bukti')) { + $path = $request->file('foto_bukti')->store('pengaduan', 'public'); + $layanan->foto = $layanan->foto ? $layanan->foto . ',' . $path : $path; + } + + $layanan->status = 'selesai'; + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Pengaduan dikonfirmasi selesai oleh RT & notifikasi terkirim.'); +} + public function destroy($id) + { + Layanan::findOrFail($id)->delete(); + return back()->with('success', 'Data berhasil dihapus'); + } + + public function tanggapiRT(Request $request, $id) + { + $request->validate([ + 'tanggapan_admin' => 'required' + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->tanggapan_admin = $request->tanggapan_admin; + $layanan->status = 'menunggu'; // diteruskan ke admin + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Berhasil ditanggapi RT & notifikasi terkirim.'); + } + + public function approveAdmin($id) + { + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->status = 'selesai'; + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Disetujui Admin & notifikasi terkirim.'); + } + + public function indexAdmin() + { + $layanan = Layanan::with('penghuni') + ->where('status', 'menunggu') + ->latest() + ->get(); + + return view('admin.layanan.index', compact('layanan')); + } + + // ========================================================= + // ✅ PRIVATE: Kirim Notifikasi WA + Email sekaligus + // ========================================================= + private function kirimNotif($layanan) + { + if (!$layanan->penghuni) return; + + $nama = $layanan->penghuni->nama; + $statusText = $layanan->status === 'selesai' ? '✅ SELESAI' : '⏳ SEDANG DIPROSES'; + $tanggapan = $layanan->tanggapan_admin ?? '-'; + $tanggal = now()->format('d-m-Y H:i'); + + // ===================== + // 📱 WHATSAPP via WhatsappService (Fix Fonnte) + // ===================== + if (!empty($layanan->penghuni->telepon)) { + + $pesan = "🏡 *GREEN VIEW RESIDENCE*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "📢 *NOTIFIKASI PENGADUAN*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n\n"; + $pesan .= "Halo *{$nama}* 👋\n\n"; + $pesan .= "Pengaduan Anda telah mendapatkan update terbaru.\n\n"; + $pesan .= "📌 *DETAIL PENGADUAN*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "🗂️ Status : *{$statusText}*\n"; + $pesan .= "📅 Tanggal : {$tanggal}\n\n"; + $pesan .= "💬 *TANGGAPAN*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "{$tanggapan}\n\n"; + $pesan .= "📲 Cek detail: " . url('/') . "\n\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "🙏 Terima kasih atas kepercayaan Anda\n"; + $pesan .= "🏡 *Green View Residence*"; + + // ✅ Pakai WhatsappService (sudah ada normalizePhone & config token) + $terkirim = WhatsappService::send($layanan->penghuni->telepon, $pesan); + + if (!$terkirim) { + Log::warning('[Layanan] WA gagal ke: ' . $layanan->penghuni->telepon); + } + } + + // ===================== + // 📧 EMAIL + // ===================== + if (!empty($layanan->penghuni->email)) { + try { + Mail::to($layanan->penghuni->email) + ->send(new NotifPengaduan($layanan)); + } catch (\Exception $e) { + Log::error('[Layanan] Email gagal: ' . $e->getMessage()); + } + } + } +} diff --git a/.history/app/Http/Controllers/LayananController_20260624223520.php b/.history/app/Http/Controllers/LayananController_20260624223520.php new file mode 100644 index 0000000..6f5c7d7 --- /dev/null +++ b/.history/app/Http/Controllers/LayananController_20260624223520.php @@ -0,0 +1,173 @@ +role == 'admin') { + $layanan = Layanan::with('penghuni') + ->whereIn('status', ['menunggu', 'selesai']) + ->latest() + ->get(); + } else { + $rtId = $user->id; + $layanan = Layanan::with('penghuni') + ->whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + }) + ->latest() + ->get(); + } + + return view('admin.layanan.index', compact('layanan')); + } + + public function store(Request $request) + { + Layanan::create([ + 'penghuni_id' => $request->penghuni_id, + 'tanggal_pengaduan' => now(), + 'kategori_masalah' => $request->kategori_masalah, + 'deskripsi' => $request->deskripsi, + 'status' => 'diajukan' + ]); + + return back()->with('success', 'Pengaduan berhasil ditambahkan'); + } + + public function tanggapi(Request $request, $id) + { + $request->validate([ + 'tanggapan_admin' => 'required|string', + 'status' => 'required|in:diproses,selesai' + ]); + + $layanan = Layanan::with('penghuni')->find($id); + + if (!$layanan) { + return back()->with('error', 'Data tidak ditemukan'); + } + + $layanan->tanggapan_admin = $request->tanggapan_admin; + $layanan->status = $request->status; + $layanan->save(); + + // ✅ Kirim notif WA + Email + $this->kirimNotif($layanan); + + return redirect()->route('layanan.index') + ->with('success', 'Tanggapan berhasil dikirim & notifikasi terkirim.'); + } + + public function destroy($id) + { + Layanan::findOrFail($id)->delete(); + return back()->with('success', 'Data berhasil dihapus'); + } + + public function tanggapiRT(Request $request, $id) + { + $request->validate([ + 'tanggapan_admin' => 'required' + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->tanggapan_admin = $request->tanggapan_admin; + $layanan->status = 'menunggu'; // diteruskan ke admin + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Berhasil ditanggapi RT & notifikasi terkirim.'); + } + + public function approveAdmin($id) + { + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->status = 'selesai'; + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Disetujui Admin & notifikasi terkirim.'); + } + + public function indexAdmin() + { + $layanan = Layanan::with('penghuni') + ->where('status', 'menunggu') + ->latest() + ->get(); + + return view('admin.layanan.index', compact('layanan')); + } + + // ========================================================= + // ✅ PRIVATE: Kirim Notifikasi WA + Email sekaligus + // ========================================================= + private function kirimNotif($layanan) + { + if (!$layanan->penghuni) return; + + $nama = $layanan->penghuni->nama; + $statusText = $layanan->status === 'selesai' ? '✅ SELESAI' : '⏳ SEDANG DIPROSES'; + $tanggapan = $layanan->tanggapan_admin ?? '-'; + $tanggal = now()->format('d-m-Y H:i'); + + // ===================== + // 📱 WHATSAPP via WhatsappService (Fix Fonnte) + // ===================== + if (!empty($layanan->penghuni->telepon)) { + + $pesan = "🏡 *GREEN VIEW RESIDENCE*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "📢 *NOTIFIKASI PENGADUAN*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n\n"; + $pesan .= "Halo *{$nama}* 👋\n\n"; + $pesan .= "Pengaduan Anda telah mendapatkan update terbaru.\n\n"; + $pesan .= "📌 *DETAIL PENGADUAN*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "🗂️ Status : *{$statusText}*\n"; + $pesan .= "📅 Tanggal : {$tanggal}\n\n"; + $pesan .= "💬 *TANGGAPAN*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "{$tanggapan}\n\n"; + $pesan .= "📲 Cek detail: " . url('/') . "\n\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "🙏 Terima kasih atas kepercayaan Anda\n"; + $pesan .= "🏡 *Green View Residence*"; + + // ✅ Pakai WhatsappService (sudah ada normalizePhone & config token) + $terkirim = WhatsappService::send($layanan->penghuni->telepon, $pesan); + + if (!$terkirim) { + Log::warning('[Layanan] WA gagal ke: ' . $layanan->penghuni->telepon); + } + } + + // ===================== + // 📧 EMAIL + // ===================== + if (!empty($layanan->penghuni->email)) { + try { + Mail::to($layanan->penghuni->email) + ->send(new NotifPengaduan($layanan)); + } catch (\Exception $e) { + Log::error('[Layanan] Email gagal: ' . $e->getMessage()); + } + } + } +} diff --git a/.history/app/Http/Controllers/LayananController_20260624223529.php b/.history/app/Http/Controllers/LayananController_20260624223529.php new file mode 100644 index 0000000..0aa1951 --- /dev/null +++ b/.history/app/Http/Controllers/LayananController_20260624223529.php @@ -0,0 +1,173 @@ +role == 'admin') { + $layanan = Layanan::with('penghuni') + ->whereIn('status', ['menunggu', 'selesai']) + ->latest() + ->get(); + } else { + $rtId = $user->id; + $layanan = Layanan::with('penghuni') + ->whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + }) + ->latest() + ->get(); + } + + return view('admin.layanan.index', compact('layanan')); + } + + public function store(Request $request) + { + Layanan::create([ + 'penghuni_id' => $request->penghuni_id, + 'tanggal_pengaduan' => now(), + 'kategori_masalah' => $request->kategori_masalah, + 'deskripsi' => $request->deskripsi, + 'status' => 'diajukan' + ]); + + return back()->with('success', 'Pengaduan berhasil ditambahkan'); + } + + public function tanggapiRT(Request $request, $id) + { + $request->validate([ + 'tanggapan_admin' => 'required|string', + 'status' => 'required|in:diproses,selesai' + ]); + + $layanan = Layanan::with('penghuni')->find($id); + + if (!$layanan) { + return back()->with('error', 'Data tidak ditemukan'); + } + + $layanan->tanggapan_admin = $request->tanggapan_admin; + $layanan->status = $request->status; + $layanan->save(); + + // ✅ Kirim notif WA + Email + $this->kirimNotif($layanan); + + return redirect()->route('layanan.index') + ->with('success', 'Tanggapan berhasil dikirim & notifikasi terkirim.'); + } + + public function destroy($id) + { + Layanan::findOrFail($id)->delete(); + return back()->with('success', 'Data berhasil dihapus'); + } + + public function tanggapiRT(Request $request, $id) + { + $request->validate([ + 'tanggapan_admin' => 'required' + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->tanggapan_admin = $request->tanggapan_admin; + $layanan->status = 'menunggu'; // diteruskan ke admin + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Berhasil ditanggapi RT & notifikasi terkirim.'); + } + + public function approveAdmin($id) + { + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->status = 'selesai'; + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Disetujui Admin & notifikasi terkirim.'); + } + + public function indexAdmin() + { + $layanan = Layanan::with('penghuni') + ->where('status', 'menunggu') + ->latest() + ->get(); + + return view('admin.layanan.index', compact('layanan')); + } + + // ========================================================= + // ✅ PRIVATE: Kirim Notifikasi WA + Email sekaligus + // ========================================================= + private function kirimNotif($layanan) + { + if (!$layanan->penghuni) return; + + $nama = $layanan->penghuni->nama; + $statusText = $layanan->status === 'selesai' ? '✅ SELESAI' : '⏳ SEDANG DIPROSES'; + $tanggapan = $layanan->tanggapan_admin ?? '-'; + $tanggal = now()->format('d-m-Y H:i'); + + // ===================== + // 📱 WHATSAPP via WhatsappService (Fix Fonnte) + // ===================== + if (!empty($layanan->penghuni->telepon)) { + + $pesan = "🏡 *GREEN VIEW RESIDENCE*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "📢 *NOTIFIKASI PENGADUAN*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n\n"; + $pesan .= "Halo *{$nama}* 👋\n\n"; + $pesan .= "Pengaduan Anda telah mendapatkan update terbaru.\n\n"; + $pesan .= "📌 *DETAIL PENGADUAN*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "🗂️ Status : *{$statusText}*\n"; + $pesan .= "📅 Tanggal : {$tanggal}\n\n"; + $pesan .= "💬 *TANGGAPAN*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "{$tanggapan}\n\n"; + $pesan .= "📲 Cek detail: " . url('/') . "\n\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "🙏 Terima kasih atas kepercayaan Anda\n"; + $pesan .= "🏡 *Green View Residence*"; + + // ✅ Pakai WhatsappService (sudah ada normalizePhone & config token) + $terkirim = WhatsappService::send($layanan->penghuni->telepon, $pesan); + + if (!$terkirim) { + Log::warning('[Layanan] WA gagal ke: ' . $layanan->penghuni->telepon); + } + } + + // ===================== + // 📧 EMAIL + // ===================== + if (!empty($layanan->penghuni->email)) { + try { + Mail::to($layanan->penghuni->email) + ->send(new NotifPengaduan($layanan)); + } catch (\Exception $e) { + Log::error('[Layanan] Email gagal: ' . $e->getMessage()); + } + } + } +} diff --git a/.history/app/Http/Controllers/LayananController_20260624223625.php b/.history/app/Http/Controllers/LayananController_20260624223625.php new file mode 100644 index 0000000..6f5c7d7 --- /dev/null +++ b/.history/app/Http/Controllers/LayananController_20260624223625.php @@ -0,0 +1,173 @@ +role == 'admin') { + $layanan = Layanan::with('penghuni') + ->whereIn('status', ['menunggu', 'selesai']) + ->latest() + ->get(); + } else { + $rtId = $user->id; + $layanan = Layanan::with('penghuni') + ->whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + }) + ->latest() + ->get(); + } + + return view('admin.layanan.index', compact('layanan')); + } + + public function store(Request $request) + { + Layanan::create([ + 'penghuni_id' => $request->penghuni_id, + 'tanggal_pengaduan' => now(), + 'kategori_masalah' => $request->kategori_masalah, + 'deskripsi' => $request->deskripsi, + 'status' => 'diajukan' + ]); + + return back()->with('success', 'Pengaduan berhasil ditambahkan'); + } + + public function tanggapi(Request $request, $id) + { + $request->validate([ + 'tanggapan_admin' => 'required|string', + 'status' => 'required|in:diproses,selesai' + ]); + + $layanan = Layanan::with('penghuni')->find($id); + + if (!$layanan) { + return back()->with('error', 'Data tidak ditemukan'); + } + + $layanan->tanggapan_admin = $request->tanggapan_admin; + $layanan->status = $request->status; + $layanan->save(); + + // ✅ Kirim notif WA + Email + $this->kirimNotif($layanan); + + return redirect()->route('layanan.index') + ->with('success', 'Tanggapan berhasil dikirim & notifikasi terkirim.'); + } + + public function destroy($id) + { + Layanan::findOrFail($id)->delete(); + return back()->with('success', 'Data berhasil dihapus'); + } + + public function tanggapiRT(Request $request, $id) + { + $request->validate([ + 'tanggapan_admin' => 'required' + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->tanggapan_admin = $request->tanggapan_admin; + $layanan->status = 'menunggu'; // diteruskan ke admin + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Berhasil ditanggapi RT & notifikasi terkirim.'); + } + + public function approveAdmin($id) + { + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->status = 'selesai'; + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Disetujui Admin & notifikasi terkirim.'); + } + + public function indexAdmin() + { + $layanan = Layanan::with('penghuni') + ->where('status', 'menunggu') + ->latest() + ->get(); + + return view('admin.layanan.index', compact('layanan')); + } + + // ========================================================= + // ✅ PRIVATE: Kirim Notifikasi WA + Email sekaligus + // ========================================================= + private function kirimNotif($layanan) + { + if (!$layanan->penghuni) return; + + $nama = $layanan->penghuni->nama; + $statusText = $layanan->status === 'selesai' ? '✅ SELESAI' : '⏳ SEDANG DIPROSES'; + $tanggapan = $layanan->tanggapan_admin ?? '-'; + $tanggal = now()->format('d-m-Y H:i'); + + // ===================== + // 📱 WHATSAPP via WhatsappService (Fix Fonnte) + // ===================== + if (!empty($layanan->penghuni->telepon)) { + + $pesan = "🏡 *GREEN VIEW RESIDENCE*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "📢 *NOTIFIKASI PENGADUAN*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n\n"; + $pesan .= "Halo *{$nama}* 👋\n\n"; + $pesan .= "Pengaduan Anda telah mendapatkan update terbaru.\n\n"; + $pesan .= "📌 *DETAIL PENGADUAN*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "🗂️ Status : *{$statusText}*\n"; + $pesan .= "📅 Tanggal : {$tanggal}\n\n"; + $pesan .= "💬 *TANGGAPAN*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "{$tanggapan}\n\n"; + $pesan .= "📲 Cek detail: " . url('/') . "\n\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "🙏 Terima kasih atas kepercayaan Anda\n"; + $pesan .= "🏡 *Green View Residence*"; + + // ✅ Pakai WhatsappService (sudah ada normalizePhone & config token) + $terkirim = WhatsappService::send($layanan->penghuni->telepon, $pesan); + + if (!$terkirim) { + Log::warning('[Layanan] WA gagal ke: ' . $layanan->penghuni->telepon); + } + } + + // ===================== + // 📧 EMAIL + // ===================== + if (!empty($layanan->penghuni->email)) { + try { + Mail::to($layanan->penghuni->email) + ->send(new NotifPengaduan($layanan)); + } catch (\Exception $e) { + Log::error('[Layanan] Email gagal: ' . $e->getMessage()); + } + } + } +} diff --git a/.history/app/Http/Controllers/LayananController_20260624223627.php b/.history/app/Http/Controllers/LayananController_20260624223627.php new file mode 100644 index 0000000..0aa1951 --- /dev/null +++ b/.history/app/Http/Controllers/LayananController_20260624223627.php @@ -0,0 +1,173 @@ +role == 'admin') { + $layanan = Layanan::with('penghuni') + ->whereIn('status', ['menunggu', 'selesai']) + ->latest() + ->get(); + } else { + $rtId = $user->id; + $layanan = Layanan::with('penghuni') + ->whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + }) + ->latest() + ->get(); + } + + return view('admin.layanan.index', compact('layanan')); + } + + public function store(Request $request) + { + Layanan::create([ + 'penghuni_id' => $request->penghuni_id, + 'tanggal_pengaduan' => now(), + 'kategori_masalah' => $request->kategori_masalah, + 'deskripsi' => $request->deskripsi, + 'status' => 'diajukan' + ]); + + return back()->with('success', 'Pengaduan berhasil ditambahkan'); + } + + public function tanggapiRT(Request $request, $id) + { + $request->validate([ + 'tanggapan_admin' => 'required|string', + 'status' => 'required|in:diproses,selesai' + ]); + + $layanan = Layanan::with('penghuni')->find($id); + + if (!$layanan) { + return back()->with('error', 'Data tidak ditemukan'); + } + + $layanan->tanggapan_admin = $request->tanggapan_admin; + $layanan->status = $request->status; + $layanan->save(); + + // ✅ Kirim notif WA + Email + $this->kirimNotif($layanan); + + return redirect()->route('layanan.index') + ->with('success', 'Tanggapan berhasil dikirim & notifikasi terkirim.'); + } + + public function destroy($id) + { + Layanan::findOrFail($id)->delete(); + return back()->with('success', 'Data berhasil dihapus'); + } + + public function tanggapiRT(Request $request, $id) + { + $request->validate([ + 'tanggapan_admin' => 'required' + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->tanggapan_admin = $request->tanggapan_admin; + $layanan->status = 'menunggu'; // diteruskan ke admin + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Berhasil ditanggapi RT & notifikasi terkirim.'); + } + + public function approveAdmin($id) + { + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->status = 'selesai'; + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Disetujui Admin & notifikasi terkirim.'); + } + + public function indexAdmin() + { + $layanan = Layanan::with('penghuni') + ->where('status', 'menunggu') + ->latest() + ->get(); + + return view('admin.layanan.index', compact('layanan')); + } + + // ========================================================= + // ✅ PRIVATE: Kirim Notifikasi WA + Email sekaligus + // ========================================================= + private function kirimNotif($layanan) + { + if (!$layanan->penghuni) return; + + $nama = $layanan->penghuni->nama; + $statusText = $layanan->status === 'selesai' ? '✅ SELESAI' : '⏳ SEDANG DIPROSES'; + $tanggapan = $layanan->tanggapan_admin ?? '-'; + $tanggal = now()->format('d-m-Y H:i'); + + // ===================== + // 📱 WHATSAPP via WhatsappService (Fix Fonnte) + // ===================== + if (!empty($layanan->penghuni->telepon)) { + + $pesan = "🏡 *GREEN VIEW RESIDENCE*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "📢 *NOTIFIKASI PENGADUAN*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n\n"; + $pesan .= "Halo *{$nama}* 👋\n\n"; + $pesan .= "Pengaduan Anda telah mendapatkan update terbaru.\n\n"; + $pesan .= "📌 *DETAIL PENGADUAN*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "🗂️ Status : *{$statusText}*\n"; + $pesan .= "📅 Tanggal : {$tanggal}\n\n"; + $pesan .= "💬 *TANGGAPAN*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "{$tanggapan}\n\n"; + $pesan .= "📲 Cek detail: " . url('/') . "\n\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "🙏 Terima kasih atas kepercayaan Anda\n"; + $pesan .= "🏡 *Green View Residence*"; + + // ✅ Pakai WhatsappService (sudah ada normalizePhone & config token) + $terkirim = WhatsappService::send($layanan->penghuni->telepon, $pesan); + + if (!$terkirim) { + Log::warning('[Layanan] WA gagal ke: ' . $layanan->penghuni->telepon); + } + } + + // ===================== + // 📧 EMAIL + // ===================== + if (!empty($layanan->penghuni->email)) { + try { + Mail::to($layanan->penghuni->email) + ->send(new NotifPengaduan($layanan)); + } catch (\Exception $e) { + Log::error('[Layanan] Email gagal: ' . $e->getMessage()); + } + } + } +} diff --git a/.history/app/Http/Controllers/LayananController_20260624223815.php b/.history/app/Http/Controllers/LayananController_20260624223815.php new file mode 100644 index 0000000..6f5c7d7 --- /dev/null +++ b/.history/app/Http/Controllers/LayananController_20260624223815.php @@ -0,0 +1,173 @@ +role == 'admin') { + $layanan = Layanan::with('penghuni') + ->whereIn('status', ['menunggu', 'selesai']) + ->latest() + ->get(); + } else { + $rtId = $user->id; + $layanan = Layanan::with('penghuni') + ->whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + }) + ->latest() + ->get(); + } + + return view('admin.layanan.index', compact('layanan')); + } + + public function store(Request $request) + { + Layanan::create([ + 'penghuni_id' => $request->penghuni_id, + 'tanggal_pengaduan' => now(), + 'kategori_masalah' => $request->kategori_masalah, + 'deskripsi' => $request->deskripsi, + 'status' => 'diajukan' + ]); + + return back()->with('success', 'Pengaduan berhasil ditambahkan'); + } + + public function tanggapi(Request $request, $id) + { + $request->validate([ + 'tanggapan_admin' => 'required|string', + 'status' => 'required|in:diproses,selesai' + ]); + + $layanan = Layanan::with('penghuni')->find($id); + + if (!$layanan) { + return back()->with('error', 'Data tidak ditemukan'); + } + + $layanan->tanggapan_admin = $request->tanggapan_admin; + $layanan->status = $request->status; + $layanan->save(); + + // ✅ Kirim notif WA + Email + $this->kirimNotif($layanan); + + return redirect()->route('layanan.index') + ->with('success', 'Tanggapan berhasil dikirim & notifikasi terkirim.'); + } + + public function destroy($id) + { + Layanan::findOrFail($id)->delete(); + return back()->with('success', 'Data berhasil dihapus'); + } + + public function tanggapiRT(Request $request, $id) + { + $request->validate([ + 'tanggapan_admin' => 'required' + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->tanggapan_admin = $request->tanggapan_admin; + $layanan->status = 'menunggu'; // diteruskan ke admin + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Berhasil ditanggapi RT & notifikasi terkirim.'); + } + + public function approveAdmin($id) + { + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->status = 'selesai'; + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Disetujui Admin & notifikasi terkirim.'); + } + + public function indexAdmin() + { + $layanan = Layanan::with('penghuni') + ->where('status', 'menunggu') + ->latest() + ->get(); + + return view('admin.layanan.index', compact('layanan')); + } + + // ========================================================= + // ✅ PRIVATE: Kirim Notifikasi WA + Email sekaligus + // ========================================================= + private function kirimNotif($layanan) + { + if (!$layanan->penghuni) return; + + $nama = $layanan->penghuni->nama; + $statusText = $layanan->status === 'selesai' ? '✅ SELESAI' : '⏳ SEDANG DIPROSES'; + $tanggapan = $layanan->tanggapan_admin ?? '-'; + $tanggal = now()->format('d-m-Y H:i'); + + // ===================== + // 📱 WHATSAPP via WhatsappService (Fix Fonnte) + // ===================== + if (!empty($layanan->penghuni->telepon)) { + + $pesan = "🏡 *GREEN VIEW RESIDENCE*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "📢 *NOTIFIKASI PENGADUAN*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n\n"; + $pesan .= "Halo *{$nama}* 👋\n\n"; + $pesan .= "Pengaduan Anda telah mendapatkan update terbaru.\n\n"; + $pesan .= "📌 *DETAIL PENGADUAN*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "🗂️ Status : *{$statusText}*\n"; + $pesan .= "📅 Tanggal : {$tanggal}\n\n"; + $pesan .= "💬 *TANGGAPAN*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "{$tanggapan}\n\n"; + $pesan .= "📲 Cek detail: " . url('/') . "\n\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "🙏 Terima kasih atas kepercayaan Anda\n"; + $pesan .= "🏡 *Green View Residence*"; + + // ✅ Pakai WhatsappService (sudah ada normalizePhone & config token) + $terkirim = WhatsappService::send($layanan->penghuni->telepon, $pesan); + + if (!$terkirim) { + Log::warning('[Layanan] WA gagal ke: ' . $layanan->penghuni->telepon); + } + } + + // ===================== + // 📧 EMAIL + // ===================== + if (!empty($layanan->penghuni->email)) { + try { + Mail::to($layanan->penghuni->email) + ->send(new NotifPengaduan($layanan)); + } catch (\Exception $e) { + Log::error('[Layanan] Email gagal: ' . $e->getMessage()); + } + } + } +} diff --git a/.history/app/Http/Controllers/LayananController_20260624223845.php b/.history/app/Http/Controllers/LayananController_20260624223845.php new file mode 100644 index 0000000..333c4f0 --- /dev/null +++ b/.history/app/Http/Controllers/LayananController_20260624223845.php @@ -0,0 +1,205 @@ +role == 'admin') { + $layanan = Layanan::with('penghuni') + ->whereIn('status', ['menunggu', 'selesai']) + ->latest() + ->get(); + } else { + $rtId = $user->id; + $layanan = Layanan::with('penghuni') + ->whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + }) + ->latest() + ->get(); + } + + return view('admin.layanan.index', compact('layanan')); + } + + public function store(Request $request) + { + Layanan::create([ + 'penghuni_id' => $request->penghuni_id, + 'tanggal_pengaduan' => now(), + 'kategori_masalah' => $request->kategori_masalah, + 'deskripsi' => $request->deskripsi, + 'status' => 'diajukan' + ]); + + return back()->with('success', 'Pengaduan berhasil ditambahkan'); + } + + public function tanggapi(Request $request, $id) + { + $request->validate([ + 'tanggapan_admin' => 'required|string', + 'status' => 'required|in:diproses,selesai' + ]); + + $layanan = Layanan::with('penghuni')->find($id); + + if (!$layanan) { + return back()->with('error', 'Data tidak ditemukan'); + } + + $layanan->tanggapan_admin = $request->tanggapan_admin; + $layanan->status = $request->status; + $layanan->save(); + + // ✅ Kirim notif WA + Email + $this->kirimNotif($layanan); + + return redirect()->route('layanan.index') + ->with('success', 'Tanggapan berhasil dikirim & notifikasi terkirim.'); + } + + public function destroy($id) + { + Layanan::findOrFail($id)->delete(); + return back()->with('success', 'Data berhasil dihapus'); + } + + public function tanggapiRT(Request $request, $id) +{ + $request->validate([ + 'tanggapan_admin' => 'required' + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->tanggapan_admin = $request->tanggapan_admin; + $layanan->status = 'diproses'; // RT yang menangani langsung, tanpa admin + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Berhasil ditanggapi RT & notifikasi terkirim.'); +} + +// ========================================================= +// ✅ RT KONFIRMASI SELESAI (gantikan approve admin) +// Manual: catatan penyelesaian + foto bukti +// Tidak perlu kolom/migration baru: +// - tanggapan_admin dipakai utk gabungkan catatan RT awal + catatan selesai +// - foto digabung koma (foto pengaduan awal tetap ada, foto bukti selesai ditambahkan) +// ========================================================= +public function konfirmasiRT(Request $request, $id) +{ + $request->validate([ + 'catatan_selesai' => 'required|string', + 'foto_bukti' => 'nullable|image|mimes:jpg,jpeg,png|max:2048', + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + + $catatanLama = $layanan->tanggapan_admin ? $layanan->tanggapan_admin . "\n\n" : ''; + $layanan->tanggapan_admin = $catatanLama . '✅ Konfirmasi Selesai (RT): ' . $request->catatan_selesai; + + if ($request->hasFile('foto_bukti')) { + $path = $request->file('foto_bukti')->store('pengaduan', 'public'); + $layanan->foto = $layanan->foto ? $layanan->foto . ',' . $path : $path; + } + + $layanan->status = 'selesai'; + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Pengaduan dikonfirmasi selesai oleh RT & notifikasi terkirim.'); +} + + public function approveAdmin($id) + { + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->status = 'selesai'; + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Disetujui Admin & notifikasi terkirim.'); + } + + public function indexAdmin() + { + $layanan = Layanan::with('penghuni') + ->where('status', 'menunggu') + ->latest() + ->get(); + + return view('admin.layanan.index', compact('layanan')); + } + + // ========================================================= + // ✅ PRIVATE: Kirim Notifikasi WA + Email sekaligus + // ========================================================= + private function kirimNotif($layanan) + { + if (!$layanan->penghuni) return; + + $nama = $layanan->penghuni->nama; + $statusText = $layanan->status === 'selesai' ? '✅ SELESAI' : '⏳ SEDANG DIPROSES'; + $tanggapan = $layanan->tanggapan_admin ?? '-'; + $tanggal = now()->format('d-m-Y H:i'); + + // ===================== + // 📱 WHATSAPP via WhatsappService (Fix Fonnte) + // ===================== + if (!empty($layanan->penghuni->telepon)) { + + $pesan = "🏡 *GREEN VIEW RESIDENCE*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "📢 *NOTIFIKASI PENGADUAN*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n\n"; + $pesan .= "Halo *{$nama}* 👋\n\n"; + $pesan .= "Pengaduan Anda telah mendapatkan update terbaru.\n\n"; + $pesan .= "📌 *DETAIL PENGADUAN*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "🗂️ Status : *{$statusText}*\n"; + $pesan .= "📅 Tanggal : {$tanggal}\n\n"; + $pesan .= "💬 *TANGGAPAN*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "{$tanggapan}\n\n"; + $pesan .= "📲 Cek detail: " . url('/') . "\n\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "🙏 Terima kasih atas kepercayaan Anda\n"; + $pesan .= "🏡 *Green View Residence*"; + + // ✅ Pakai WhatsappService (sudah ada normalizePhone & config token) + $terkirim = WhatsappService::send($layanan->penghuni->telepon, $pesan); + + if (!$terkirim) { + Log::warning('[Layanan] WA gagal ke: ' . $layanan->penghuni->telepon); + } + } + + // ===================== + // 📧 EMAIL + // ===================== + if (!empty($layanan->penghuni->email)) { + try { + Mail::to($layanan->penghuni->email) + ->send(new NotifPengaduan($layanan)); + } catch (\Exception $e) { + Log::error('[Layanan] Email gagal: ' . $e->getMessage()); + } + } + } +} diff --git a/.history/app/Http/Controllers/LayananController_20260624223857.php b/.history/app/Http/Controllers/LayananController_20260624223857.php new file mode 100644 index 0000000..51103c9 --- /dev/null +++ b/.history/app/Http/Controllers/LayananController_20260624223857.php @@ -0,0 +1,205 @@ +role == 'admin') { + $layanan = Layanan::with('penghuni') + ->whereIn('status', ['menunggu', 'selesai']) + ->latest() + ->get(); + } else { + $rtId = $user->id; + $layanan = Layanan::with('penghuni') + ->whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + }) + ->latest() + ->get(); + } + + return view('admin.layanan.index', compact('layanan')); + } + + public function store(Request $request) + { + Layanan::create([ + 'penghuni_id' => $request->penghuni_id, + 'tanggal_pengaduan' => now(), + 'kategori_masalah' => $request->kategori_masalah, + 'deskripsi' => $request->deskripsi, + 'status' => 'diajukan' + ]); + + return back()->with('success', 'Pengaduan berhasil ditambahkan'); + } + + public function tanggapi(Request $request, $id) + { + $request->validate([ + 'tanggapan_admin' => 'required|string', + 'status' => 'required|in:diproses,selesai' + ]); + + $layanan = Layanan::with('penghuni')->find($id); + + if (!$layanan) { + return back()->with('error', 'Data tidak ditemukan'); + } + + $layanan->tanggapan_admin = $request->tanggapan_admin; + $layanan->status = $request->status; + $layanan->save(); + + // ✅ Kirim notif WA + Email + $this->kirimNotif($layanan); + + return redirect()->route('layanan.index') + ->with('success', 'Tanggapan berhasil dikirim & notifikasi terkirim.'); + } + + public function destroy($id) + { + Layanan::findOrFail($id)->delete(); + return back()->with('success', 'Data berhasil dihapus'); + } + + public function tanggapiRT(Request $request, $id) + { + $request->validate([ + 'tanggapan_admin' => 'required' + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->tanggapan_admin = $request->tanggapan_admin; + $layanan->status = 'diproses'; // RT yang menangani langsung, tanpa admin + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Berhasil ditanggapi RT & notifikasi terkirim.'); + } + + // ========================================================= + // ✅ RT KONFIRMASI SELESAI (gantikan approve admin) + // Manual: catatan penyelesaian + foto bukti + // Tidak perlu kolom/migration baru: + // - tanggapan_admin dipakai utk gabungkan catatan RT awal + catatan selesai + // - foto digabung koma (foto pengaduan awal tetap ada, foto bukti selesai ditambahkan) + // ========================================================= + public function konfirmasiRT(Request $request, $id) + { + $request->validate([ + 'catatan_selesai' => 'required|string', + 'foto_bukti' => 'nullable|image|mimes:jpg,jpeg,png|max:2048', + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + + $catatanLama = $layanan->tanggapan_admin ? $layanan->tanggapan_admin . "\n\n" : ''; + $layanan->tanggapan_admin = $catatanLama . '✅ Konfirmasi Selesai (RT): ' . $request->catatan_selesai; + + if ($request->hasFile('foto_bukti')) { + $path = $request->file('foto_bukti')->store('pengaduan', 'public'); + $layanan->foto = $layanan->foto ? $layanan->foto . ',' . $path : $path; + } + + $layanan->status = 'selesai'; + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Pengaduan dikonfirmasi selesai oleh RT & notifikasi terkirim.'); + } + + public function approveAdmin($id) + { + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->status = 'selesai'; + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Disetujui Admin & notifikasi terkirim.'); + } + + public function indexAdmin() + { + $layanan = Layanan::with('penghuni') + ->where('status', 'menunggu') + ->latest() + ->get(); + + return view('admin.layanan.index', compact('layanan')); + } + + // ========================================================= + // ✅ PRIVATE: Kirim Notifikasi WA + Email sekaligus + // ========================================================= + private function kirimNotif($layanan) + { + if (!$layanan->penghuni) return; + + $nama = $layanan->penghuni->nama; + $statusText = $layanan->status === 'selesai' ? '✅ SELESAI' : '⏳ SEDANG DIPROSES'; + $tanggapan = $layanan->tanggapan_admin ?? '-'; + $tanggal = now()->format('d-m-Y H:i'); + + // ===================== + // 📱 WHATSAPP via WhatsappService (Fix Fonnte) + // ===================== + if (!empty($layanan->penghuni->telepon)) { + + $pesan = "🏡 *GREEN VIEW RESIDENCE*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "📢 *NOTIFIKASI PENGADUAN*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n\n"; + $pesan .= "Halo *{$nama}* 👋\n\n"; + $pesan .= "Pengaduan Anda telah mendapatkan update terbaru.\n\n"; + $pesan .= "📌 *DETAIL PENGADUAN*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "🗂️ Status : *{$statusText}*\n"; + $pesan .= "📅 Tanggal : {$tanggal}\n\n"; + $pesan .= "💬 *TANGGAPAN*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "{$tanggapan}\n\n"; + $pesan .= "📲 Cek detail: " . url('/') . "\n\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "🙏 Terima kasih atas kepercayaan Anda\n"; + $pesan .= "🏡 *Green View Residence*"; + + // ✅ Pakai WhatsappService (sudah ada normalizePhone & config token) + $terkirim = WhatsappService::send($layanan->penghuni->telepon, $pesan); + + if (!$terkirim) { + Log::warning('[Layanan] WA gagal ke: ' . $layanan->penghuni->telepon); + } + } + + // ===================== + // 📧 EMAIL + // ===================== + if (!empty($layanan->penghuni->email)) { + try { + Mail::to($layanan->penghuni->email) + ->send(new NotifPengaduan($layanan)); + } catch (\Exception $e) { + Log::error('[Layanan] Email gagal: ' . $e->getMessage()); + } + } + } +} diff --git a/.history/app/Http/Controllers/LayananController_20260624224251.php b/.history/app/Http/Controllers/LayananController_20260624224251.php new file mode 100644 index 0000000..6f5c7d7 --- /dev/null +++ b/.history/app/Http/Controllers/LayananController_20260624224251.php @@ -0,0 +1,173 @@ +role == 'admin') { + $layanan = Layanan::with('penghuni') + ->whereIn('status', ['menunggu', 'selesai']) + ->latest() + ->get(); + } else { + $rtId = $user->id; + $layanan = Layanan::with('penghuni') + ->whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + }) + ->latest() + ->get(); + } + + return view('admin.layanan.index', compact('layanan')); + } + + public function store(Request $request) + { + Layanan::create([ + 'penghuni_id' => $request->penghuni_id, + 'tanggal_pengaduan' => now(), + 'kategori_masalah' => $request->kategori_masalah, + 'deskripsi' => $request->deskripsi, + 'status' => 'diajukan' + ]); + + return back()->with('success', 'Pengaduan berhasil ditambahkan'); + } + + public function tanggapi(Request $request, $id) + { + $request->validate([ + 'tanggapan_admin' => 'required|string', + 'status' => 'required|in:diproses,selesai' + ]); + + $layanan = Layanan::with('penghuni')->find($id); + + if (!$layanan) { + return back()->with('error', 'Data tidak ditemukan'); + } + + $layanan->tanggapan_admin = $request->tanggapan_admin; + $layanan->status = $request->status; + $layanan->save(); + + // ✅ Kirim notif WA + Email + $this->kirimNotif($layanan); + + return redirect()->route('layanan.index') + ->with('success', 'Tanggapan berhasil dikirim & notifikasi terkirim.'); + } + + public function destroy($id) + { + Layanan::findOrFail($id)->delete(); + return back()->with('success', 'Data berhasil dihapus'); + } + + public function tanggapiRT(Request $request, $id) + { + $request->validate([ + 'tanggapan_admin' => 'required' + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->tanggapan_admin = $request->tanggapan_admin; + $layanan->status = 'menunggu'; // diteruskan ke admin + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Berhasil ditanggapi RT & notifikasi terkirim.'); + } + + public function approveAdmin($id) + { + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->status = 'selesai'; + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Disetujui Admin & notifikasi terkirim.'); + } + + public function indexAdmin() + { + $layanan = Layanan::with('penghuni') + ->where('status', 'menunggu') + ->latest() + ->get(); + + return view('admin.layanan.index', compact('layanan')); + } + + // ========================================================= + // ✅ PRIVATE: Kirim Notifikasi WA + Email sekaligus + // ========================================================= + private function kirimNotif($layanan) + { + if (!$layanan->penghuni) return; + + $nama = $layanan->penghuni->nama; + $statusText = $layanan->status === 'selesai' ? '✅ SELESAI' : '⏳ SEDANG DIPROSES'; + $tanggapan = $layanan->tanggapan_admin ?? '-'; + $tanggal = now()->format('d-m-Y H:i'); + + // ===================== + // 📱 WHATSAPP via WhatsappService (Fix Fonnte) + // ===================== + if (!empty($layanan->penghuni->telepon)) { + + $pesan = "🏡 *GREEN VIEW RESIDENCE*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "📢 *NOTIFIKASI PENGADUAN*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n\n"; + $pesan .= "Halo *{$nama}* 👋\n\n"; + $pesan .= "Pengaduan Anda telah mendapatkan update terbaru.\n\n"; + $pesan .= "📌 *DETAIL PENGADUAN*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "🗂️ Status : *{$statusText}*\n"; + $pesan .= "📅 Tanggal : {$tanggal}\n\n"; + $pesan .= "💬 *TANGGAPAN*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "{$tanggapan}\n\n"; + $pesan .= "📲 Cek detail: " . url('/') . "\n\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "🙏 Terima kasih atas kepercayaan Anda\n"; + $pesan .= "🏡 *Green View Residence*"; + + // ✅ Pakai WhatsappService (sudah ada normalizePhone & config token) + $terkirim = WhatsappService::send($layanan->penghuni->telepon, $pesan); + + if (!$terkirim) { + Log::warning('[Layanan] WA gagal ke: ' . $layanan->penghuni->telepon); + } + } + + // ===================== + // 📧 EMAIL + // ===================== + if (!empty($layanan->penghuni->email)) { + try { + Mail::to($layanan->penghuni->email) + ->send(new NotifPengaduan($layanan)); + } catch (\Exception $e) { + Log::error('[Layanan] Email gagal: ' . $e->getMessage()); + } + } + } +} diff --git a/.history/app/Http/Controllers/LayananController_20260625013509.php b/.history/app/Http/Controllers/LayananController_20260625013509.php new file mode 100644 index 0000000..9f85beb --- /dev/null +++ b/.history/app/Http/Controllers/LayananController_20260625013509.php @@ -0,0 +1,232 @@ +getMessage()); + } + } + + // ============================================================ + // INDEX — RT & Admin + // ============================================================ + public function index() + { + $user = Auth::user(); + + if ($user->role == 'admin') { + // Admin hanya lihat (tidak ada approve lagi, hanya view) + $layanan = Layanan::with('penghuni') + ->latest() + ->get(); + } else { + // RT lihat pengaduan penghuni di RT-nya + $rtId = $user->id; + $layanan = Layanan::with('penghuni') + ->whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + }) + ->latest() + ->get(); + } + + return view('admin.layanan.index', compact('layanan')); + } + + // ============================================================ + // STORE — dari admin panel (jika ada) + // ============================================================ + public function store(Request $request) + { + Layanan::create([ + 'penghuni_id' => $request->penghuni_id, + 'tanggal_pengaduan' => now(), + 'kategori_masalah' => $request->kategori_masalah, + 'deskripsi' => $request->deskripsi, + 'status' => 'diajukan' + ]); + + return back()->with('success', 'Pengaduan berhasil ditambahkan'); + } + + // ============================================================ + // TANGGAPI RT — RT memberi tanggapan awal (status: diproses) + // ============================================================ + public function tanggapiRT(Request $request, $id) + { + $request->validate([ + 'tanggapan_admin' => 'required|string', + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->tanggapan_admin = $request->tanggapan_admin; + $layanan->status = 'diproses'; + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Tanggapan berhasil dikirim ke penghuni.'); + } + + // ============================================================ + // KONFIRMASI SELESAI — RT konfirmasi selesai + foto bukti + // ============================================================ + public function konfirmasiSelesai(Request $request, $id) + { + $request->validate([ + 'catatan_selesai' => 'required|string', + 'foto_bukti_rt' => 'nullable|image|mimes:jpg,jpeg,png|max:3072', + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + + // Simpan catatan selesai + $layanan->catatan_selesai = $request->catatan_selesai; + $layanan->status = 'selesai'; + + // Upload foto bukti RT jika ada + if ($request->hasFile('foto_bukti_rt')) { + $path = $request->file('foto_bukti_rt')->store('bukti_rt', 'public'); + $layanan->foto_bukti_rt = $path; + } + + $layanan->save(); + + // Kirim notifikasi selesai + $this->kirimNotifSelesai($layanan); + + return back()->with('success', 'Pengaduan dikonfirmasi selesai & notifikasi terkirim.'); + } + + // ============================================================ + // DESTROY + // ============================================================ + public function destroy($id) + { + Layanan::findOrFail($id)->delete(); + return back()->with('success', 'Data berhasil dihapus'); + } + + // ============================================================ + // INDEX ADMIN (view only) + // ============================================================ + public function indexAdmin() + { + $layanan = Layanan::with('penghuni')->latest()->get(); + return view('admin.layanan.index', compact('layanan')); + } + + // ============================================================ + // PRIVATE: Notif tanggapan awal (diproses) + // ============================================================ + private function kirimNotif($layanan) + { + if (!$layanan->penghuni) return; + + $nama = $layanan->penghuni->nama; + $tanggapan = $layanan->tanggapan_admin ?? '-'; + $tanggal = now()->format('d-m-Y H:i'); + + // WhatsApp + if (!empty($layanan->penghuni->telepon)) { + $pesan = "🏡 *GREEN VIEW RESIDENCE*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "📢 *NOTIFIKASI PENGADUAN*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n\n"; + $pesan .= "Halo *{$nama}* 👋\n\n"; + $pesan .= "Pengaduan Anda sedang *DIPROSES* oleh RT.\n\n"; + $pesan .= "📌 *TANGGAPAN RT*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "{$tanggapan}\n\n"; + $pesan .= "📅 Tanggal: {$tanggal}\n"; + $pesan .= "📲 Cek detail: " . url('/') . "\n\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "🙏 Terima kasih atas kepercayaan Anda\n"; + $pesan .= "🏡 *Green View Residence*"; + + $terkirim = WhatsappService::send($layanan->penghuni->telepon, $pesan); + if (!$terkirim) { + Log::warning('[Layanan] WA gagal ke: ' . $layanan->penghuni->telepon); + } + } + + // Email + if (!empty($layanan->penghuni->email)) { + try { + Mail::to($layanan->penghuni->email)->send(new NotifPengaduan($layanan)); + } catch (\Exception $e) { + Log::error('[Layanan] Email gagal: ' . $e->getMessage()); + } + } + } + + // ============================================================ + // PRIVATE: Notif selesai (RT konfirmasi selesai) + // ============================================================ + private function kirimNotifSelesai($layanan) + { + if (!$layanan->penghuni) return; + + $nama = $layanan->penghuni->nama; + $catatan = $layanan->catatan_selesai ?? '-'; + $tanggal = now()->format('d-m-Y H:i'); + + // WhatsApp + if (!empty($layanan->penghuni->telepon)) { + $pesan = "🏡 *GREEN VIEW RESIDENCE*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "✅ *PENGADUAN SELESAI*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n\n"; + $pesan .= "Halo *{$nama}* 👋\n\n"; + $pesan .= "Pengaduan Anda telah *SELESAI* ditangani oleh RT.\n\n"; + $pesan .= "📋 *KETERANGAN PENYELESAIAN*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "{$catatan}\n\n"; + $pesan .= "📅 Tanggal Selesai: {$tanggal}\n"; + $pesan .= "📲 Lihat bukti: " . url('/') . "\n\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "🙏 Terima kasih telah menggunakan layanan kami\n"; + $pesan .= "🏡 *Green View Residence*"; + + $terkirim = WhatsappService::send($layanan->penghuni->telepon, $pesan); + if (!$terkirim) { + Log::warning('[Layanan] WA selesai gagal ke: ' . $layanan->penghuni->telepon); + } + } + + // Email + if (!empty($layanan->penghuni->email)) { + try { + Mail::to($layanan->penghuni->email)->send(new \App\Mail\NotifPengaduanSelesai($layanan)); + } catch (\Exception $e) { + Log::error('[Layanan] Email selesai gagal: ' . $e->getMessage()); + } + } + } +} diff --git a/.history/app/Http/Controllers/LayananController_20260625013511.php b/.history/app/Http/Controllers/LayananController_20260625013511.php new file mode 100644 index 0000000..6f5c7d7 --- /dev/null +++ b/.history/app/Http/Controllers/LayananController_20260625013511.php @@ -0,0 +1,173 @@ +role == 'admin') { + $layanan = Layanan::with('penghuni') + ->whereIn('status', ['menunggu', 'selesai']) + ->latest() + ->get(); + } else { + $rtId = $user->id; + $layanan = Layanan::with('penghuni') + ->whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + }) + ->latest() + ->get(); + } + + return view('admin.layanan.index', compact('layanan')); + } + + public function store(Request $request) + { + Layanan::create([ + 'penghuni_id' => $request->penghuni_id, + 'tanggal_pengaduan' => now(), + 'kategori_masalah' => $request->kategori_masalah, + 'deskripsi' => $request->deskripsi, + 'status' => 'diajukan' + ]); + + return back()->with('success', 'Pengaduan berhasil ditambahkan'); + } + + public function tanggapi(Request $request, $id) + { + $request->validate([ + 'tanggapan_admin' => 'required|string', + 'status' => 'required|in:diproses,selesai' + ]); + + $layanan = Layanan::with('penghuni')->find($id); + + if (!$layanan) { + return back()->with('error', 'Data tidak ditemukan'); + } + + $layanan->tanggapan_admin = $request->tanggapan_admin; + $layanan->status = $request->status; + $layanan->save(); + + // ✅ Kirim notif WA + Email + $this->kirimNotif($layanan); + + return redirect()->route('layanan.index') + ->with('success', 'Tanggapan berhasil dikirim & notifikasi terkirim.'); + } + + public function destroy($id) + { + Layanan::findOrFail($id)->delete(); + return back()->with('success', 'Data berhasil dihapus'); + } + + public function tanggapiRT(Request $request, $id) + { + $request->validate([ + 'tanggapan_admin' => 'required' + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->tanggapan_admin = $request->tanggapan_admin; + $layanan->status = 'menunggu'; // diteruskan ke admin + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Berhasil ditanggapi RT & notifikasi terkirim.'); + } + + public function approveAdmin($id) + { + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->status = 'selesai'; + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Disetujui Admin & notifikasi terkirim.'); + } + + public function indexAdmin() + { + $layanan = Layanan::with('penghuni') + ->where('status', 'menunggu') + ->latest() + ->get(); + + return view('admin.layanan.index', compact('layanan')); + } + + // ========================================================= + // ✅ PRIVATE: Kirim Notifikasi WA + Email sekaligus + // ========================================================= + private function kirimNotif($layanan) + { + if (!$layanan->penghuni) return; + + $nama = $layanan->penghuni->nama; + $statusText = $layanan->status === 'selesai' ? '✅ SELESAI' : '⏳ SEDANG DIPROSES'; + $tanggapan = $layanan->tanggapan_admin ?? '-'; + $tanggal = now()->format('d-m-Y H:i'); + + // ===================== + // 📱 WHATSAPP via WhatsappService (Fix Fonnte) + // ===================== + if (!empty($layanan->penghuni->telepon)) { + + $pesan = "🏡 *GREEN VIEW RESIDENCE*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "📢 *NOTIFIKASI PENGADUAN*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n\n"; + $pesan .= "Halo *{$nama}* 👋\n\n"; + $pesan .= "Pengaduan Anda telah mendapatkan update terbaru.\n\n"; + $pesan .= "📌 *DETAIL PENGADUAN*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "🗂️ Status : *{$statusText}*\n"; + $pesan .= "📅 Tanggal : {$tanggal}\n\n"; + $pesan .= "💬 *TANGGAPAN*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "{$tanggapan}\n\n"; + $pesan .= "📲 Cek detail: " . url('/') . "\n\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "🙏 Terima kasih atas kepercayaan Anda\n"; + $pesan .= "🏡 *Green View Residence*"; + + // ✅ Pakai WhatsappService (sudah ada normalizePhone & config token) + $terkirim = WhatsappService::send($layanan->penghuni->telepon, $pesan); + + if (!$terkirim) { + Log::warning('[Layanan] WA gagal ke: ' . $layanan->penghuni->telepon); + } + } + + // ===================== + // 📧 EMAIL + // ===================== + if (!empty($layanan->penghuni->email)) { + try { + Mail::to($layanan->penghuni->email) + ->send(new NotifPengaduan($layanan)); + } catch (\Exception $e) { + Log::error('[Layanan] Email gagal: ' . $e->getMessage()); + } + } + } +} diff --git a/.history/app/Http/Controllers/LayananController_20260625013512.php b/.history/app/Http/Controllers/LayananController_20260625013512.php new file mode 100644 index 0000000..9f85beb --- /dev/null +++ b/.history/app/Http/Controllers/LayananController_20260625013512.php @@ -0,0 +1,232 @@ +getMessage()); + } + } + + // ============================================================ + // INDEX — RT & Admin + // ============================================================ + public function index() + { + $user = Auth::user(); + + if ($user->role == 'admin') { + // Admin hanya lihat (tidak ada approve lagi, hanya view) + $layanan = Layanan::with('penghuni') + ->latest() + ->get(); + } else { + // RT lihat pengaduan penghuni di RT-nya + $rtId = $user->id; + $layanan = Layanan::with('penghuni') + ->whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + }) + ->latest() + ->get(); + } + + return view('admin.layanan.index', compact('layanan')); + } + + // ============================================================ + // STORE — dari admin panel (jika ada) + // ============================================================ + public function store(Request $request) + { + Layanan::create([ + 'penghuni_id' => $request->penghuni_id, + 'tanggal_pengaduan' => now(), + 'kategori_masalah' => $request->kategori_masalah, + 'deskripsi' => $request->deskripsi, + 'status' => 'diajukan' + ]); + + return back()->with('success', 'Pengaduan berhasil ditambahkan'); + } + + // ============================================================ + // TANGGAPI RT — RT memberi tanggapan awal (status: diproses) + // ============================================================ + public function tanggapiRT(Request $request, $id) + { + $request->validate([ + 'tanggapan_admin' => 'required|string', + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->tanggapan_admin = $request->tanggapan_admin; + $layanan->status = 'diproses'; + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Tanggapan berhasil dikirim ke penghuni.'); + } + + // ============================================================ + // KONFIRMASI SELESAI — RT konfirmasi selesai + foto bukti + // ============================================================ + public function konfirmasiSelesai(Request $request, $id) + { + $request->validate([ + 'catatan_selesai' => 'required|string', + 'foto_bukti_rt' => 'nullable|image|mimes:jpg,jpeg,png|max:3072', + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + + // Simpan catatan selesai + $layanan->catatan_selesai = $request->catatan_selesai; + $layanan->status = 'selesai'; + + // Upload foto bukti RT jika ada + if ($request->hasFile('foto_bukti_rt')) { + $path = $request->file('foto_bukti_rt')->store('bukti_rt', 'public'); + $layanan->foto_bukti_rt = $path; + } + + $layanan->save(); + + // Kirim notifikasi selesai + $this->kirimNotifSelesai($layanan); + + return back()->with('success', 'Pengaduan dikonfirmasi selesai & notifikasi terkirim.'); + } + + // ============================================================ + // DESTROY + // ============================================================ + public function destroy($id) + { + Layanan::findOrFail($id)->delete(); + return back()->with('success', 'Data berhasil dihapus'); + } + + // ============================================================ + // INDEX ADMIN (view only) + // ============================================================ + public function indexAdmin() + { + $layanan = Layanan::with('penghuni')->latest()->get(); + return view('admin.layanan.index', compact('layanan')); + } + + // ============================================================ + // PRIVATE: Notif tanggapan awal (diproses) + // ============================================================ + private function kirimNotif($layanan) + { + if (!$layanan->penghuni) return; + + $nama = $layanan->penghuni->nama; + $tanggapan = $layanan->tanggapan_admin ?? '-'; + $tanggal = now()->format('d-m-Y H:i'); + + // WhatsApp + if (!empty($layanan->penghuni->telepon)) { + $pesan = "🏡 *GREEN VIEW RESIDENCE*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "📢 *NOTIFIKASI PENGADUAN*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n\n"; + $pesan .= "Halo *{$nama}* 👋\n\n"; + $pesan .= "Pengaduan Anda sedang *DIPROSES* oleh RT.\n\n"; + $pesan .= "📌 *TANGGAPAN RT*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "{$tanggapan}\n\n"; + $pesan .= "📅 Tanggal: {$tanggal}\n"; + $pesan .= "📲 Cek detail: " . url('/') . "\n\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "🙏 Terima kasih atas kepercayaan Anda\n"; + $pesan .= "🏡 *Green View Residence*"; + + $terkirim = WhatsappService::send($layanan->penghuni->telepon, $pesan); + if (!$terkirim) { + Log::warning('[Layanan] WA gagal ke: ' . $layanan->penghuni->telepon); + } + } + + // Email + if (!empty($layanan->penghuni->email)) { + try { + Mail::to($layanan->penghuni->email)->send(new NotifPengaduan($layanan)); + } catch (\Exception $e) { + Log::error('[Layanan] Email gagal: ' . $e->getMessage()); + } + } + } + + // ============================================================ + // PRIVATE: Notif selesai (RT konfirmasi selesai) + // ============================================================ + private function kirimNotifSelesai($layanan) + { + if (!$layanan->penghuni) return; + + $nama = $layanan->penghuni->nama; + $catatan = $layanan->catatan_selesai ?? '-'; + $tanggal = now()->format('d-m-Y H:i'); + + // WhatsApp + if (!empty($layanan->penghuni->telepon)) { + $pesan = "🏡 *GREEN VIEW RESIDENCE*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "✅ *PENGADUAN SELESAI*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n\n"; + $pesan .= "Halo *{$nama}* 👋\n\n"; + $pesan .= "Pengaduan Anda telah *SELESAI* ditangani oleh RT.\n\n"; + $pesan .= "📋 *KETERANGAN PENYELESAIAN*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "{$catatan}\n\n"; + $pesan .= "📅 Tanggal Selesai: {$tanggal}\n"; + $pesan .= "📲 Lihat bukti: " . url('/') . "\n\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "🙏 Terima kasih telah menggunakan layanan kami\n"; + $pesan .= "🏡 *Green View Residence*"; + + $terkirim = WhatsappService::send($layanan->penghuni->telepon, $pesan); + if (!$terkirim) { + Log::warning('[Layanan] WA selesai gagal ke: ' . $layanan->penghuni->telepon); + } + } + + // Email + if (!empty($layanan->penghuni->email)) { + try { + Mail::to($layanan->penghuni->email)->send(new \App\Mail\NotifPengaduanSelesai($layanan)); + } catch (\Exception $e) { + Log::error('[Layanan] Email selesai gagal: ' . $e->getMessage()); + } + } + } +} diff --git a/.history/app/Http/Controllers/LayananController_20260625013514.php b/.history/app/Http/Controllers/LayananController_20260625013514.php new file mode 100644 index 0000000..6f5c7d7 --- /dev/null +++ b/.history/app/Http/Controllers/LayananController_20260625013514.php @@ -0,0 +1,173 @@ +role == 'admin') { + $layanan = Layanan::with('penghuni') + ->whereIn('status', ['menunggu', 'selesai']) + ->latest() + ->get(); + } else { + $rtId = $user->id; + $layanan = Layanan::with('penghuni') + ->whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + }) + ->latest() + ->get(); + } + + return view('admin.layanan.index', compact('layanan')); + } + + public function store(Request $request) + { + Layanan::create([ + 'penghuni_id' => $request->penghuni_id, + 'tanggal_pengaduan' => now(), + 'kategori_masalah' => $request->kategori_masalah, + 'deskripsi' => $request->deskripsi, + 'status' => 'diajukan' + ]); + + return back()->with('success', 'Pengaduan berhasil ditambahkan'); + } + + public function tanggapi(Request $request, $id) + { + $request->validate([ + 'tanggapan_admin' => 'required|string', + 'status' => 'required|in:diproses,selesai' + ]); + + $layanan = Layanan::with('penghuni')->find($id); + + if (!$layanan) { + return back()->with('error', 'Data tidak ditemukan'); + } + + $layanan->tanggapan_admin = $request->tanggapan_admin; + $layanan->status = $request->status; + $layanan->save(); + + // ✅ Kirim notif WA + Email + $this->kirimNotif($layanan); + + return redirect()->route('layanan.index') + ->with('success', 'Tanggapan berhasil dikirim & notifikasi terkirim.'); + } + + public function destroy($id) + { + Layanan::findOrFail($id)->delete(); + return back()->with('success', 'Data berhasil dihapus'); + } + + public function tanggapiRT(Request $request, $id) + { + $request->validate([ + 'tanggapan_admin' => 'required' + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->tanggapan_admin = $request->tanggapan_admin; + $layanan->status = 'menunggu'; // diteruskan ke admin + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Berhasil ditanggapi RT & notifikasi terkirim.'); + } + + public function approveAdmin($id) + { + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->status = 'selesai'; + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Disetujui Admin & notifikasi terkirim.'); + } + + public function indexAdmin() + { + $layanan = Layanan::with('penghuni') + ->where('status', 'menunggu') + ->latest() + ->get(); + + return view('admin.layanan.index', compact('layanan')); + } + + // ========================================================= + // ✅ PRIVATE: Kirim Notifikasi WA + Email sekaligus + // ========================================================= + private function kirimNotif($layanan) + { + if (!$layanan->penghuni) return; + + $nama = $layanan->penghuni->nama; + $statusText = $layanan->status === 'selesai' ? '✅ SELESAI' : '⏳ SEDANG DIPROSES'; + $tanggapan = $layanan->tanggapan_admin ?? '-'; + $tanggal = now()->format('d-m-Y H:i'); + + // ===================== + // 📱 WHATSAPP via WhatsappService (Fix Fonnte) + // ===================== + if (!empty($layanan->penghuni->telepon)) { + + $pesan = "🏡 *GREEN VIEW RESIDENCE*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "📢 *NOTIFIKASI PENGADUAN*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n\n"; + $pesan .= "Halo *{$nama}* 👋\n\n"; + $pesan .= "Pengaduan Anda telah mendapatkan update terbaru.\n\n"; + $pesan .= "📌 *DETAIL PENGADUAN*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "🗂️ Status : *{$statusText}*\n"; + $pesan .= "📅 Tanggal : {$tanggal}\n\n"; + $pesan .= "💬 *TANGGAPAN*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "{$tanggapan}\n\n"; + $pesan .= "📲 Cek detail: " . url('/') . "\n\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "🙏 Terima kasih atas kepercayaan Anda\n"; + $pesan .= "🏡 *Green View Residence*"; + + // ✅ Pakai WhatsappService (sudah ada normalizePhone & config token) + $terkirim = WhatsappService::send($layanan->penghuni->telepon, $pesan); + + if (!$terkirim) { + Log::warning('[Layanan] WA gagal ke: ' . $layanan->penghuni->telepon); + } + } + + // ===================== + // 📧 EMAIL + // ===================== + if (!empty($layanan->penghuni->email)) { + try { + Mail::to($layanan->penghuni->email) + ->send(new NotifPengaduan($layanan)); + } catch (\Exception $e) { + Log::error('[Layanan] Email gagal: ' . $e->getMessage()); + } + } + } +} diff --git a/.history/app/Http/Controllers/LayananController_20260625013516.php b/.history/app/Http/Controllers/LayananController_20260625013516.php new file mode 100644 index 0000000..9f85beb --- /dev/null +++ b/.history/app/Http/Controllers/LayananController_20260625013516.php @@ -0,0 +1,232 @@ +getMessage()); + } + } + + // ============================================================ + // INDEX — RT & Admin + // ============================================================ + public function index() + { + $user = Auth::user(); + + if ($user->role == 'admin') { + // Admin hanya lihat (tidak ada approve lagi, hanya view) + $layanan = Layanan::with('penghuni') + ->latest() + ->get(); + } else { + // RT lihat pengaduan penghuni di RT-nya + $rtId = $user->id; + $layanan = Layanan::with('penghuni') + ->whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + }) + ->latest() + ->get(); + } + + return view('admin.layanan.index', compact('layanan')); + } + + // ============================================================ + // STORE — dari admin panel (jika ada) + // ============================================================ + public function store(Request $request) + { + Layanan::create([ + 'penghuni_id' => $request->penghuni_id, + 'tanggal_pengaduan' => now(), + 'kategori_masalah' => $request->kategori_masalah, + 'deskripsi' => $request->deskripsi, + 'status' => 'diajukan' + ]); + + return back()->with('success', 'Pengaduan berhasil ditambahkan'); + } + + // ============================================================ + // TANGGAPI RT — RT memberi tanggapan awal (status: diproses) + // ============================================================ + public function tanggapiRT(Request $request, $id) + { + $request->validate([ + 'tanggapan_admin' => 'required|string', + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->tanggapan_admin = $request->tanggapan_admin; + $layanan->status = 'diproses'; + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Tanggapan berhasil dikirim ke penghuni.'); + } + + // ============================================================ + // KONFIRMASI SELESAI — RT konfirmasi selesai + foto bukti + // ============================================================ + public function konfirmasiSelesai(Request $request, $id) + { + $request->validate([ + 'catatan_selesai' => 'required|string', + 'foto_bukti_rt' => 'nullable|image|mimes:jpg,jpeg,png|max:3072', + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + + // Simpan catatan selesai + $layanan->catatan_selesai = $request->catatan_selesai; + $layanan->status = 'selesai'; + + // Upload foto bukti RT jika ada + if ($request->hasFile('foto_bukti_rt')) { + $path = $request->file('foto_bukti_rt')->store('bukti_rt', 'public'); + $layanan->foto_bukti_rt = $path; + } + + $layanan->save(); + + // Kirim notifikasi selesai + $this->kirimNotifSelesai($layanan); + + return back()->with('success', 'Pengaduan dikonfirmasi selesai & notifikasi terkirim.'); + } + + // ============================================================ + // DESTROY + // ============================================================ + public function destroy($id) + { + Layanan::findOrFail($id)->delete(); + return back()->with('success', 'Data berhasil dihapus'); + } + + // ============================================================ + // INDEX ADMIN (view only) + // ============================================================ + public function indexAdmin() + { + $layanan = Layanan::with('penghuni')->latest()->get(); + return view('admin.layanan.index', compact('layanan')); + } + + // ============================================================ + // PRIVATE: Notif tanggapan awal (diproses) + // ============================================================ + private function kirimNotif($layanan) + { + if (!$layanan->penghuni) return; + + $nama = $layanan->penghuni->nama; + $tanggapan = $layanan->tanggapan_admin ?? '-'; + $tanggal = now()->format('d-m-Y H:i'); + + // WhatsApp + if (!empty($layanan->penghuni->telepon)) { + $pesan = "🏡 *GREEN VIEW RESIDENCE*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "📢 *NOTIFIKASI PENGADUAN*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n\n"; + $pesan .= "Halo *{$nama}* 👋\n\n"; + $pesan .= "Pengaduan Anda sedang *DIPROSES* oleh RT.\n\n"; + $pesan .= "📌 *TANGGAPAN RT*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "{$tanggapan}\n\n"; + $pesan .= "📅 Tanggal: {$tanggal}\n"; + $pesan .= "📲 Cek detail: " . url('/') . "\n\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "🙏 Terima kasih atas kepercayaan Anda\n"; + $pesan .= "🏡 *Green View Residence*"; + + $terkirim = WhatsappService::send($layanan->penghuni->telepon, $pesan); + if (!$terkirim) { + Log::warning('[Layanan] WA gagal ke: ' . $layanan->penghuni->telepon); + } + } + + // Email + if (!empty($layanan->penghuni->email)) { + try { + Mail::to($layanan->penghuni->email)->send(new NotifPengaduan($layanan)); + } catch (\Exception $e) { + Log::error('[Layanan] Email gagal: ' . $e->getMessage()); + } + } + } + + // ============================================================ + // PRIVATE: Notif selesai (RT konfirmasi selesai) + // ============================================================ + private function kirimNotifSelesai($layanan) + { + if (!$layanan->penghuni) return; + + $nama = $layanan->penghuni->nama; + $catatan = $layanan->catatan_selesai ?? '-'; + $tanggal = now()->format('d-m-Y H:i'); + + // WhatsApp + if (!empty($layanan->penghuni->telepon)) { + $pesan = "🏡 *GREEN VIEW RESIDENCE*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "✅ *PENGADUAN SELESAI*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n\n"; + $pesan .= "Halo *{$nama}* 👋\n\n"; + $pesan .= "Pengaduan Anda telah *SELESAI* ditangani oleh RT.\n\n"; + $pesan .= "📋 *KETERANGAN PENYELESAIAN*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "{$catatan}\n\n"; + $pesan .= "📅 Tanggal Selesai: {$tanggal}\n"; + $pesan .= "📲 Lihat bukti: " . url('/') . "\n\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "🙏 Terima kasih telah menggunakan layanan kami\n"; + $pesan .= "🏡 *Green View Residence*"; + + $terkirim = WhatsappService::send($layanan->penghuni->telepon, $pesan); + if (!$terkirim) { + Log::warning('[Layanan] WA selesai gagal ke: ' . $layanan->penghuni->telepon); + } + } + + // Email + if (!empty($layanan->penghuni->email)) { + try { + Mail::to($layanan->penghuni->email)->send(new \App\Mail\NotifPengaduanSelesai($layanan)); + } catch (\Exception $e) { + Log::error('[Layanan] Email selesai gagal: ' . $e->getMessage()); + } + } + } +} diff --git a/.history/app/Http/Controllers/LayananController_20260625013554.php b/.history/app/Http/Controllers/LayananController_20260625013554.php new file mode 100644 index 0000000..029556c --- /dev/null +++ b/.history/app/Http/Controllers/LayananController_20260625013554.php @@ -0,0 +1,30 @@ +belongsTo(\App\Models\Penghuni::class); + } +} diff --git a/.history/app/Http/Controllers/LayananController_20260625013557.php b/.history/app/Http/Controllers/LayananController_20260625013557.php new file mode 100644 index 0000000..9f85beb --- /dev/null +++ b/.history/app/Http/Controllers/LayananController_20260625013557.php @@ -0,0 +1,232 @@ +getMessage()); + } + } + + // ============================================================ + // INDEX — RT & Admin + // ============================================================ + public function index() + { + $user = Auth::user(); + + if ($user->role == 'admin') { + // Admin hanya lihat (tidak ada approve lagi, hanya view) + $layanan = Layanan::with('penghuni') + ->latest() + ->get(); + } else { + // RT lihat pengaduan penghuni di RT-nya + $rtId = $user->id; + $layanan = Layanan::with('penghuni') + ->whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + }) + ->latest() + ->get(); + } + + return view('admin.layanan.index', compact('layanan')); + } + + // ============================================================ + // STORE — dari admin panel (jika ada) + // ============================================================ + public function store(Request $request) + { + Layanan::create([ + 'penghuni_id' => $request->penghuni_id, + 'tanggal_pengaduan' => now(), + 'kategori_masalah' => $request->kategori_masalah, + 'deskripsi' => $request->deskripsi, + 'status' => 'diajukan' + ]); + + return back()->with('success', 'Pengaduan berhasil ditambahkan'); + } + + // ============================================================ + // TANGGAPI RT — RT memberi tanggapan awal (status: diproses) + // ============================================================ + public function tanggapiRT(Request $request, $id) + { + $request->validate([ + 'tanggapan_admin' => 'required|string', + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->tanggapan_admin = $request->tanggapan_admin; + $layanan->status = 'diproses'; + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Tanggapan berhasil dikirim ke penghuni.'); + } + + // ============================================================ + // KONFIRMASI SELESAI — RT konfirmasi selesai + foto bukti + // ============================================================ + public function konfirmasiSelesai(Request $request, $id) + { + $request->validate([ + 'catatan_selesai' => 'required|string', + 'foto_bukti_rt' => 'nullable|image|mimes:jpg,jpeg,png|max:3072', + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + + // Simpan catatan selesai + $layanan->catatan_selesai = $request->catatan_selesai; + $layanan->status = 'selesai'; + + // Upload foto bukti RT jika ada + if ($request->hasFile('foto_bukti_rt')) { + $path = $request->file('foto_bukti_rt')->store('bukti_rt', 'public'); + $layanan->foto_bukti_rt = $path; + } + + $layanan->save(); + + // Kirim notifikasi selesai + $this->kirimNotifSelesai($layanan); + + return back()->with('success', 'Pengaduan dikonfirmasi selesai & notifikasi terkirim.'); + } + + // ============================================================ + // DESTROY + // ============================================================ + public function destroy($id) + { + Layanan::findOrFail($id)->delete(); + return back()->with('success', 'Data berhasil dihapus'); + } + + // ============================================================ + // INDEX ADMIN (view only) + // ============================================================ + public function indexAdmin() + { + $layanan = Layanan::with('penghuni')->latest()->get(); + return view('admin.layanan.index', compact('layanan')); + } + + // ============================================================ + // PRIVATE: Notif tanggapan awal (diproses) + // ============================================================ + private function kirimNotif($layanan) + { + if (!$layanan->penghuni) return; + + $nama = $layanan->penghuni->nama; + $tanggapan = $layanan->tanggapan_admin ?? '-'; + $tanggal = now()->format('d-m-Y H:i'); + + // WhatsApp + if (!empty($layanan->penghuni->telepon)) { + $pesan = "🏡 *GREEN VIEW RESIDENCE*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "📢 *NOTIFIKASI PENGADUAN*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n\n"; + $pesan .= "Halo *{$nama}* 👋\n\n"; + $pesan .= "Pengaduan Anda sedang *DIPROSES* oleh RT.\n\n"; + $pesan .= "📌 *TANGGAPAN RT*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "{$tanggapan}\n\n"; + $pesan .= "📅 Tanggal: {$tanggal}\n"; + $pesan .= "📲 Cek detail: " . url('/') . "\n\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "🙏 Terima kasih atas kepercayaan Anda\n"; + $pesan .= "🏡 *Green View Residence*"; + + $terkirim = WhatsappService::send($layanan->penghuni->telepon, $pesan); + if (!$terkirim) { + Log::warning('[Layanan] WA gagal ke: ' . $layanan->penghuni->telepon); + } + } + + // Email + if (!empty($layanan->penghuni->email)) { + try { + Mail::to($layanan->penghuni->email)->send(new NotifPengaduan($layanan)); + } catch (\Exception $e) { + Log::error('[Layanan] Email gagal: ' . $e->getMessage()); + } + } + } + + // ============================================================ + // PRIVATE: Notif selesai (RT konfirmasi selesai) + // ============================================================ + private function kirimNotifSelesai($layanan) + { + if (!$layanan->penghuni) return; + + $nama = $layanan->penghuni->nama; + $catatan = $layanan->catatan_selesai ?? '-'; + $tanggal = now()->format('d-m-Y H:i'); + + // WhatsApp + if (!empty($layanan->penghuni->telepon)) { + $pesan = "🏡 *GREEN VIEW RESIDENCE*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "✅ *PENGADUAN SELESAI*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n\n"; + $pesan .= "Halo *{$nama}* 👋\n\n"; + $pesan .= "Pengaduan Anda telah *SELESAI* ditangani oleh RT.\n\n"; + $pesan .= "📋 *KETERANGAN PENYELESAIAN*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "{$catatan}\n\n"; + $pesan .= "📅 Tanggal Selesai: {$tanggal}\n"; + $pesan .= "📲 Lihat bukti: " . url('/') . "\n\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "🙏 Terima kasih telah menggunakan layanan kami\n"; + $pesan .= "🏡 *Green View Residence*"; + + $terkirim = WhatsappService::send($layanan->penghuni->telepon, $pesan); + if (!$terkirim) { + Log::warning('[Layanan] WA selesai gagal ke: ' . $layanan->penghuni->telepon); + } + } + + // Email + if (!empty($layanan->penghuni->email)) { + try { + Mail::to($layanan->penghuni->email)->send(new \App\Mail\NotifPengaduanSelesai($layanan)); + } catch (\Exception $e) { + Log::error('[Layanan] Email selesai gagal: ' . $e->getMessage()); + } + } + } +} diff --git a/.history/app/Http/Controllers/LayananController_20260625013601.php b/.history/app/Http/Controllers/LayananController_20260625013601.php new file mode 100644 index 0000000..029556c --- /dev/null +++ b/.history/app/Http/Controllers/LayananController_20260625013601.php @@ -0,0 +1,30 @@ +belongsTo(\App\Models\Penghuni::class); + } +} diff --git a/.history/app/Http/Controllers/LayananController_20260625013607.php b/.history/app/Http/Controllers/LayananController_20260625013607.php new file mode 100644 index 0000000..9f85beb --- /dev/null +++ b/.history/app/Http/Controllers/LayananController_20260625013607.php @@ -0,0 +1,232 @@ +getMessage()); + } + } + + // ============================================================ + // INDEX — RT & Admin + // ============================================================ + public function index() + { + $user = Auth::user(); + + if ($user->role == 'admin') { + // Admin hanya lihat (tidak ada approve lagi, hanya view) + $layanan = Layanan::with('penghuni') + ->latest() + ->get(); + } else { + // RT lihat pengaduan penghuni di RT-nya + $rtId = $user->id; + $layanan = Layanan::with('penghuni') + ->whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + }) + ->latest() + ->get(); + } + + return view('admin.layanan.index', compact('layanan')); + } + + // ============================================================ + // STORE — dari admin panel (jika ada) + // ============================================================ + public function store(Request $request) + { + Layanan::create([ + 'penghuni_id' => $request->penghuni_id, + 'tanggal_pengaduan' => now(), + 'kategori_masalah' => $request->kategori_masalah, + 'deskripsi' => $request->deskripsi, + 'status' => 'diajukan' + ]); + + return back()->with('success', 'Pengaduan berhasil ditambahkan'); + } + + // ============================================================ + // TANGGAPI RT — RT memberi tanggapan awal (status: diproses) + // ============================================================ + public function tanggapiRT(Request $request, $id) + { + $request->validate([ + 'tanggapan_admin' => 'required|string', + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->tanggapan_admin = $request->tanggapan_admin; + $layanan->status = 'diproses'; + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Tanggapan berhasil dikirim ke penghuni.'); + } + + // ============================================================ + // KONFIRMASI SELESAI — RT konfirmasi selesai + foto bukti + // ============================================================ + public function konfirmasiSelesai(Request $request, $id) + { + $request->validate([ + 'catatan_selesai' => 'required|string', + 'foto_bukti_rt' => 'nullable|image|mimes:jpg,jpeg,png|max:3072', + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + + // Simpan catatan selesai + $layanan->catatan_selesai = $request->catatan_selesai; + $layanan->status = 'selesai'; + + // Upload foto bukti RT jika ada + if ($request->hasFile('foto_bukti_rt')) { + $path = $request->file('foto_bukti_rt')->store('bukti_rt', 'public'); + $layanan->foto_bukti_rt = $path; + } + + $layanan->save(); + + // Kirim notifikasi selesai + $this->kirimNotifSelesai($layanan); + + return back()->with('success', 'Pengaduan dikonfirmasi selesai & notifikasi terkirim.'); + } + + // ============================================================ + // DESTROY + // ============================================================ + public function destroy($id) + { + Layanan::findOrFail($id)->delete(); + return back()->with('success', 'Data berhasil dihapus'); + } + + // ============================================================ + // INDEX ADMIN (view only) + // ============================================================ + public function indexAdmin() + { + $layanan = Layanan::with('penghuni')->latest()->get(); + return view('admin.layanan.index', compact('layanan')); + } + + // ============================================================ + // PRIVATE: Notif tanggapan awal (diproses) + // ============================================================ + private function kirimNotif($layanan) + { + if (!$layanan->penghuni) return; + + $nama = $layanan->penghuni->nama; + $tanggapan = $layanan->tanggapan_admin ?? '-'; + $tanggal = now()->format('d-m-Y H:i'); + + // WhatsApp + if (!empty($layanan->penghuni->telepon)) { + $pesan = "🏡 *GREEN VIEW RESIDENCE*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "📢 *NOTIFIKASI PENGADUAN*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n\n"; + $pesan .= "Halo *{$nama}* 👋\n\n"; + $pesan .= "Pengaduan Anda sedang *DIPROSES* oleh RT.\n\n"; + $pesan .= "📌 *TANGGAPAN RT*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "{$tanggapan}\n\n"; + $pesan .= "📅 Tanggal: {$tanggal}\n"; + $pesan .= "📲 Cek detail: " . url('/') . "\n\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "🙏 Terima kasih atas kepercayaan Anda\n"; + $pesan .= "🏡 *Green View Residence*"; + + $terkirim = WhatsappService::send($layanan->penghuni->telepon, $pesan); + if (!$terkirim) { + Log::warning('[Layanan] WA gagal ke: ' . $layanan->penghuni->telepon); + } + } + + // Email + if (!empty($layanan->penghuni->email)) { + try { + Mail::to($layanan->penghuni->email)->send(new NotifPengaduan($layanan)); + } catch (\Exception $e) { + Log::error('[Layanan] Email gagal: ' . $e->getMessage()); + } + } + } + + // ============================================================ + // PRIVATE: Notif selesai (RT konfirmasi selesai) + // ============================================================ + private function kirimNotifSelesai($layanan) + { + if (!$layanan->penghuni) return; + + $nama = $layanan->penghuni->nama; + $catatan = $layanan->catatan_selesai ?? '-'; + $tanggal = now()->format('d-m-Y H:i'); + + // WhatsApp + if (!empty($layanan->penghuni->telepon)) { + $pesan = "🏡 *GREEN VIEW RESIDENCE*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "✅ *PENGADUAN SELESAI*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n\n"; + $pesan .= "Halo *{$nama}* 👋\n\n"; + $pesan .= "Pengaduan Anda telah *SELESAI* ditangani oleh RT.\n\n"; + $pesan .= "📋 *KETERANGAN PENYELESAIAN*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "{$catatan}\n\n"; + $pesan .= "📅 Tanggal Selesai: {$tanggal}\n"; + $pesan .= "📲 Lihat bukti: " . url('/') . "\n\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "🙏 Terima kasih telah menggunakan layanan kami\n"; + $pesan .= "🏡 *Green View Residence*"; + + $terkirim = WhatsappService::send($layanan->penghuni->telepon, $pesan); + if (!$terkirim) { + Log::warning('[Layanan] WA selesai gagal ke: ' . $layanan->penghuni->telepon); + } + } + + // Email + if (!empty($layanan->penghuni->email)) { + try { + Mail::to($layanan->penghuni->email)->send(new \App\Mail\NotifPengaduanSelesai($layanan)); + } catch (\Exception $e) { + Log::error('[Layanan] Email selesai gagal: ' . $e->getMessage()); + } + } + } +} diff --git a/.history/app/Http/Controllers/LayananController_20260625014723.php b/.history/app/Http/Controllers/LayananController_20260625014723.php new file mode 100644 index 0000000..cf752f0 --- /dev/null +++ b/.history/app/Http/Controllers/LayananController_20260625014723.php @@ -0,0 +1,233 @@ +getMessage()); + } + } + + // ============================================================ + // INDEX — RT & Admin + // ============================================================ + public function index() + { + $user = Auth::user(); + + if ($user->role == 'admin') { + // Admin hanya lihat (tidak ada approve lagi, hanya view) + $layanan = Layanan::with('penghuni') + ->latest() + ->get(); + } else { + // RT lihat pengaduan penghuni di RT-nya + $rtId = $user->id; + $layanan = Layanan::with('penghuni') + ->whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + }) + ->latest() + ->get(); + } + + return view('admin.layanan.index', compact('layanan')); + } + + // ============================================================ + // STORE — dari admin panel (jika ada) + // ============================================================ + public function store(Request $request) + { + Layanan::create([ + 'penghuni_id' => $request->penghuni_id, + 'tanggal_pengaduan' => now(), + 'kategori_masalah' => $request->kategori_masalah, + 'deskripsi' => $request->deskripsi, + 'status' => 'diajukan' + ]); + + return back()->with('success', 'Pengaduan berhasil ditambahkan'); + } + + // ============================================================ + // TANGGAPI RT — RT memberi tanggapan awal (status: diproses) + // ============================================================ + public function tanggapiRT(Request $request, $id) + { + $request->validate([ + 'tanggapan_admin' => 'required|string', + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->tanggapan_admin = $request->tanggapan_admin; + $layanan->status = 'diproses'; + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Tanggapan berhasil dikirim ke penghuni.'); + } + + // ============================================================ + // KONFIRMASI SELESAI — RT konfirmasi selesai + foto bukti + // ============================================================ + public function konfirmasiSelesai(Request $request, $id) + { + $request->validate([ + 'catatan_selesai' => 'required|string', + 'foto_bukti_rt' => 'nullable|image|mimes:jpg,jpeg,png|max:3072', + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + + // Simpan catatan selesai + $layanan->catatan_selesai = $request->catatan_selesai; + $layanan->status = 'selesai'; + + // Upload foto bukti RT jika ada + if ($request->hasFile('foto_bukti_rt')) { + $path = $request->file('foto_bukti_rt')->store('bukti_rt', 'public'); + $layanan->foto_bukti_rt = $path; + } + + $layanan->save(); + + // Kirim notifikasi selesai + $this->kirimNotifSelesai($layanan); + + return back()->with('success', 'Pengaduan dikonfirmasi selesai & notifikasi terkirim.'); + } + + // ============================================================ + // DESTROY + // ============================================================ + public function destroy($id) + { + Layanan::findOrFail($id)->delete(); + return back()->with('success', 'Data berhasil dihapus'); + } + + // ============================================================ + // INDEX ADMIN (view only) + // ============================================================ + public function indexAdmin() + { + $layanan = Layanan::with('penghuni')->latest()->get(); + return view('admin.layanan.index', compact('layanan')); + } + + // ============================================================ + // PRIVATE: Notif tanggapan awal (diproses) + // ============================================================ + private function kirimNotif($layanan) + { + if (!$layanan->penghuni) return; + + $nama = $layanan->penghuni->nama; + $tanggapan = $layanan->tanggapan_admin ?? '-'; + $tanggal = now()->format('d-m-Y H:i'); + + // WhatsApp + if (!empty($layanan->penghuni->telepon)) { + $pesan = "🏡 *GREEN VIEW RESIDENCE*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "📢 *NOTIFIKASI PENGADUAN*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n\n"; + $pesan .= "Halo *{$nama}* 👋\n\n"; + $pesan .= "Pengaduan Anda sedang *DIPROSES* oleh RT.\n\n"; + $pesan .= "📌 *TANGGAPAN RT*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "{$tanggapan}\n\n"; + $pesan .= "📅 Tanggal: {$tanggal}\n"; + $pesan .= "📲 Cek detail: " . url('/') . "\n\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "🙏 Terima kasih atas kepercayaan Anda\n"; + $pesan .= "🏡 *Green View Residence*"; + + $terkirim = WhatsappService::send($layanan->penghuni->telepon, $pesan); + if (!$terkirim) { + Log::warning('[Layanan] WA gagal ke: ' . $layanan->penghuni->telepon); + } + } + + // Email + if (!empty($layanan->penghuni->email)) { + try { + Mail::to($layanan->penghuni->email)->send(new NotifPengaduan($layanan)); + } catch (\Exception $e) { + Log::error('[Layanan] Email gagal: ' . $e->getMessage()); + } + } + } + + // ============================================================ + // PRIVATE: Notif selesai (RT konfirmasi selesai) + // ============================================================ + private function kirimNotifSelesai($layanan) + { + if (!$layanan->penghuni) return; + + $nama = $layanan->penghuni->nama; + $catatan = $layanan->catatan_selesai ?? '-'; + $tanggal = now()->format('d-m-Y H:i'); + + // WhatsApp + if (!empty($layanan->penghuni->telepon)) { + $pesan = "🏡 *GREEN VIEW RESIDENCE*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "✅ *PENGADUAN SELESAI*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n\n"; + $pesan .= "Halo *{$nama}* 👋\n\n"; + $pesan .= "Pengaduan Anda telah *SELESAI* ditangani oleh RT.\n\n"; + $pesan .= "📋 *KETERANGAN PENYELESAIAN*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "{$catatan}\n\n"; + $pesan .= "📅 Tanggal Selesai: {$tanggal}\n"; + $pesan .= "📲 Lihat bukti: " . url('/') . "\n\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "🙏 Terima kasih telah menggunakan layanan kami\n"; + $pesan .= "🏡 *Green View Residence*"; + + $terkirim = WhatsappService::send($layanan->penghuni->telepon, $pesan); + if (!$terkirim) { + Log::warning('[Layanan] WA selesai gagal ke: ' . $layanan->penghuni->telepon); + } + } + + // Email + if (!empty($layanan->penghuni->email)) { + try { + Mail::to($layanan->penghuni->email)->send(new \App\Mail\NotifPengaduanSelesai($layanan)); + } catch (\Exception $e) { + Log::error('[Layanan] Email selesai gagal: ' . $e->getMessage()); + } + } + } +} diff --git a/.history/app/Http/Controllers/LayananController_20260625014724.php b/.history/app/Http/Controllers/LayananController_20260625014724.php new file mode 100644 index 0000000..2479469 --- /dev/null +++ b/.history/app/Http/Controllers/LayananController_20260625014724.php @@ -0,0 +1,233 @@ +getMessage()); + } + } + + // ============================================================ + // INDEX — RT & Admin + // ============================================================ + public function index() + { + $user = Auth::user(); + + if ($user->role == 'admin') { + // Admin hanya lihat (tidak ada approve lagi, hanya view) + $layanan = Layanan::with('penghuni') + ->latest() + ->get(); + } else { + // RT lihat pengaduan penghuni di RT-nya + $rtId = $user->id; + $layanan = Layanan::with('penghuni') + ->whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + }) + ->latest() + ->get(); + } + + return view('admin.layanan.index', compact('layanan')); + } + + // ============================================================ + // STORE — dari admin panel (jika ada) + // ============================================================ + public function store(Request $request) + { + Layanan::create([ + 'penghuni_id' => $request->penghuni_id, + 'tanggal_pengaduan' => now(), + 'kategori_masalah' => $request->kategori_masalah, + 'deskripsi' => $request->deskripsi, + 'status' => 'diajukan' + ]); + + return back()->with('success', 'Pengaduan berhasil ditambahkan'); + } + + // ============================================================ + // TANGGAPI RT — RT memberi tanggapan awal (status: diproses) + // ============================================================ + public function tanggapiRT(Request $request, $id) + { + $request->validate([ + 'tanggapan_admin' => 'required|string', + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->tanggapan_admin = $request->tanggapan_admin; + $layanan->status = 'diproses'; + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Tanggapan berhasil dikirim ke penghuni.'); + } + + // ============================================================ + // KONFIRMASI SELESAI — RT konfirmasi selesai + foto bukti + // ============================================================ + public function konfirmasiSelesai(Request $request, $id) + { + $request->validate([ + 'catatan_selesai' => 'required|string', + 'foto_bukti_rt' => 'nullable|image|mimes:jpg,jpeg,png|max:3072', + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + + // Simpan catatan selesai + $layanan->catatan_selesai = $request->catatan_selesai; + $layanan->status = 'selesai'; + + // Upload foto bukti RT jika ada + if ($request->hasFile('foto_bukti_rt')) { + $path = $request->file('foto_bukti_rt')->store('bukti_rt', 'public'); + $layanan->foto_bukti_rt = $path; + } + + $layanan->save(); + + // Kirim notifikasi selesai + $this->kirimNotifSelesai($layanan); + + return back()->with('success', 'Pengaduan dikonfirmasi selesai & notifikasi terkirim.'); + } + + // ============================================================ + // DESTROY + // ============================================================ + public function destroy($id) + { + Layanan::findOrFail($id)->delete(); + return back()->with('success', 'Data berhasil dihapus'); + } + + // ============================================================ + // INDEX ADMIN (view only) + // ============================================================ + public function indexAdmin() + { + $layanan = Layanan::with('penghuni')->latest()->get(); + return view('admin.layanan.index', compact('layanan')); + } + + // ============================================================ + // PRIVATE: Notif tanggapan awal (diproses) + // ============================================================ + private function kirimNotif($layanan) + { + if (!$layanan->penghuni) return; + + $nama = $layanan->penghuni->nama; + $tanggapan = $layanan->tanggapan_admin ?? '-'; + $tanggal = now()->format('d-m-Y H:i'); + + // WhatsApp + if (!empty($layanan->penghuni->telepon)) { + $pesan = "🏡 *GREEN VIEW RESIDENCE*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "📢 *NOTIFIKASI PENGADUAN*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n\n"; + $pesan .= "Halo *{$nama}* 👋\n\n"; + $pesan .= "Pengaduan Anda sedang *DIPROSES* oleh RT.\n\n"; + $pesan .= "📌 *TANGGAPAN RT*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "{$tanggapan}\n\n"; + $pesan .= "📅 Tanggal: {$tanggal}\n"; + $pesan .= "📲 Cek detail: " . url('/') . "\n\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "🙏 Terima kasih atas kepercayaan Anda\n"; + $pesan .= "🏡 *Green View Residence*"; + + $terkirim = WhatsappService::send($layanan->penghuni->telepon, $pesan); + if (!$terkirim) { + Log::warning('[Layanan] WA gagal ke: ' . $layanan->penghuni->telepon); + } + } + + // Email + if (!empty($layanan->penghuni->email)) { + try { + Mail::to($layanan->penghuni->email)->send(new NotifPengaduan($layanan)); + } catch (\Exception $e) { + Log::error('[Layanan] Email gagal: ' . $e->getMessage()); + } + } + } + + // ============================================================ + // PRIVATE: Notif selesai (RT konfirmasi selesai) + // ============================================================ + private function kirimNotifSelesai($layanan) + { + if (!$layanan->penghuni) return; + + $nama = $layanan->penghuni->nama; + $catatan = $layanan->catatan_selesai ?? '-'; + $tanggal = now()->format('d-m-Y H:i'); + + // WhatsApp + if (!empty($layanan->penghuni->telepon)) { + $pesan = "🏡 *GREEN VIEW RESIDENCE*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "✅ *PENGADUAN SELESAI*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n\n"; + $pesan .= "Halo *{$nama}* 👋\n\n"; + $pesan .= "Pengaduan Anda telah *SELESAI* ditangani oleh RT.\n\n"; + $pesan .= "📋 *KETERANGAN PENYELESAIAN*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "{$catatan}\n\n"; + $pesan .= "📅 Tanggal Selesai: {$tanggal}\n"; + $pesan .= "📲 Lihat bukti: " . url('/') . "\n\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "🙏 Terima kasih telah menggunakan layanan kami\n"; + $pesan .= "🏡 *Green View Residence*"; + + $terkirim = WhatsappService::send($layanan->penghuni->telepon, $pesan); + if (!$terkirim) { + Log::warning('[Layanan] WA selesai gagal ke: ' . $layanan->penghuni->telepon); + } + } + + // Email + if (!empty($layanan->penghuni->email)) { + try { + Mail::to($layanan->penghuni->email)->send(new \App\Mail\NotifPengaduanSelesai($layanan)); + } catch (\Exception $e) { + Log::error('[Layanan] Email selesai gagal: ' . $e->getMessage()); + } + } + } +} diff --git a/.history/app/Http/Controllers/LayananController_20260625014727.php b/.history/app/Http/Controllers/LayananController_20260625014727.php new file mode 100644 index 0000000..9f85beb --- /dev/null +++ b/.history/app/Http/Controllers/LayananController_20260625014727.php @@ -0,0 +1,232 @@ +getMessage()); + } + } + + // ============================================================ + // INDEX — RT & Admin + // ============================================================ + public function index() + { + $user = Auth::user(); + + if ($user->role == 'admin') { + // Admin hanya lihat (tidak ada approve lagi, hanya view) + $layanan = Layanan::with('penghuni') + ->latest() + ->get(); + } else { + // RT lihat pengaduan penghuni di RT-nya + $rtId = $user->id; + $layanan = Layanan::with('penghuni') + ->whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + }) + ->latest() + ->get(); + } + + return view('admin.layanan.index', compact('layanan')); + } + + // ============================================================ + // STORE — dari admin panel (jika ada) + // ============================================================ + public function store(Request $request) + { + Layanan::create([ + 'penghuni_id' => $request->penghuni_id, + 'tanggal_pengaduan' => now(), + 'kategori_masalah' => $request->kategori_masalah, + 'deskripsi' => $request->deskripsi, + 'status' => 'diajukan' + ]); + + return back()->with('success', 'Pengaduan berhasil ditambahkan'); + } + + // ============================================================ + // TANGGAPI RT — RT memberi tanggapan awal (status: diproses) + // ============================================================ + public function tanggapiRT(Request $request, $id) + { + $request->validate([ + 'tanggapan_admin' => 'required|string', + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->tanggapan_admin = $request->tanggapan_admin; + $layanan->status = 'diproses'; + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Tanggapan berhasil dikirim ke penghuni.'); + } + + // ============================================================ + // KONFIRMASI SELESAI — RT konfirmasi selesai + foto bukti + // ============================================================ + public function konfirmasiSelesai(Request $request, $id) + { + $request->validate([ + 'catatan_selesai' => 'required|string', + 'foto_bukti_rt' => 'nullable|image|mimes:jpg,jpeg,png|max:3072', + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + + // Simpan catatan selesai + $layanan->catatan_selesai = $request->catatan_selesai; + $layanan->status = 'selesai'; + + // Upload foto bukti RT jika ada + if ($request->hasFile('foto_bukti_rt')) { + $path = $request->file('foto_bukti_rt')->store('bukti_rt', 'public'); + $layanan->foto_bukti_rt = $path; + } + + $layanan->save(); + + // Kirim notifikasi selesai + $this->kirimNotifSelesai($layanan); + + return back()->with('success', 'Pengaduan dikonfirmasi selesai & notifikasi terkirim.'); + } + + // ============================================================ + // DESTROY + // ============================================================ + public function destroy($id) + { + Layanan::findOrFail($id)->delete(); + return back()->with('success', 'Data berhasil dihapus'); + } + + // ============================================================ + // INDEX ADMIN (view only) + // ============================================================ + public function indexAdmin() + { + $layanan = Layanan::with('penghuni')->latest()->get(); + return view('admin.layanan.index', compact('layanan')); + } + + // ============================================================ + // PRIVATE: Notif tanggapan awal (diproses) + // ============================================================ + private function kirimNotif($layanan) + { + if (!$layanan->penghuni) return; + + $nama = $layanan->penghuni->nama; + $tanggapan = $layanan->tanggapan_admin ?? '-'; + $tanggal = now()->format('d-m-Y H:i'); + + // WhatsApp + if (!empty($layanan->penghuni->telepon)) { + $pesan = "🏡 *GREEN VIEW RESIDENCE*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "📢 *NOTIFIKASI PENGADUAN*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n\n"; + $pesan .= "Halo *{$nama}* 👋\n\n"; + $pesan .= "Pengaduan Anda sedang *DIPROSES* oleh RT.\n\n"; + $pesan .= "📌 *TANGGAPAN RT*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "{$tanggapan}\n\n"; + $pesan .= "📅 Tanggal: {$tanggal}\n"; + $pesan .= "📲 Cek detail: " . url('/') . "\n\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "🙏 Terima kasih atas kepercayaan Anda\n"; + $pesan .= "🏡 *Green View Residence*"; + + $terkirim = WhatsappService::send($layanan->penghuni->telepon, $pesan); + if (!$terkirim) { + Log::warning('[Layanan] WA gagal ke: ' . $layanan->penghuni->telepon); + } + } + + // Email + if (!empty($layanan->penghuni->email)) { + try { + Mail::to($layanan->penghuni->email)->send(new NotifPengaduan($layanan)); + } catch (\Exception $e) { + Log::error('[Layanan] Email gagal: ' . $e->getMessage()); + } + } + } + + // ============================================================ + // PRIVATE: Notif selesai (RT konfirmasi selesai) + // ============================================================ + private function kirimNotifSelesai($layanan) + { + if (!$layanan->penghuni) return; + + $nama = $layanan->penghuni->nama; + $catatan = $layanan->catatan_selesai ?? '-'; + $tanggal = now()->format('d-m-Y H:i'); + + // WhatsApp + if (!empty($layanan->penghuni->telepon)) { + $pesan = "🏡 *GREEN VIEW RESIDENCE*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "✅ *PENGADUAN SELESAI*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n\n"; + $pesan .= "Halo *{$nama}* 👋\n\n"; + $pesan .= "Pengaduan Anda telah *SELESAI* ditangani oleh RT.\n\n"; + $pesan .= "📋 *KETERANGAN PENYELESAIAN*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "{$catatan}\n\n"; + $pesan .= "📅 Tanggal Selesai: {$tanggal}\n"; + $pesan .= "📲 Lihat bukti: " . url('/') . "\n\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "🙏 Terima kasih telah menggunakan layanan kami\n"; + $pesan .= "🏡 *Green View Residence*"; + + $terkirim = WhatsappService::send($layanan->penghuni->telepon, $pesan); + if (!$terkirim) { + Log::warning('[Layanan] WA selesai gagal ke: ' . $layanan->penghuni->telepon); + } + } + + // Email + if (!empty($layanan->penghuni->email)) { + try { + Mail::to($layanan->penghuni->email)->send(new \App\Mail\NotifPengaduanSelesai($layanan)); + } catch (\Exception $e) { + Log::error('[Layanan] Email selesai gagal: ' . $e->getMessage()); + } + } + } +} diff --git a/.history/app/Http/Controllers/LayananController_20260625014952.php b/.history/app/Http/Controllers/LayananController_20260625014952.php new file mode 100644 index 0000000..0b4b314 --- /dev/null +++ b/.history/app/Http/Controllers/LayananController_20260625014952.php @@ -0,0 +1,233 @@ +getMessage()); + } + } + + // ============================================================ + // INDEX — RT & Admin + // ============================================================ + public function index() + { + $user = Auth::user(); + + if ($user->role == 'admin') { + // Admin hanya lihat (tidak ada approve lagi, hanya view) + $layanan = Layanan::with('penghuni') + ->latest() + ->get(); + } else { + // RT lihat pengaduan penghuni di RT-nya + $rtId = $user->id; + $layanan = Layanan::with('penghuni') + ->whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + }) + ->latest() + ->get(); + } + + return view('admin.layanan.index', compact('layanan')); + } + + // ============================================================ + // STORE — dari admin panel (jika ada) + // ============================================================ + public function store(Request $request) + { + Layanan::create([ + 'penghuni_id' => $request->penghuni_id, + 'tanggal_pengaduan' => now(), + 'kategori_masalah' => $request->kategori_masalah, + 'deskripsi' => $request->deskripsi, + 'status' => 'diajukan' + ]); + + return back()->with('success', 'Pengaduan berhasil ditambahkan'); + } + + // ============================================================ + // TANGGAPI RT — RT memberi tanggapan awal (status: diproses) + // ============================================================ + public function tanggapiRT(Request $request, $id) + { + $request->validate([ + 'tanggapan_admin' => 'required|string', + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->tanggapan_admin = $request->tanggapan_admin; + $layanan->status = 'diproses'; + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Tanggapan berhasil dikirim ke penghuni.'); + } + + // ============================================================ + // KONFIRMASI SELESAI — RT konfirmasi selesai + foto bukti + // ============================================================ + public function konfirmasiSelesai(Request $request, $id) + { + $request->validate([ + 'catatan_selesai' => 'required|string', + 'foto_bukti_rt' => 'nullable|image|mimes:jpg,jpeg,png|max:3072', + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + + // Simpan catatan selesai + $layanan->catatan_selesai = $request->catatan_selesai; + $layanan->status = 'selesai'; + + // Upload foto bukti RT jika ada + if ($request->hasFile('foto_bukti_rt')) { + $path = $request->file('foto_bukti_rt')->store('bukti_rt', 'public'); + $layanan->foto_bukti_rt = $path; + } + + $layanan->save(); + + // Kirim notifikasi selesai + $this->kirimNotifSelesai($layanan); + + return back()->with('success', 'Pengaduan dikonfirmasi selesai & notifikasi terkirim.'); + } + + // ============================================================ + // DESTROY + // ============================================================ + public function destroy($id) + { + Layanan::findOrFail($id)->delete(); + return back()->with('success', 'Data berhasil dihapus'); + } + + // ============================================================ + // INDEX ADMIN (view only) + // ============================================================ + public function indexAdmin() + { + $layanan = Layanan::with('penghuni')->latest()->get(); + return view('admin.layanan.index', compact('layanan')); + } + + // ============================================================ + // PRIVATE: Notif tanggapan awal (diproses) + // ============================================================ + private function kirimNotif($layanan) + { + if (!$layanan->penghuni) return; + + $nama = $layanan->penghuni->nama; + $tanggapan = $layanan->tanggapan_admin ?? '-'; + $tanggal = now()->format('d-m-Y H:i'); + + // WhatsApp + if (!empty($layanan->penghuni->telepon)) { + $pesan = "🏡 *GREEN VIEW RESIDENCE*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "📢 *NOTIFIKASI PENGADUAN*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n\n"; + $pesan .= "Halo *{$nama}* 👋\n\n"; + $pesan .= "Pengaduan Anda sedang *DIPROSES* oleh RT.\n\n"; + $pesan .= "📌 *TANGGAPAN RT*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "{$tanggapan}\n\n"; + $pesan .= "📅 Tanggal: {$tanggal}\n"; + $pesan .= "📲 Cek detail: " . url('/') . "\n\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "🙏 Terima kasih atas kepercayaan Anda\n"; + $pesan .= "🏡 *Green View Residence*"; + + $terkirim = WhatsappService::send($layanan->penghuni->telepon, $pesan); + if (!$terkirim) { + Log::warning('[Layanan] WA gagal ke: ' . $layanan->penghuni->telepon); + } + } + + // Email + if (!empty($layanan->penghuni->email)) { + try { + Mail::to($layanan->penghuni->email)->send(new NotifPengaduan($layanan)); + } catch (\Exception $e) { + Log::error('[Layanan] Email gagal: ' . $e->getMessage()); + } + } + } + + // ============================================================ + // PRIVATE: Notif selesai (RT konfirmasi selesai) + // ============================================================ + private function kirimNotifSelesai($layanan) + { + if (!$layanan->penghuni) return; + + $nama = $layanan->penghuni->nama; + $catatan = $layanan->catatan_selesai ?? '-'; + $tanggal = now()->format('d-m-Y H:i'); + + // WhatsApp + if (!empty($layanan->penghuni->telepon)) { + $pesan = "🏡 *GREEN VIEW RESIDENCE*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "✅ *PENGADUAN SELESAI*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n\n"; + $pesan .= "Halo *{$nama}* 👋\n\n"; + $pesan .= "Pengaduan Anda telah *SELESAI* ditangani oleh RT.\n\n"; + $pesan .= "📋 *KETERANGAN PENYELESAIAN*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "{$catatan}\n\n"; + $pesan .= "📅 Tanggal Selesai: {$tanggal}\n"; + $pesan .= "📲 Lihat bukti: " . url('/') . "\n\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "🙏 Terima kasih telah menggunakan layanan kami\n"; + $pesan .= "🏡 *Green View Residence*"; + + $terkirim = WhatsappService::send($layanan->penghuni->telepon, $pesan); + if (!$terkirim) { + Log::warning('[Layanan] WA selesai gagal ke: ' . $layanan->penghuni->telepon); + } + } + + // Email + if (!empty($layanan->penghuni->email)) { + try { + Mail::to($layanan->penghuni->email)->send(new \App\Mail\NotifPengaduanSelesai($layanan)); + } catch (\Exception $e) { + Log::error('[Layanan] Email selesai gagal: ' . $e->getMessage()); + } + } + } +} diff --git a/.history/app/Http/Controllers/LayananController_20260625014958.php b/.history/app/Http/Controllers/LayananController_20260625014958.php new file mode 100644 index 0000000..bab7116 --- /dev/null +++ b/.history/app/Http/Controllers/LayananController_20260625014958.php @@ -0,0 +1,233 @@ +getMessage()); + } + } + + // ============================================================ + // INDEX — RT & Admin + // ============================================================ + public function index() + { + $user = Auth::user(); + + if ($user->role == 'admin') { + // Admin hanya lihat (tidak ada approve lagi, hanya view) + $layanan = Layanan::with('penghuni') + ->latest() + ->get(); + } else { + // RT lihat pengaduan penghuni di RT-nya + $rtId = $user->id; + $layanan = Layanan::with('penghuni') + ->whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + }) + ->latest() + ->get(); + } + + return view('admin.layanan.index', compact('layanan')); + } + + // ============================================================ + // STORE — dari admin panel (jika ada) + // ============================================================ + public function store(Request $request) + { + Layanan::create([ + 'penghuni_id' => $request->penghuni_id, + 'tanggal_pengaduan' => now(), + 'kategori_masalah' => $request->kategori_masalah, + 'deskripsi' => $request->deskripsi, + 'status' => 'diajukan' + ]); + + return back()->with('success', 'Pengaduan berhasil ditambahkan'); + } + + // ============================================================ + // TANGGAPI RT — RT memberi tanggapan awal (status: diproses) + // ============================================================ + public function tanggapiRT(Request $request, $id) + { + $request->validate([ + 'tanggapan_admin' => 'required|string', + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->tanggapan_admin = $request->tanggapan_admin; + $layanan->status = 'diproses'; + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Tanggapan berhasil dikirim ke penghuni.'); + } + + // ============================================================ + // KONFIRMASI SELESAI — RT konfirmasi selesai + foto bukti + // ============================================================ + public function konfirmasiSelesai(Request $request, $id) + { + $request->validate([ + 'catatan_selesai' => 'required|string', + 'foto_bukti_rt' => 'nullable|image|mimes:jpg,jpeg,png|max:3072', + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + + // Simpan catatan selesai + $layanan->catatan_selesai = $request->catatan_selesai; + $layanan->status = 'selesai'; + + // Upload foto bukti RT jika ada + if ($request->hasFile('foto_bukti_rt')) { + $path = $request->file('foto_bukti_rt')->store('bukti_rt', 'public'); + $layanan->foto_bukti_rt = $path; + } + + $layanan->save(); + + // Kirim notifikasi selesai + $this->kirimNotifSelesai($layanan); + + return back()->with('success', 'Pengaduan dikonfirmasi selesai & notifikasi terkirim.'); + } + + // ============================================================ + // DESTROY + // ============================================================ + public function destroy($id) + { + Layanan::findOrFail($id)->delete(); + return back()->with('success', 'Data berhasil dihapus'); + } + + // ============================================================ + // INDEX ADMIN (view only) + // ============================================================ + public function indexAdmin() + { + $layanan = Layanan::with('penghuni')->latest()->get(); + return view('admin.layanan.index', compact('layanan')); + } + + // ============================================================ + // PRIVATE: Notif tanggapan awal (diproses) + // ============================================================ + private function kirimNotif($layanan) + { + if (!$layanan->penghuni) return; + + $nama = $layanan->penghuni->nama; + $tanggapan = $layanan->tanggapan_admin ?? '-'; + $tanggal = now()->format('d-m-Y H:i'); + + // WhatsApp + if (!empty($layanan->penghuni->telepon)) { + $pesan = "🏡 *GREEN VIEW RESIDENCE*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "📢 *NOTIFIKASI PENGADUAN*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n\n"; + $pesan .= "Halo *{$nama}* 👋\n\n"; + $pesan .= "Pengaduan Anda sedang *DIPROSES* oleh RT.\n\n"; + $pesan .= "📌 *TANGGAPAN RT*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "{$tanggapan}\n\n"; + $pesan .= "📅 Tanggal: {$tanggal}\n"; + $pesan .= "📲 Cek detail: " . url('/') . "\n\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "🙏 Terima kasih atas kepercayaan Anda\n"; + $pesan .= "🏡 *Green View Residence*"; + + $terkirim = WhatsappService::send($layanan->penghuni->telepon, $pesan); + if (!$terkirim) { + Log::warning('[Layanan] WA gagal ke: ' . $layanan->penghuni->telepon); + } + } + + // Email + if (!empty($layanan->penghuni->email)) { + try { + Mail::to($layanan->penghuni->email)->send(new NotifPengaduan($layanan)); + } catch (\Exception $e) { + Log::error('[Layanan] Email gagal: ' . $e->getMessage()); + } + } + } + + // ============================================================ + // PRIVATE: Notif selesai (RT konfirmasi selesai) + // ============================================================ + private function kirimNotifSelesai($layanan) + { + if (!$layanan->penghuni) return; + + $nama = $layanan->penghuni->nama; + $catatan = $layanan->catatan_selesai ?? '-'; + $tanggal = now()->format('d-m-Y H:i'); + + // WhatsApp + if (!empty($layanan->penghuni->telepon)) { + $pesan = "🏡 *GREEN VIEW RESIDENCE*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "✅ *PENGADUAN SELESAI*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n\n"; + $pesan .= "Halo *{$nama}* 👋\n\n"; + $pesan .= "Pengaduan Anda telah *SELESAI* ditangani oleh RT.\n\n"; + $pesan .= "📋 *KETERANGAN PENYELESAIAN*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "{$catatan}\n\n"; + $pesan .= "📅 Tanggal Selesai: {$tanggal}\n"; + $pesan .= "📲 Lihat bukti: " . url('/') . "\n\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "🙏 Terima kasih telah menggunakan layanan kami\n"; + $pesan .= "🏡 *Green View Residence*"; + + $terkirim = WhatsappService::send($layanan->penghuni->telepon, $pesan); + if (!$terkirim) { + Log::warning('[Layanan] WA selesai gagal ke: ' . $layanan->penghuni->telepon); + } + } + + // Email + if (!empty($layanan->penghuni->email)) { + try { + Mail::to($layanan->penghuni->email)->send(new \App\Mail\NotifPengaduanSelesai($layanan)); + } catch (\Exception $e) { + Log::error('[Layanan] Email selesai gagal: ' . $e->getMessage()); + } + } + } +} diff --git a/.history/app/Http/Controllers/LayananController_20260625015033.php b/.history/app/Http/Controllers/LayananController_20260625015033.php new file mode 100644 index 0000000..c6ac14d --- /dev/null +++ b/.history/app/Http/Controllers/LayananController_20260625015033.php @@ -0,0 +1,233 @@ +getMessage()); + } + } + + // ============================================================ + // INDEX — RT & Admin + // ============================================================ + public function index() + { + $user = Auth::user(); + + if ($user->role == 'admin') { + // Admin hanya lihat (tidak ada approve lagi, hanya view) + $layanan = Layanan::with('penghuni') + ->latest() + ->get(); + } else { + // RT lihat pengaduan penghuni di RT-nya + $rtId = $user->id; + $layanan = Layanan::with('penghuni') + ->whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + }) + ->latest() + ->get(); + } + + return view('admin.layanan.index', compact('layanan')); + } + + // ============================================================ + // STORE — dari admin panel (jika ada) + // ============================================================ + public function store(Request $request) + { + Layanan::create([ + 'penghuni_id' => $request->penghuni_id, + 'tanggal_pengaduan' => now(), + 'kategori_masalah' => $request->kategori_masalah, + 'deskripsi' => $request->deskripsi, + 'status' => 'diajukan' + ]); + + return back()->with('success', 'Pengaduan berhasil ditambahkan'); + } + + // ============================================================ + // TANGGAPI RT — RT memberi tanggapan awal (status: diproses) + // ============================================================ + public function tanggapiRT(Request $request, $id) + { + $request->validate([ + 'tanggapan_admin' => 'required|string', + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->tanggapan_admin = $request->tanggapan_admin; + $layanan->status = 'diproses'; + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Tanggapan berhasil dikirim ke penghuni.'); + } + + // ============================================================ + // KONFIRMASI SELESAI — RT konfirmasi selesai + foto bukti + // ============================================================ + public function konfirmasiSelesai(Request $request, $id) + { + $request->validate([ + 'catatan_selesai' => 'required|string', + 'foto_bukti_rt' => 'nullable|image|mimes:jpg,jpeg,png|max:3072', + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + + // Simpan catatan selesai + $layanan->catatan_selesai = $request->catatan_selesai; + $layanan->status = 'selesai'; + + // Upload foto bukti RT jika ada + if ($request->hasFile('foto_bukti_rt')) { + $path = $request->file('foto_bukti_rt')->store('bukti_rt', 'public'); + $layanan->foto_bukti_rt = $path; + } + + $layanan->save(); + + // Kirim notifikasi selesai + $this->kirimNotifSelesai($layanan); + + return back()->with('success', 'Pengaduan dikonfirmasi selesai & notifikasi terkirim.'); + } + + // ============================================================ + // DESTROY + // ============================================================ + public function destroy($id) + { + Layanan::findOrFail($id)->delete(); + return back()->with('success', 'Data berhasil dihapus'); + } + + // ============================================================ + // INDEX ADMIN (view only) + // ============================================================ + public function indexAdmin() + { + $layanan = Layanan::with('penghuni')->latest()->get(); + return view('admin.layanan.index', compact('layanan')); + } + + // ============================================================ + // PRIVATE: Notif tanggapan awal (diproses) + // ============================================================ + private function kirimNotif($layanan) + { + if (!$layanan->penghuni) return; + + $nama = $layanan->penghuni->nama; + $tanggapan = $layanan->tanggapan_admin ?? '-'; + $tanggal = now()->format('d-m-Y H:i'); + + // WhatsApp + if (!empty($layanan->penghuni->telepon)) { + $pesan = "🏡 *GREEN VIEW RESIDENCE*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "📢 *NOTIFIKASI PENGADUAN*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n\n"; + $pesan .= "Halo *{$nama}* 👋\n\n"; + $pesan .= "Pengaduan Anda sedang *DIPROSES* oleh RT.\n\n"; + $pesan .= "📌 *TANGGAPAN RT*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "{$tanggapan}\n\n"; + $pesan .= "📅 Tanggal: {$tanggal}\n"; + $pesan .= "📲 Cek detail: " . url('/') . "\n\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "🙏 Terima kasih atas kepercayaan Anda\n"; + $pesan .= "🏡 *Green View Residence*"; + + $terkirim = WhatsappService::send($layanan->penghuni->telepon, $pesan); + if (!$terkirim) { + Log::warning('[Layanan] WA gagal ke: ' . $layanan->penghuni->telepon); + } + } + + // Email + if (!empty($layanan->penghuni->email)) { + try { + Mail::to($layanan->penghuni->email)->send(new NotifPengaduan($layanan)); + } catch (\Exception $e) { + Log::error('[Layanan] Email gagal: ' . $e->getMessage()); + } + } + } + + // ============================================================ + // PRIVATE: Notif selesai (RT konfirmasi selesai) + // ============================================================ + private function kirimNotifSelesai($layanan) + { + if (!$layanan->penghuni) return; + + $nama = $layanan->penghuni->nama; + $catatan = $layanan->catatan_selesai ?? '-'; + $tanggal = now()->format('d-m-Y H:i'); + + // WhatsApp + if (!empty($layanan->penghuni->telepon)) { + $pesan = "🏡 *GREEN VIEW RESIDENCE*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "✅ *PENGADUAN SELESAI*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n\n"; + $pesan .= "Halo *{$nama}* 👋\n\n"; + $pesan .= "Pengaduan Anda telah *SELESAI* ditangani oleh RT.\n\n"; + $pesan .= "📋 *KETERANGAN PENYELESAIAN*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "{$catatan}\n\n"; + $pesan .= "📅 Tanggal Selesai: {$tanggal}\n"; + $pesan .= "📲 Lihat bukti: " . url('/') . "\n\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "🙏 Terima kasih telah menggunakan layanan kami\n"; + $pesan .= "🏡 *Green View Residence*"; + + $terkirim = WhatsappService::send($layanan->penghuni->telepon, $pesan); + if (!$terkirim) { + Log::warning('[Layanan] WA selesai gagal ke: ' . $layanan->penghuni->telepon); + } + } + + // Email + if (!empty($layanan->penghuni->email)) { + try { + Mail::to($layanan->penghuni->email)->send(new NotifPengaduanSelesai($layanan)); + } catch (\Exception $e) { + Log::error('[Layanan] Email selesai gagal: ' . $e->getMessage()); + } + } + } +} diff --git a/.history/app/Http/Controllers/LayananController_20260625022400.php b/.history/app/Http/Controllers/LayananController_20260625022400.php new file mode 100644 index 0000000..a3eb56a --- /dev/null +++ b/.history/app/Http/Controllers/LayananController_20260625022400.php @@ -0,0 +1,233 @@ +getMessage()); + } + } + + // ============================================================ + // INDEX — RT & Admin + // ============================================================ + public function index() + { + $user = Auth::user(); + + if ($user->role == 'admin') { + // Admin hanya lihat (tidak ada approve lagi, hanya view) + $layanan = Layanan::with('penghuni') + ->latest() + ->get(); + } else { + // RT lihat pengaduan penghuni di RT-nya + $rtId = $user->id; + $layanan = Layanan::with('penghuni') + ->whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + }) + ->latest() + ->get(); + } + + return view('admin.layanan.index', compact('layanan')); + } + + // ============================================================ + // STORE — dari admin panel (jika ada) + // ============================================================ + public function store(Request $request) + { + Layanan::create([ + 'penghuni_id' => $request->penghuni_id, + 'tanggal_pengaduan' => now(), + 'kategori_masalah' => $request->kategori_masalah, + 'deskripsi' => $request->deskripsi, + 'status' => 'diajukan' + ]); + + return back()->with('success', 'Pengaduan berhasil ditambahkan'); + } + + // ============================================================ + // TANGGAPI RT — RT memberi tanggapan awal (status: diproses) + // ============================================================ + public function tanggapiRT(Request $request, $id) + { + $request->validate([ + 'tanggapan_admin' => 'required|string', + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + $layanan->tanggapan_admin = $request->tanggapan_admin; + $layanan->status = 'diproses'; + $layanan->save(); + + $this->kirimNotif($layanan); + + return back()->with('success', 'Tanggapan berhasil dikirim ke penghuni.'); + } + + // ============================================================ + // KONFIRMASI SELESAI — RT konfirmasi selesai + foto bukti + // ============================================================ + public function konfirmasiSelesai(Request $request, $id) + { + $request->validate([ + 'catatan_selesai' => 'required|string', + 'foto_bukti_rt' => 'nullable|image|mimes:jpg,jpeg,png|max:3072', + ]); + + $layanan = Layanan::with('penghuni')->findOrFail($id); + + // Simpan catatan selesai + $layanan->catatan_selesai = $request->catatan_selesai; + $layanan->status = 'selesai'; + + // Upload foto bukti RT jika ada + if ($request->hasFile('foto_bukti_rt')) { + $path = $request->file('foto_bukti_rt')->store('bukti_rt', 'public'); + $layanan->foto_bukti_rt = $path; + } + + $layanan->save(); + + // Kirim notifikasi selesai + $this->kirimNotifSelesai($layanan); + + return back()->with('success', 'Pengaduan dikonfirmasi selesai & notifikasi terkirim.'); + } + + // ============================================================ + // DESTROY + // ============================================================ + public function destroy($id) + { + Layanan::findOrFail($id)->delete(); + return back()->with('success', 'Data berhasil dihapus'); + } + + // ============================================================ + // INDEX ADMIN (view only) + // ============================================================ + public function indexAdmin() + { + $layanan = Layanan::with('penghuni')->latest()->get(); + return view('admin.layanan.index', compact('layanan')); + } + + // ============================================================ + // PRIVATE: Notif tanggapan awal (diproses) + // ============================================================ + private function kirimNotif($layanan) + { + if (!$layanan->penghuni) return; + + $nama = $layanan->penghuni->nama; + $tanggapan = $layanan->tanggapan_admin ?? '-'; + $tanggal = now()->format('d-m-Y H:i'); + + // WhatsApp + if (!empty($layanan->penghuni->telepon)) { + $pesan = "🏡 *GREEN VIEW RESIDENCE*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "📢 *NOTIFIKASI PENGADUAN*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n\n"; + $pesan .= "Halo *{$nama}* 👋\n\n"; + $pesan .= "Pengaduan Anda sedang *DIPROSES* oleh RT.\n\n"; + $pesan .= "📌 *TANGGAPAN RT*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "{$tanggapan}\n\n"; + $pesan .= "📅 Tanggal: {$tanggal}\n"; + $pesan .= "📲 Cek detail: " . url('/') . "\n\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "🙏 Terima kasih atas kepercayaan Anda\n"; + $pesan .= "🏡 *Green View Residence*"; + + $terkirim = WhatsappService::send($layanan->penghuni->telepon, $pesan); + if (!$terkirim) { + Log::warning('[Layanan] WA gagal ke: ' . $layanan->penghuni->telepon); + } + } + + // Email + if (!empty($layanan->penghuni->email)) { + try { + Mail::to($layanan->penghuni->email)->send(new NotifPengaduan($layanan)); + } catch (\Exception $e) { + Log::error('[Layanan] Email gagal: ' . $e->getMessage()); + } + } + } + + // ============================================================ + // PRIVATE: Notif selesai (RT konfirmasi selesai) + // ============================================================ + private function kirimNotifSelesai($layanan) + { + if (!$layanan->penghuni) return; + + $nama = $layanan->penghuni->nama; + $catatan = $layanan->catatan_selesai ?? '-'; + $tanggal = now()->format('d-m-Y H:i'); + + // WhatsApp + if (!empty($layanan->penghuni->telepon)) { + $pesan = "🏡 *GREEN VIEW RESIDENCE*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "✅ *PENGADUAN SELESAI*\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n\n"; + $pesan .= "Halo *{$nama}* 👋\n\n"; + $pesan .= "Pengaduan Anda telah *SELESAI* ditangani oleh RT.\n\n"; + $pesan .= "📋 *KETERANGAN PENYELESAIAN*\n"; + $pesan .= "──────────────────────\n"; + $pesan .= "{$catatan}\n\n"; + $pesan .= "📅 Tanggal Selesai: {$tanggal}\n"; + $pesan .= "📲 Lihat bukti: " . url('/') . "\n\n"; + $pesan .= "━━━━━━━━━━━━━━━━━━━━━━\n"; + $pesan .= "🙏 Terima kasih telah menggunakan layanan kami\n"; + $pesan .= "🏡 *Green View Residence*"; + + $terkirim = WhatsappService::send($layanan->penghuni->telepon, $pesan); + if (!$terkirim) { + Log::warning('[Layanan] WA selesai gagal ke: ' . $layanan->penghuni->telepon); + } + } + + // Email + if (!empty($layanan->penghuni->email)) { + try { + Mail::to($layanan->penghuni->email)->send(new NotifPengaduan($layanan, 'selesai')); + } catch (\Exception $e) { + Log::error('[Layanan] Email selesai gagal: ' . $e->getMessage()); + } + } + } +} diff --git a/.history/app/Http/Controllers/PenghuniController_20260604090538.php b/.history/app/Http/Controllers/PenghuniController_20260604090538.php new file mode 100644 index 0000000..94dbd64 --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260604090538.php @@ -0,0 +1,508 @@ +has('blok')) { + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, // RT 1 + 'B' => 13, // RT 1 (gabung A+B kalau 1 blok = 10 rumah) + 'C' => 13, // RT 2 + 'D' => 13, // RT 2 + 'E' => 13, // RT 3 + 'F' => 13, + // RT 3 + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260604090540.php b/.history/app/Http/Controllers/PenghuniController_20260604090540.php new file mode 100644 index 0000000..ccf55f2 --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260604090540.php @@ -0,0 +1,507 @@ +has('blok')) { + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, // RT 1 + 'B' => 13, // RT 1 (gabung A+B kalau 1 blok = 10 rumah) + 'C' => 13, // RT 2 + 'D' => 13, // RT 2 + 'E' => 13, // RT 3 + 'F' => 13, // RT 3 + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260604090543.php b/.history/app/Http/Controllers/PenghuniController_20260604090543.php new file mode 100644 index 0000000..1af68cb --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260604090543.php @@ -0,0 +1,508 @@ +has('blok')) { + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, // RT 1 + 'B' => 13, // RT 1 (gabung A+B kalau 1 blok = 10 rumah) + 'C' => 13, // RT 2 + 'D' => 13, // RT 2 + 'E' => 13, // RT 3 + 'F' => 13, // RT 3 + 'F' => 13, + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260604090547.php b/.history/app/Http/Controllers/PenghuniController_20260604090547.php new file mode 100644 index 0000000..94de309 --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260604090547.php @@ -0,0 +1,508 @@ +has('blok')) { + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, // RT 1 + 'B' => 13, // RT 1 (gabung A+B kalau 1 blok = 10 rumah) + 'C' => 13, // RT 2 + 'D' => 13, // RT 2 + 'E' => 13, // RT 3 + 'F' => 13, // RT 3 + '' => 13, + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260604090549.php b/.history/app/Http/Controllers/PenghuniController_20260604090549.php new file mode 100644 index 0000000..459d320 --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260604090549.php @@ -0,0 +1,509 @@ +has('blok')) { + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, // RT 1 + 'B' => 13, // RT 1 (gabung A+B kalau 1 blok = 10 rumah) + 'C' => 13, // RT 2 + 'D' => 13, // RT 2 + 'E' => 13, // RT 3 + 'F' => 13, // RT 3 + 'G' => 13, // RT 4 + 'H' => 13, // RT 4 + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260604090552.php b/.history/app/Http/Controllers/PenghuniController_20260604090552.php new file mode 100644 index 0000000..45ad71b --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260604090552.php @@ -0,0 +1,510 @@ +has('blok')) { + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, // RT 1 + 'B' => 13, // RT 1 (gabung A+B kalau 1 blok = 10 rumah) + 'C' => 13, // RT 2 + 'D' => 13, // RT 2 + 'E' => 13, // RT 3 + 'F' => 13, // RT 3 + 'G' => 13, // RT 4 + 'H' => 13, // RT 4 + 'F' => 13, + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260604090557.php b/.history/app/Http/Controllers/PenghuniController_20260604090557.php new file mode 100644 index 0000000..e8dfb36 --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260604090557.php @@ -0,0 +1,510 @@ +has('blok')) { + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, // RT 1 + 'B' => 13, // RT 1 (gabung A+B kalau 1 blok = 10 rumah) + 'C' => 13, // RT 2 + 'D' => 13, // RT 2 + 'E' => 13, // RT 3 + 'F' => 13, // RT 3 + 'G' => 13, // RT 4 + 'H' => 13, // RT 4 + 'I' => 13, + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260604090600.php b/.history/app/Http/Controllers/PenghuniController_20260604090600.php new file mode 100644 index 0000000..27144b0 --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260604090600.php @@ -0,0 +1,511 @@ +has('blok')) { + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, // RT 1 + 'B' => 13, // RT 1 (gabung A+B kalau 1 blok = 10 rumah) + 'C' => 13, // RT 2 + 'D' => 13, // RT 2 + 'E' => 13, // RT 3 + 'F' => 13, // RT 3 + 'G' => 13, // RT 4 + 'H' => 13, // RT 4 + 'I' => 13, + + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260604090603.php b/.history/app/Http/Controllers/PenghuniController_20260604090603.php new file mode 100644 index 0000000..47f57f9 --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260604090603.php @@ -0,0 +1,512 @@ +has('blok')) { + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, // RT 1 + 'B' => 13, // RT 1 (gabung A+B kalau 1 blok = 10 rumah) + 'C' => 13, // RT 2 + 'D' => 13, // RT 2 + 'E' => 13, // RT 3 + 'F' => 13, // RT 3 + 'G' => 13, // RT 4 + 'H' => 13, // RT 4 + 'I' => 13, + 'J' => 13, + + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260604090606.php b/.history/app/Http/Controllers/PenghuniController_20260604090606.php new file mode 100644 index 0000000..b5cd0d0 --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260604090606.php @@ -0,0 +1,512 @@ +has('blok')) { + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, // RT 1 + 'B' => 13, // RT 1 (gabung A+B kalau 1 blok = 10 rumah) + 'C' => 13, // RT 2 + 'D' => 13, // RT 2 + 'E' => 13, // RT 3 + 'F' => 13, // RT 3 + 'G' => 13, // RT 4 + 'H' => 13, // RT 4 + 'I' => 13, + 'J' => 13, + K + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260604090607.php b/.history/app/Http/Controllers/PenghuniController_20260604090607.php new file mode 100644 index 0000000..840f0fe --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260604090607.php @@ -0,0 +1,512 @@ +has('blok')) { + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, // RT 1 + 'B' => 13, // RT 1 (gabung A+B kalau 1 blok = 10 rumah) + 'C' => 13, // RT 2 + 'D' => 13, // RT 2 + 'E' => 13, // RT 3 + 'F' => 13, // RT 3 + 'G' => 13, // RT 4 + 'H' => 13, // RT 4 + 'I' => 13, + 'J' => 13, + K' => 13, + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260604090611.php b/.history/app/Http/Controllers/PenghuniController_20260604090611.php new file mode 100644 index 0000000..4c6fc13 --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260604090611.php @@ -0,0 +1,511 @@ +has('blok')) { + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, // RT 1 + 'B' => 13, // RT 1 (gabung A+B kalau 1 blok = 10 rumah) + 'C' => 13, // RT 2 + 'D' => 13, // RT 2 + 'E' => 13, // RT 3 + 'F' => 13, // RT 3 + 'G' => 13, // RT 4 + 'H' => 13, // RT 4 + 'I' => 13, + 'J' => 13, + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260604090612.php b/.history/app/Http/Controllers/PenghuniController_20260604090612.php new file mode 100644 index 0000000..47f57f9 --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260604090612.php @@ -0,0 +1,512 @@ +has('blok')) { + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, // RT 1 + 'B' => 13, // RT 1 (gabung A+B kalau 1 blok = 10 rumah) + 'C' => 13, // RT 2 + 'D' => 13, // RT 2 + 'E' => 13, // RT 3 + 'F' => 13, // RT 3 + 'G' => 13, // RT 4 + 'H' => 13, // RT 4 + 'I' => 13, + 'J' => 13, + + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260604090616.php b/.history/app/Http/Controllers/PenghuniController_20260604090616.php new file mode 100644 index 0000000..76cf7c6 --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260604090616.php @@ -0,0 +1,512 @@ +has('blok')) { + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, // RT 1 + 'B' => 13, // RT 1 (gabung A+B kalau 1 blok = 10 rumah) + 'C' => 13, // RT 2 + 'D' => 13, // RT 2 + 'E' => 13, // RT 3 + 'F' => 13, // RT 3 + 'G' => 13, // RT 4 + 'H' => 13, // RT 4 + 'I' => 13, + 'J' => 13, + '' + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260604090617.php b/.history/app/Http/Controllers/PenghuniController_20260604090617.php new file mode 100644 index 0000000..9eb8e9d --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260604090617.php @@ -0,0 +1,512 @@ +has('blok')) { + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, // RT 1 + 'B' => 13, // RT 1 (gabung A+B kalau 1 blok = 10 rumah) + 'C' => 13, // RT 2 + 'D' => 13, // RT 2 + 'E' => 13, // RT 3 + 'F' => 13, // RT 3 + 'G' => 13, // RT 4 + 'H' => 13, // RT 4 + 'I' => 13, + 'J' => 13, + 'K' => 13, + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260604090619.php b/.history/app/Http/Controllers/PenghuniController_20260604090619.php new file mode 100644 index 0000000..0ad7e29 --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260604090619.php @@ -0,0 +1,513 @@ +has('blok')) { + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, // RT 1 + 'B' => 13, // RT 1 (gabung A+B kalau 1 blok = 10 rumah) + 'C' => 13, // RT 2 + 'D' => 13, // RT 2 + 'E' => 13, // RT 3 + 'F' => 13, // RT 3 + 'G' => 13, // RT 4 + 'H' => 13, // RT 4 + 'I' => 13, + 'J' => 13, + 'K' => 13, + 'L' => 13, + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260604090621.php b/.history/app/Http/Controllers/PenghuniController_20260604090621.php new file mode 100644 index 0000000..9a691b0 --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260604090621.php @@ -0,0 +1,514 @@ +has('blok')) { + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, // RT 1 + 'B' => 13, // RT 1 (gabung A+B kalau 1 blok = 10 rumah) + 'C' => 13, // RT 2 + 'D' => 13, // RT 2 + 'E' => 13, // RT 3 + 'F' => 13, // RT 3 + 'G' => 13, // RT 4 + 'H' => 13, // RT 4 + 'I' => 13, + 'J' => 13, + 'K' => 13, + 'L' => 13, + + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260604090659.php b/.history/app/Http/Controllers/PenghuniController_20260604090659.php new file mode 100644 index 0000000..eda38c1 --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260604090659.php @@ -0,0 +1,514 @@ +has('blok')) { + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, // RT 1 + 'B' => 13, // RT 1 (gabung A+B kalau 1 blok = 10 rumah) + 'C' => 13, // RT 2 + 'D' => 13, // RT 2 + 'E' => 13, // RT 3 + 'F' => 13, // RT 3 + 'G' => 13, // RT 4 + 'H' => 13, // RT 4 + 'I' => 13, + 'J' => 13, + 'K' => 13, + 'L' => 13, + '' + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260604090702.php b/.history/app/Http/Controllers/PenghuniController_20260604090702.php new file mode 100644 index 0000000..9a691b0 --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260604090702.php @@ -0,0 +1,514 @@ +has('blok')) { + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, // RT 1 + 'B' => 13, // RT 1 (gabung A+B kalau 1 blok = 10 rumah) + 'C' => 13, // RT 2 + 'D' => 13, // RT 2 + 'E' => 13, // RT 3 + 'F' => 13, // RT 3 + 'G' => 13, // RT 4 + 'H' => 13, // RT 4 + 'I' => 13, + 'J' => 13, + 'K' => 13, + 'L' => 13, + + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260604090704.php b/.history/app/Http/Controllers/PenghuniController_20260604090704.php new file mode 100644 index 0000000..0e16a77 --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260604090704.php @@ -0,0 +1,514 @@ +has('blok')) { + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, // RT 1 + 'B' => 13, // RT 1 (gabung A+B kalau 1 blok = 10 rumah) + 'C' => 13, // RT 2 + 'D' => 13, // RT 2 + 'E' => 13, // RT 3 + 'F' => 13, // RT 3 + 'G' => 13, // RT 4 + 'H' => 13, // RT 4 + 'I' => 13, + 'J' => 13, + 'K' => 13, + 'L' => 13, + 'M' => 13, + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260604090714.php b/.history/app/Http/Controllers/PenghuniController_20260604090714.php new file mode 100644 index 0000000..0ad7e29 --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260604090714.php @@ -0,0 +1,513 @@ +has('blok')) { + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, // RT 1 + 'B' => 13, // RT 1 (gabung A+B kalau 1 blok = 10 rumah) + 'C' => 13, // RT 2 + 'D' => 13, // RT 2 + 'E' => 13, // RT 3 + 'F' => 13, // RT 3 + 'G' => 13, // RT 4 + 'H' => 13, // RT 4 + 'I' => 13, + 'J' => 13, + 'K' => 13, + 'L' => 13, + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260610222045.php b/.history/app/Http/Controllers/PenghuniController_20260610222045.php new file mode 100644 index 0000000..8ffe63b --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260610222045.php @@ -0,0 +1,513 @@ +has('blok')) { + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, // RT 1 + 'B' => 13, // RT 1 k = 10 ruma(gabung A+B kalau 1 bloh) + 'C' => 13, // RT 2 + 'D' => 13, // RT 2 + 'E' => 13, // RT 3 + 'F' => 13, // RT 3 + 'G' => 13, // RT 4 + 'H' => 13, // RT 4 + 'I' => 13, + 'J' => 13, + 'K' => 13, + 'L' => 13, + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260610222048.php b/.history/app/Http/Controllers/PenghuniController_20260610222048.php new file mode 100644 index 0000000..7d946b3 --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260610222048.php @@ -0,0 +1,513 @@ +has('blok')) { + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, // RT 1 + 'B' => 13, // RT 1 + 'C' => 13, // RT 2 + 'D' => 13, // RT 2 + 'E' => 13, // RT 3 + 'F' => 13, // RT 3 + 'G' => 13, // RT 4 + 'H' => 13, // RT 4 + 'I' => 13, + 'J' => 13, + 'K' => 13, + 'L' => 13, + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260610222051.php b/.history/app/Http/Controllers/PenghuniController_20260610222051.php new file mode 100644 index 0000000..a539c8e --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260610222051.php @@ -0,0 +1,513 @@ +has('blok')) { + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, + 'B' => 13, // RT 1 + 'C' => 13, // RT 2 + 'D' => 13, // RT 2 + 'E' => 13, // RT 3 + 'F' => 13, // RT 3 + 'G' => 13, // RT 4 + 'H' => 13, // RT 4 + 'I' => 13, + 'J' => 13, + 'K' => 13, + 'L' => 13, + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260610222056.php b/.history/app/Http/Controllers/PenghuniController_20260610222056.php new file mode 100644 index 0000000..f9a9569 --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260610222056.php @@ -0,0 +1,513 @@ +has('blok')) { + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, + 'B' => 13, + 'C' => 13, // RT 2 + 'D' => 13, // RT 2 + 'E' => 13, // RT 3 + 'F' => 13, // RT 3 + 'G' => 13, // RT 4 + 'H' => 13, // RT 4 + 'I' => 13, + 'J' => 13, + 'K' => 13, + 'L' => 13, + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260610222059.php b/.history/app/Http/Controllers/PenghuniController_20260610222059.php new file mode 100644 index 0000000..c32c4df --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260610222059.php @@ -0,0 +1,513 @@ +has('blok')) { + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, + 'B' => 13, + 'C' => 13, + 'D' => 13, // RT 2 + 'E' => 13, // RT 3 + 'F' => 13, // RT 3 + 'G' => 13, // RT 4 + 'H' => 13, // RT 4 + 'I' => 13, + 'J' => 13, + 'K' => 13, + 'L' => 13, + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260610222102.php b/.history/app/Http/Controllers/PenghuniController_20260610222102.php new file mode 100644 index 0000000..232779a --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260610222102.php @@ -0,0 +1,513 @@ +has('blok')) { + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, + 'B' => 13, + 'C' => 13, + 'D' => 13, + 'E' => 13, // RT 3 + 'F' => 13, // RT 3 + 'G' => 13, // RT 4 + 'H' => 13, // RT 4 + 'I' => 13, + 'J' => 13, + 'K' => 13, + 'L' => 13, + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260610222105.php b/.history/app/Http/Controllers/PenghuniController_20260610222105.php new file mode 100644 index 0000000..b522773 --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260610222105.php @@ -0,0 +1,513 @@ +has('blok')) { + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, + 'B' => 13, + 'C' => 13, + 'D' => 13, + 'E' => 13, + 'F' => 13, // RT 3 + 'G' => 13, // RT 4 + 'H' => 13, // RT 4 + 'I' => 13, + 'J' => 13, + 'K' => 13, + 'L' => 13, + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260610222108.php b/.history/app/Http/Controllers/PenghuniController_20260610222108.php new file mode 100644 index 0000000..cd87e10 --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260610222108.php @@ -0,0 +1,513 @@ +has('blok')) { + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, + 'B' => 13, + 'C' => 13, + 'D' => 13, + 'E' => 13, + 'F' => 13, + 'G' => 13, // RT 4 + 'H' => 13, // RT 4 + 'I' => 13, + 'J' => 13, + 'K' => 13, + 'L' => 13, + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260610222110.php b/.history/app/Http/Controllers/PenghuniController_20260610222110.php new file mode 100644 index 0000000..b522773 --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260610222110.php @@ -0,0 +1,513 @@ +has('blok')) { + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, + 'B' => 13, + 'C' => 13, + 'D' => 13, + 'E' => 13, + 'F' => 13, // RT 3 + 'G' => 13, // RT 4 + 'H' => 13, // RT 4 + 'I' => 13, + 'J' => 13, + 'K' => 13, + 'L' => 13, + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260610222113.php b/.history/app/Http/Controllers/PenghuniController_20260610222113.php new file mode 100644 index 0000000..157b7e8 --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260610222113.php @@ -0,0 +1,513 @@ +has('blok')) { + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, + 'B' => 13, + 'C' => 13, + 'D' => 13, + 'E' => 13, + 'F' => 13, + 'G' => 13, // RT 4 + 'H' => 13, // RT 4 + 'I' => 13, + 'J' => 13, + 'K' => 13, + 'L' => 13, + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260610222117.php b/.history/app/Http/Controllers/PenghuniController_20260610222117.php new file mode 100644 index 0000000..eb10686 --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260610222117.php @@ -0,0 +1,513 @@ +has('blok')) { + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, + 'B' => 13, + 'C' => 13, + 'D' => 13, + 'E' => 13, + 'F' => 13, + 'G' => 13, + 'H' => 13, // RT 4 + 'I' => 13, + 'J' => 13, + 'K' => 13, + 'L' => 13, + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260610222119.php b/.history/app/Http/Controllers/PenghuniController_20260610222119.php new file mode 100644 index 0000000..715f33a --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260610222119.php @@ -0,0 +1,513 @@ +has('blok')) { + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, + 'B' => 13, + 'C' => 13, + 'D' => 13, + 'E' => 13, + 'F' => 13, + 'G' => 13, + 'H' => 13, // RT 4 + 'I' => 13, + 'J' => 13, + 'K' => 13, + 'L' => 13, + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260610222120.php b/.history/app/Http/Controllers/PenghuniController_20260610222120.php new file mode 100644 index 0000000..eb10686 --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260610222120.php @@ -0,0 +1,513 @@ +has('blok')) { + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, + 'B' => 13, + 'C' => 13, + 'D' => 13, + 'E' => 13, + 'F' => 13, + 'G' => 13, + 'H' => 13, // RT 4 + 'I' => 13, + 'J' => 13, + 'K' => 13, + 'L' => 13, + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260610222123.php b/.history/app/Http/Controllers/PenghuniController_20260610222123.php new file mode 100644 index 0000000..3c971df --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260610222123.php @@ -0,0 +1,513 @@ +has('blok')) { + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, + 'B' => 13, + 'C' => 13, + 'D' => 13, + 'E' => 13, + 'F' => 13, + 'G' => 13, + 'H' => 13, + 'I' => 13, + 'J' => 13, + 'K' => 13, + 'L' => 13, + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260614183436.php b/.history/app/Http/Controllers/PenghuniController_20260614183436.php new file mode 100644 index 0000000..238ebf9 --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260614183436.php @@ -0,0 +1,517 @@ +has('blok')) { + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => [ + 'required', + \Illuminate\Validation\Rule::unique('rumah')->where(function ($query) use ($request) { + return $query->where('blok', $request->blok); + }), + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, + 'B' => 13, + 'C' => 13, + 'D' => 13, + 'E' => 13, + 'F' => 13, + 'G' => 13, + 'H' => 13, + 'I' => 13, + 'J' => 13, + 'K' => 13, + 'L' => 13, + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260614183442.php b/.history/app/Http/Controllers/PenghuniController_20260614183442.php new file mode 100644 index 0000000..344e2e9 --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260614183442.php @@ -0,0 +1,517 @@ +has('blok')) { + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => [ + 'required', + \Illuminate\Validation\Rule::unique('rumah')->where(function ($query) use ($request) { + return $query->where('blok', $request->blok); + }) + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, + 'B' => 13, + 'C' => 13, + 'D' => 13, + 'E' => 13, + 'F' => 13, + 'G' => 13, + 'H' => 13, + 'I' => 13, + 'J' => 13, + 'K' => 13, + 'L' => 13, + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260614183444.php b/.history/app/Http/Controllers/PenghuniController_20260614183444.php new file mode 100644 index 0000000..238ebf9 --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260614183444.php @@ -0,0 +1,517 @@ +has('blok')) { + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => [ + 'required', + \Illuminate\Validation\Rule::unique('rumah')->where(function ($query) use ($request) { + return $query->where('blok', $request->blok); + }), + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, + 'B' => 13, + 'C' => 13, + 'D' => 13, + 'E' => 13, + 'F' => 13, + 'G' => 13, + 'H' => 13, + 'I' => 13, + 'J' => 13, + 'K' => 13, + 'L' => 13, + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260614183449.php b/.history/app/Http/Controllers/PenghuniController_20260614183449.php new file mode 100644 index 0000000..0144c35 --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260614183449.php @@ -0,0 +1,513 @@ +has('blok')) { + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, + 'B' => 13, + 'C' => 13, + 'D' => 13, + 'E' => 13, + 'F' => 13, + 'G' => 13, + 'H' => 13, + 'I' => 13, + 'J' => 13, + 'K' => 13, + 'L' => 13, + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260614183500.php b/.history/app/Http/Controllers/PenghuniController_20260614183500.php new file mode 100644 index 0000000..dde177c --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260614183500.php @@ -0,0 +1,518 @@ +has('blok')) { + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => [ + 'required', + \Illuminate\Validation\Rule::unique('rumah')->where(function ($query) use ($request) { + return $query->where('blok', $request->blok); + }), + ], + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, + 'B' => 13, + 'C' => 13, + 'D' => 13, + 'E' => 13, + 'F' => 13, + 'G' => 13, + 'H' => 13, + 'I' => 13, + 'J' => 13, + 'K' => 13, + 'L' => 13, + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260614183504.php b/.history/app/Http/Controllers/PenghuniController_20260614183504.php new file mode 100644 index 0000000..beefe7c --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260614183504.php @@ -0,0 +1,518 @@ +has('blok')) { + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => [ + 'required', + \Illuminate\Validation\Rule::unique('rumah')->where(function ($query) use ($request) { + return $query->where('blok', $request->blok); + }), + ], + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, + 'B' => 13, + 'C' => 13, + 'D' => 13, + 'E' => 13, + 'F' => 13, + 'G' => 13, + 'H' => 13, + 'I' => 13, + 'J' => 13, + 'K' => 13, + 'L' => 13, + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260614183546.php b/.history/app/Http/Controllers/PenghuniController_20260614183546.php new file mode 100644 index 0000000..6f522f1 --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260614183546.php @@ -0,0 +1,520 @@ +has('blok')) { + + + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => [ + 'required', + \Illuminate\Validation\Rule::unique('rumah')->where(function ($query) use ($request) { + return $query->where('blok', $request->blok); + }), + ], + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, + 'B' => 13, + 'C' => 13, + 'D' => 13, + 'E' => 13, + 'F' => 13, + 'G' => 13, + 'H' => 13, + 'I' => 13, + 'J' => 13, + 'K' => 13, + 'L' => 13, + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260614183547.php b/.history/app/Http/Controllers/PenghuniController_20260614183547.php new file mode 100644 index 0000000..592f480 --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260614183547.php @@ -0,0 +1,527 @@ +has('blok')) { + + // Cek duplikat blok + no_rumah + $sudahAda = \App\Models\Rumah::where('blok', $request->blok) + ->where('no_rumah', $request->no_rumah) + ->exists(); + + if ($sudahAda) { + return back()->with('error', 'Kavling ' . $request->blok . ' No. ' . $request->no_rumah . ' sudah ada!'); + } + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => [ + 'required', + \Illuminate\Validation\Rule::unique('rumah')->where(function ($query) use ($request) { + return $query->where('blok', $request->blok); + }), + ], + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, + 'B' => 13, + 'C' => 13, + 'D' => 13, + 'E' => 13, + 'F' => 13, + 'G' => 13, + 'H' => 13, + 'I' => 13, + 'J' => 13, + 'K' => 13, + 'L' => 13, + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260614183556.php b/.history/app/Http/Controllers/PenghuniController_20260614183556.php new file mode 100644 index 0000000..cf7a771 --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260614183556.php @@ -0,0 +1,527 @@ +has('blok')) { + + // Cek duplikat blok + no_rumah + $sudahAda = \App\Models\Rumah::where('blok', $request->blok) + ->where('no_rumah', $request->no_rumah) + ->exists(); + + if ($sudahAda) { + return back()->with('error', 'Kavling ' . $request->blok . ' No. ' . $request->no_rumah . ' sudah ada!'); + } + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => [ + 'required', + \Illuminate\Validation\Rule::unique('rumah')->where(function ($query) use ($request) { + return $query->where('blok', $request->blok); + }), + ], + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, + 'B' => 13, + 'C' => 13, + 'D' => 13, + 'E' => 13, + 'F' => 13, + 'G' => 13, + 'H' => 13, + 'I' => 13, + 'J' => 13, + 'K' => 13, + 'L' => 13, + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260614183933.php b/.history/app/Http/Controllers/PenghuniController_20260614183933.php new file mode 100644 index 0000000..5a80fd4 --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260614183933.php @@ -0,0 +1,529 @@ +has('blok')) { + + // Cek duplikat blok + no_rumah + $sudahAda = \App\Models\Rumah::where('blok', $request->blok) + ->where('no_rumah', $request->no_rumah) + ->exists(); + + if ($sudahAda) { + return redirect()->back() + ->with('error', 'Kavling ' . $request->blok . ' No. ' . $request->no_rumah . ' sudah ada!'); +}eturn back()->with('error', 'Kavling ' . $request->blok . ' No. ' . $request->no_rumah . ' sudah ada!'); + } + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => [ + 'required', + \Illuminate\Validation\Rule::unique('rumah')->where(function ($query) use ($request) { + return $query->where('blok', $request->blok); + }), + ], + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, + 'B' => 13, + 'C' => 13, + 'D' => 13, + 'E' => 13, + 'F' => 13, + 'G' => 13, + 'H' => 13, + 'I' => 13, + 'J' => 13, + 'K' => 13, + 'L' => 13, + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260614183935.php b/.history/app/Http/Controllers/PenghuniController_20260614183935.php new file mode 100644 index 0000000..cf7a771 --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260614183935.php @@ -0,0 +1,527 @@ +has('blok')) { + + // Cek duplikat blok + no_rumah + $sudahAda = \App\Models\Rumah::where('blok', $request->blok) + ->where('no_rumah', $request->no_rumah) + ->exists(); + + if ($sudahAda) { + return back()->with('error', 'Kavling ' . $request->blok . ' No. ' . $request->no_rumah . ' sudah ada!'); + } + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => [ + 'required', + \Illuminate\Validation\Rule::unique('rumah')->where(function ($query) use ($request) { + return $query->where('blok', $request->blok); + }), + ], + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, + 'B' => 13, + 'C' => 13, + 'D' => 13, + 'E' => 13, + 'F' => 13, + 'G' => 13, + 'H' => 13, + 'I' => 13, + 'J' => 13, + 'K' => 13, + 'L' => 13, + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260614183941.php b/.history/app/Http/Controllers/PenghuniController_20260614183941.php new file mode 100644 index 0000000..5383e86 --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260614183941.php @@ -0,0 +1,528 @@ +has('blok')) { + + // Cek duplikat blok + no_rumah + $sudahAda = \App\Models\Rumah::where('blok', $request->blok) + ->where('no_rumah', $request->no_rumah) + ->exists(); + + if ($sudahAda) { + return redirect()->back() + ->with('error', 'Kavling ' . $request->blok . ' No. ' . $request->no_rumah . ' sudah ada!'); +} + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => [ + 'required', + \Illuminate\Validation\Rule::unique('rumah')->where(function ($query) use ($request) { + return $query->where('blok', $request->blok); + }), + ], + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, + 'B' => 13, + 'C' => 13, + 'D' => 13, + 'E' => 13, + 'F' => 13, + 'G' => 13, + 'H' => 13, + 'I' => 13, + 'J' => 13, + 'K' => 13, + 'L' => 13, + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260614183944.php b/.history/app/Http/Controllers/PenghuniController_20260614183944.php new file mode 100644 index 0000000..ba11ada --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260614183944.php @@ -0,0 +1,528 @@ +has('blok')) { + + // Cek duplikat blok + no_rumah + $sudahAda = \App\Models\Rumah::where('blok', $request->blok) + ->where('no_rumah', $request->no_rumah) + ->exists(); + + if ($sudahAda) { + return redirect()->back() + ->with('error', 'Kavling ' . $request->blok . ' No. ' . $request->no_rumah . ' sudah ada!'); + } + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => [ + 'required', + \Illuminate\Validation\Rule::unique('rumah')->where(function ($query) use ($request) { + return $query->where('blok', $request->blok); + }), + ], + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, + 'B' => 13, + 'C' => 13, + 'D' => 13, + 'E' => 13, + 'F' => 13, + 'G' => 13, + 'H' => 13, + 'I' => 13, + 'J' => 13, + 'K' => 13, + 'L' => 13, + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260614184208.php b/.history/app/Http/Controllers/PenghuniController_20260614184208.php new file mode 100644 index 0000000..f8f2631 --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260614184208.php @@ -0,0 +1,530 @@ +has('blok')) { + + // Cek duplikat blok + no_rumah + $sudahAda = \App\Models\Rumah::where('blok', $request->blok) + ->where('no_rumah', $request->no_rumah) + ->exists(); + + if ($sudahAda) { + return redirect()->back() + ->with('error', 'Kavling ' . $request->blok . ' No. ' . $request->no_rumah . ' sudah ada!'); + } + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => [ + 'required', + \Illuminate\Validation\Rule::unique('rumah')->where(function ($query) use ($request) { + return $query->where('blok', $request->blok); + }), + ], + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, + 'B' => 13, + 'C' => 13, + 'D' => 13, + 'E' => 13, + 'F' => 13, + 'G' => 13, + 'H' => 13, + 'I' => 13, + 'J' => 13, + 'K' => 13, + 'L' => 13, + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260614184210.php b/.history/app/Http/Controllers/PenghuniController_20260614184210.php new file mode 100644 index 0000000..da56f41 --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260614184210.php @@ -0,0 +1,529 @@ +has('blok')) { + + // Cek duplikat blok + no_rumah + $sudahAda = \App\Models\Rumah::where('blok', $request->blok) + ->where('no_rumah', $request->no_rumah) + ->exists(); + + if ($sudahAda) { + return redirect()->back() + ->with('error', 'Kavling ' . $request->blok . ' No. ' . $request->no_rumah . ' sudah ada!'); + } + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => [ + 'required', + \Illuminate\Validation\Rule::unique('rumah')->where(function ($query) use ($request) { + return $query->where('blok', $request->blok); + }), + ], + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, + 'B' => 13, + 'C' => 13, + 'D' => 13, + 'E' => 13, + 'F' => 13, + 'G' => 13, + 'H' => 13, + 'I' => 13, + 'J' => 13, + 'K' => 13, + 'L' => 13, + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260614184211.php b/.history/app/Http/Controllers/PenghuniController_20260614184211.php new file mode 100644 index 0000000..332dd6f --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260614184211.php @@ -0,0 +1,537 @@ +has('blok')) { + + // Cek duplikat blok + no_rumah + $sudahAda = \App\Models\Rumah::where('blok', $request->blok) + ->where('no_rumah', $request->no_rumah) + ->exists(); + + if ($sudahAda) { + return redirect()->back() + ->with('error', 'Kavling ' . $request->blok . ' No. ' . $request->no_rumah . ' sudah ada!'); + } + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + // ✅ Cek duplikat DULU sebelum validate + $sudahAda = \App\Models\Rumah::where('blok', $request->blok) + ->where('no_rumah', $request->no_rumah) + ->exists(); + + if ($sudahAda) { + return redirect()->back() + ->with('error', 'Kavling ' . $request->blok . ' No. ' . $request->no_rumah . ' sudah ada!'); + } + $request->validate([ + 'blok' => 'required', + 'no_rumah' => [ + 'required', + \Illuminate\Validation\Rule::unique('rumah')->where(function ($query) use ($request) { + return $query->where('blok', $request->blok); + }), + ], + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, + 'B' => 13, + 'C' => 13, + 'D' => 13, + 'E' => 13, + 'F' => 13, + 'G' => 13, + 'H' => 13, + 'I' => 13, + 'J' => 13, + 'K' => 13, + 'L' => 13, + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260614184217.php b/.history/app/Http/Controllers/PenghuniController_20260614184217.php new file mode 100644 index 0000000..de88212 --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260614184217.php @@ -0,0 +1,537 @@ +has('blok')) { + + // Cek duplikat blok + no_rumah + $sudahAda = \App\Models\Rumah::where('blok', $request->blok) + ->where('no_rumah', $request->no_rumah) + ->exists(); + + if ($sudahAda) { + return redirect()->back() + ->with('error', 'Kavling ' . $request->blok . ' No. ' . $request->no_rumah . ' sudah ada!'); + } + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + // ✅ Cek duplikat DULU sebelum validate + $sudahAda = \App\Models\Rumah::where('blok', $request->blok) + ->where('no_rumah', $request->no_rumah) + ->exists(); + + if ($sudahAda) { + return redirect()->back() + ->with('error', 'Kavling ' . $request->blok . ' No. ' . $request->no_rumah . ' sudah ada!'); + } + $request->validate([ + 'blok' => 'required', + 'no_rumah' => [ + 'required', + \Illuminate\Validation\Rule::unique('rumah')->where(function ($query) use ($request) { + return $query->where('blok', $request->blok); + }), + ], + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, + 'B' => 13, + 'C' => 13, + 'D' => 13, + 'E' => 13, + 'F' => 13, + 'G' => 13, + 'H' => 13, + 'I' => 13, + 'J' => 13, + 'K' => 13, + 'L' => 13, + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260614184219.php b/.history/app/Http/Controllers/PenghuniController_20260614184219.php new file mode 100644 index 0000000..2e9d3ff --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260614184219.php @@ -0,0 +1,538 @@ +has('blok')) { + + // Cek duplikat blok + no_rumah + $sudahAda = \App\Models\Rumah::where('blok', $request->blok) + ->where('no_rumah', $request->no_rumah) + ->exists(); + + if ($sudahAda) { + return redirect()->back() + ->with('error', 'Kavling ' . $request->blok . ' No. ' . $request->no_rumah . ' sudah ada!'); + } + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + // ✅ Cek duplikat DULU sebelum validate + $sudahAda = \App\Models\Rumah::where('blok', $request->blok) + ->where('no_rumah', $request->no_rumah) + ->exists(); + + if ($sudahAda) { + return redirect()->back() + ->with('error', 'Kavling ' . $request->blok . ' No. ' . $request->no_rumah . ' sudah ada!'); + } + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => [ + 'required', + \Illuminate\Validation\Rule::unique('rumah')->where(function ($query) use ($request) { + return $query->where('blok', $request->blok); + }), + ], + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, + 'B' => 13, + 'C' => 13, + 'D' => 13, + 'E' => 13, + 'F' => 13, + 'G' => 13, + 'H' => 13, + 'I' => 13, + 'J' => 13, + 'K' => 13, + 'L' => 13, + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260614184337.php b/.history/app/Http/Controllers/PenghuniController_20260614184337.php new file mode 100644 index 0000000..ef47773 --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260614184337.php @@ -0,0 +1,538 @@ +has('blok')) { + + // // Cek duplikat blok + no_rumah + // $sudahAda = \App\Models\Rumah::where('blok', $request->blok) + // ->where('no_rumah', $request->no_rumah) + // ->exists(); + + // if ($sudahAda) { + // return redirect()->back() + // ->with('error', 'Kavling ' . $request->blok . ' No. ' . $request->no_rumah . ' sudah ada!'); + // } + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + // ✅ Cek duplikat DULU sebelum validate + $sudahAda = \App\Models\Rumah::where('blok', $request->blok) + ->where('no_rumah', $request->no_rumah) + ->exists(); + + if ($sudahAda) { + return redirect()->back() + ->with('error', 'Kavling ' . $request->blok . ' No. ' . $request->no_rumah . ' sudah ada!'); + } + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => [ + 'required', + \Illuminate\Validation\Rule::unique('rumah')->where(function ($query) use ($request) { + return $query->where('blok', $request->blok); + }), + ], + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, + 'B' => 13, + 'C' => 13, + 'D' => 13, + 'E' => 13, + 'F' => 13, + 'G' => 13, + 'H' => 13, + 'I' => 13, + 'J' => 13, + 'K' => 13, + 'L' => 13, + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260614184732.php b/.history/app/Http/Controllers/PenghuniController_20260614184732.php new file mode 100644 index 0000000..2a225ba --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260614184732.php @@ -0,0 +1,556 @@ +has('blok')) { + + // // Cek duplikat blok + no_rumah + // $sudahAda = \App\Models\Rumah::where('blok', $request->blok) + // ->where('no_rumah', $request->no_rumah) + // ->exists(); + + // if ($sudahAda) { + // return redirect()->back() + // ->with('error', 'Kavling ' . $request->blok . ' No. ' . $request->no_rumah . ' sudah ada!'); + // } + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) +{ + // Normalisasi blok dulu + $blok = strtoupper(trim($request->blok)); + + // ✅ Cek duplikat kombinasi blok + no_rumah + $sudahAda = \App\Models\Rumah::whereRaw('UPPER(TRIM(blok)) = ?', [$blok]) + ->where('no_rumah', $request->no_rumah) + ->exists(); + + if ($sudahAda) { + return redirect()->back() + ->with('error', 'Kavling Blok ' . $blok . ' No. ' . $request->no_rumah . ' sudah terdaftar!'); + } + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($blok); + + if (!$rtId) { + return redirect()->back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $blok, // simpan dalam format uppercase + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah'=> $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan'=> $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); +} + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, + 'B' => 13, + 'C' => 13, + 'D' => 13, + 'E' => 13, + 'F' => 13, + 'G' => 13, + 'H' => 13, + 'I' => 13, + 'J' => 13, + 'K' => 13, + 'L' => 13, + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260614184735.php b/.history/app/Http/Controllers/PenghuniController_20260614184735.php new file mode 100644 index 0000000..ef47773 --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260614184735.php @@ -0,0 +1,538 @@ +has('blok')) { + + // // Cek duplikat blok + no_rumah + // $sudahAda = \App\Models\Rumah::where('blok', $request->blok) + // ->where('no_rumah', $request->no_rumah) + // ->exists(); + + // if ($sudahAda) { + // return redirect()->back() + // ->with('error', 'Kavling ' . $request->blok . ' No. ' . $request->no_rumah . ' sudah ada!'); + // } + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) + { + // ✅ Cek duplikat DULU sebelum validate + $sudahAda = \App\Models\Rumah::where('blok', $request->blok) + ->where('no_rumah', $request->no_rumah) + ->exists(); + + if ($sudahAda) { + return redirect()->back() + ->with('error', 'Kavling ' . $request->blok . ' No. ' . $request->no_rumah . ' sudah ada!'); + } + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => [ + 'required', + \Illuminate\Validation\Rule::unique('rumah')->where(function ($query) use ($request) { + return $query->where('blok', $request->blok); + }), + ], + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + // 🔥 INI YANG DIPAKAI + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, + 'B' => 13, + 'C' => 13, + 'D' => 13, + 'E' => 13, + 'F' => 13, + 'G' => 13, + 'H' => 13, + 'I' => 13, + 'J' => 13, + 'K' => 13, + 'L' => 13, + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260614184747.php b/.history/app/Http/Controllers/PenghuniController_20260614184747.php new file mode 100644 index 0000000..2864868 --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260614184747.php @@ -0,0 +1,535 @@ +has('blok')) { + + // // Cek duplikat blok + no_rumah + // $sudahAda = \App\Models\Rumah::where('blok', $request->blok) + // ->where('no_rumah', $request->no_rumah) + // ->exists(); + + // if ($sudahAda) { + // return redirect()->back() + // ->with('error', 'Kavling ' . $request->blok . ' No. ' . $request->no_rumah . ' sudah ada!'); + // } + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) +{ + // Normalisasi blok dulu + $blok = strtoupper(trim($request->blok)); + + // ✅ Cek duplikat kombinasi blok + no_rumah + $sudahAda = \App\Models\Rumah::whereRaw('UPPER(TRIM(blok)) = ?', [$blok]) + ->where('no_rumah', $request->no_rumah) + ->exists(); + + if ($sudahAda) { + return redirect()->back() + ->with('error', 'Kavling Blok ' . $blok . ' No. ' . $request->no_rumah . ' sudah terdaftar!'); + } + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($blok); + + if (!$rtId) { + return redirect()->back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $blok, // simpan dalam format uppercase + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah'=> $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan'=> $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); +} + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, + 'B' => 13, + 'C' => 13, + 'D' => 13, + 'E' => 13, + 'F' => 13, + 'G' => 13, + 'H' => 13, + 'I' => 13, + 'J' => 13, + 'K' => 13, + 'L' => 13, + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260614184931.php b/.history/app/Http/Controllers/PenghuniController_20260614184931.php new file mode 100644 index 0000000..c855a80 --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260614184931.php @@ -0,0 +1,540 @@ +has('blok')) { + + // // Cek duplikat blok + no_rumah + // $sudahAda = \App\Models\Rumah::where('blok', $request->blok) + // ->where('no_rumah', $request->no_rumah) + // ->exists(); + + // if ($sudahAda) { + // return redirect()->back() + // ->with('error', 'Kavling ' . $request->blok . ' No. ' . $request->no_rumah . ' sudah ada!'); + // } + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) +{ + // Normalisasi blok — hapus prefix "blok" lalu uppercase + $blok = strtoupper(trim($request->blok)); + $blok = trim(preg_replace('/^BLOK\s+/i', '', $blok)); // "Blok A" → "A" + + // Ambil semua rumah lalu normalisasi di PHP untuk cek duplikat + $sudahAda = \App\Models\Rumah::where('no_rumah', $request->no_rumah) + ->get() + ->contains(function ($r) use ($blok) { + $dbBlok = strtoupper(trim($r->blok)); + $dbBlok = trim(preg_replace('/^BLOK\s+/i', '', $dbBlok)); + return $dbBlok === $blok; + }); + + if ($sudahAda) { + return redirect()->back() + ->with('error', 'Kavling Blok ' . $blok . ' No. ' . $request->no_rumah . ' sudah terdaftar!'); + } + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($blok); + + if (!$rtId) { + return redirect()->back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $blok, // disimpan konsisten: "A", "B", dst + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId, + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); +} + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, + 'B' => 13, + 'C' => 13, + 'D' => 13, + 'E' => 13, + 'F' => 13, + 'G' => 13, + 'H' => 13, + 'I' => 13, + 'J' => 13, + 'K' => 13, + 'L' => 13, + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260614185304.php b/.history/app/Http/Controllers/PenghuniController_20260614185304.php new file mode 100644 index 0000000..33d7da1 --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260614185304.php @@ -0,0 +1,547 @@ +has('blok')) { + + // // Cek duplikat blok + no_rumah + // $sudahAda = \App\Models\Rumah::where('blok', $request->blok) + // ->where('no_rumah', $request->no_rumah) + // ->exists(); + + // if ($sudahAda) { + // return redirect()->back() + // ->with('error', 'Kavling ' . $request->blok . ' No. ' . $request->no_rumah . ' sudah ada!'); + // } + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) +{ + // Normalisasi blok + $blok = strtoupper(trim($request->blok)); + $blok = trim(preg_replace('/^BLOK\s+/i', '', $blok)); + + $noRumah = $request->no_rumah; + + // Ambil semua rumah, normalisasi di PHP, cek manual + $semuaRumah = \App\Models\Rumah::all(); + + $sudahAda = false; + foreach ($semuaRumah as $r) { + $dbBlok = strtoupper(trim($r->blok)); + $dbBlok = trim(preg_replace('/^BLOK\s+/i', '', $dbBlok)); + + if ($dbBlok === $blok && (string)$r->no_rumah === (string)$noRumah) { + $sudahAda = true; + break; + } + } + + if ($sudahAda) { + return redirect()->back() + ->with('error', 'Kavling Blok ' . $blok . ' No. ' . $noRumah . ' sudah terdaftar!'); + } + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($blok); + + if (!$rtId) { + return redirect()->back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $blok, + 'no_rumah' => $noRumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId, + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); +} + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, + 'B' => 13, + 'C' => 13, + 'D' => 13, + 'E' => 13, + 'F' => 13, + 'G' => 13, + 'H' => 13, + 'I' => 13, + 'J' => 13, + 'K' => 13, + 'L' => 13, + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/PenghuniController_20260614190042.php b/.history/app/Http/Controllers/PenghuniController_20260614190042.php new file mode 100644 index 0000000..761fa6c --- /dev/null +++ b/.history/app/Http/Controllers/PenghuniController_20260614190042.php @@ -0,0 +1,536 @@ +has('blok')) { + + // // Cek duplikat blok + no_rumah + // $sudahAda = \App\Models\Rumah::where('blok', $request->blok) + // ->where('no_rumah', $request->no_rumah) + // ->exists(); + + // if ($sudahAda) { + // return redirect()->back() + // ->with('error', 'Kavling ' . $request->blok . ' No. ' . $request->no_rumah . ' sudah ada!'); + // } + + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); + } + + $penghuni = Penghuni::with('rumah')->get(); + $rumahList = Rumah::with('penghuni')->get(); + + return view('admin.penghuni.index', compact('penghuni', 'rumahList')); + } + + // ========================= + // FORM TAMBAH + // ========================= + public function create() + { + $rumah = Rumah::where('status', 'Kosong')->get(); + return view('admin.penghuni.create', compact('rumah')); + } + + // ========================= + // SIMPAN DATA + // ========================= + public function store(Request $request) + { + $validated = $request->validate([ + + 'nama' => 'required|string|max:100', + 'no_ktp' => 'required|string|max:20|unique:penghuni,no_ktp', + 'email' => 'required|email|max:100|unique:penghuni,email', + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + if ($request->rumah_id) { + + $rumah = \App\Models\Rumah::find($request->rumah_id); + + if ($rumah && $rumah->rt_id) { + + $jumlah = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rumah) { + $q->where('rt_id', $rumah->rt_id); + })->count(); + + if ($jumlah >= 20) { + return back()->with('error', 'RT sudah penuh (max 20 penghuni)'); + } + } + } + + // 🔥 AUTO ISI TANGGAL MASUK + $validated['tanggal_masuk'] = $request->input('tanggal_masuk') ?: now(); + + $validated['user_id'] = Auth::id(); + + $penghuni = Penghuni::create($validated); + + // set rumah jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil disimpan.'); + } + + // ========================= + // FORM EDIT + // ========================= + public function edit($id) + { + $penghuni = Penghuni::findOrFail($id); + + $rumahList = Rumah::where('status', 'Kosong') + ->orWhere('id', $penghuni->rumah_id) + ->get(); + + return view('admin.penghuni.edit', compact('penghuni', 'rumahList')); + } + + // ========================= + // UPDATE DATA + // ========================= + public function update(Request $request, $id) + { + $penghuni = Penghuni::findOrFail($id); + + $validated = $request->validate([ + 'nama' => 'required|string|max:100', + 'no_ktp' => ['required', Rule::unique('penghuni')->ignore($id)], + 'email' => ['required', 'email', Rule::unique('penghuni')->ignore($id)], + 'telepon' => 'nullable|string|max:20', + 'alamat' => 'required|string|max:150', + 'rumah_id' => 'nullable|exists:rumah,id', + 'status' => 'required|in:Aktif,Tidak Aktif', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_masuk' => 'nullable|date', + 'tanggal_keluar' => 'nullable|date|after_or_equal:tanggal_masuk', + ]); + + $oldRumahId = $penghuni->rumah_id; + + $penghuni->update($validated); + + // kosongkan rumah lama + if ($oldRumahId && $oldRumahId != $request->rumah_id) { + Rumah::where('id', $oldRumahId) + ->update(['status' => 'Kosong']); + } + + // set rumah baru jadi terisi + if ($request->rumah_id) { + Rumah::where('id', $request->rumah_id) + ->update(['status' => 'Terisi']); + } + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil diperbarui.'); + } + + // ========================= + // HAPUS DATA + // ========================= + public function destroy($id) + { + $penghuni = Penghuni::findOrFail($id); + + // kosongkan rumah + if ($penghuni->rumah_id) { + Rumah::where('id', $penghuni->rumah_id) + ->update(['status' => 'Kosong']); + } + + $penghuni->delete(); + + return redirect()->route('penghuni.index') + ->with('success', 'Data penghuni berhasil dihapus!'); + } + + // ========================= + // SIMPAN RUMAH (MODAL) + // ========================= + public function storeRumah(Request $request) +{ + // Input dari dropdown sudah bersih, tinggal uppercase saja + $blok = strtoupper(trim($request->blok)); + $noRumah = trim($request->no_rumah); + + // Cek duplikat langsung pakai query, sudah pasti format sama + $sudahAda = \App\Models\Rumah::where('blok', $blok) + ->where('no_rumah', $noRumah) + ->exists(); + + if ($sudahAda) { + return redirect()->back() + ->with('error', 'Kavling Blok ' . $blok . ' No. ' . $noRumah . ' sudah terdaftar!'); + } + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + ]); + + $namaFile = null; + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + $file->move(public_path('foto_rumah'), $namaFile); + } + + $rtId = $this->getRtOtomatis($blok); + + if (!$rtId) { + return redirect()->back()->with('error', 'Blok tidak dikenali!'); + } + + \App\Models\Rumah::create([ + 'blok' => $blok, + 'no_rumah' => $noRumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile, + 'rt_id' => $rtId, + ]); + + return redirect()->back()->with('success', 'Rumah berhasil ditambahkan'); +} + + // ========================= + // EDIT RUMAH + // ========================= + public function editRumah($id) + { + $rumah = Rumah::findOrFail($id); + + return view('admin.penghuni.edit', [ + 'penghuni' => null, + 'rumah' => $rumah, + 'rumahList' => Rumah::with('penghuni')->get() + ]); + } + + // ========================= + // UPDATE RUMAH + // ========================= + public function updateRumah(Request $request, $id) +{ + $rumah = Rumah::findOrFail($id); + + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $rtId = $this->getRtOtomatis($request->blok); + + if (!$rtId) { + return back()->with('error', 'Blok tidak dikenali!'); + } + + $data = [ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'rt_id' => $rtId + ]; + + // =============================== + // 🔥 TAMBAHAN LOGIC (PENTING) + // =============================== + $penghuni = \App\Models\Penghuni::where('rumah_id', $rumah->id)->first(); + + if ($penghuni) { + // kalau ada penghuni → paksa jadi terisi + $data['status'] = 'Terisi'; + } else { + // kalau tidak ada penghuni → kosong + $data['status'] = 'Kosong'; + } + // =============================== + + if ($request->hasFile('foto')) { + + // hapus lama + if ($rumah->foto && file_exists(public_path('foto_rumah/'.$rumah->foto))) { + unlink(public_path('foto_rumah/'.$rumah->foto)); + } + + $file = $request->file('foto'); + $namaFile = time().'_'.$file->getClientOriginalName(); + $file->move(public_path('foto_rumah'), $namaFile); + + $data['foto'] = $namaFile; + } + + $rumah->update($data); + + return redirect()->route('penghuni.index') + ->with('success', 'Data rumah berhasil diupdate'); +} + + // ========================= + // HAPUS RUMAH + // ========================= + public function destroyRumah($id) + { + $rumah = Rumah::findOrFail($id); + $rumah->delete(); + + return redirect()->back() + ->with('success', 'Data rumah berhasil dihapus'); + } + + public function indexRT() + { + $rtId = Auth::id(); + + $penghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.penghuni.index', compact('penghuni')); + } + + public function bagiRT() + { + $rtList = User::where('role', 'rt')->get(); + $rumahs = Rumah::orderBy('id')->get(); + + if ($rtList->count() == 0) { + return back()->with('error', 'RT belum ada!'); + } + + $rtIndex = 0; + $counter = 0; + + foreach ($rumahs as $rumah) { + + $rumah->rt_id = $rtList[$rtIndex]->id; + $rumah->save(); + + $counter++; + + if ($counter == 20) { + $rtIndex++; + $counter = 0; + + if ($rtIndex >= $rtList->count()) { + $rtIndex = 0; + } + } + } + + return back()->with('success', 'Pembagian RT berhasil!'); + } + + public function rumahRT() + { + $rtId = Auth::id(); + + $rumah = \App\Models\Rumah::where('rt_id', $rtId)->get(); + + return view('rt.rumah.index', compact('rumah')); + } + + public function iuranRT() + { + $rtId = Auth::id(); + + $iuran = \App\Models\Iuran::whereHas('penghuni.rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.iuran.index', compact('iuran')); + } + + public function dashboardRT() + { + $rtId = Auth::id(); + + $totalRumah = \App\Models\Rumah::where('rt_id', $rtId)->count(); + + $totalPenghuni = \App\Models\Penghuni::whereHas('rumah', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->count(); + + return view('rt.dashboard', compact('totalRumah', 'totalPenghuni')); + } + private function getRtOtomatis($blok) + { + if (!$blok) return null; + + // 🔥 bersihin input + $blok = trim($blok); + $blok = strtoupper($blok); + + $prefix = substr($blok, 0, 1); + + $mapping = [ + 'A' => 13, + 'B' => 13, + 'C' => 13, + 'D' => 13, + 'E' => 13, + 'F' => 13, + 'G' => 13, + 'H' => 13, + 'I' => 13, + 'J' => 13, + 'K' => 13, + 'L' => 13, + ]; + + return $mapping[$prefix] ?? null; + } + + // private function getRtOtomatis() + // { + // $rtList = \App\Models\User::where('role', 'rt')->orderBy('id')->get(); + + // if ($rtList->count() == 0) { + // return null; + // } + + // $jumlahRumah = \App\Models\Rumah::count(); + + // // tiap 10 rumah pindah RT + // $rtIndex = floor($jumlahRumah / 10); + + // // reset kalau melebihi jumlah RT + // if ($rtIndex >= $rtList->count()) { + // $rtIndex = 0; + // } + + // return $rtList[$rtIndex]->id; + // } + + public function layananRT() + { + $rtId = Auth::user()->id; + + $data = Layanan::whereHas('penghuni', function ($q) use ($rtId) { + $q->where('rt_id', $rtId); + })->get(); + + return view('rt.layanan.index', ['layanan' => $data]); + } + + public function home() + { + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id)->first(); + + $rumah = null; + $rtUser = null; + + if ($penghuni && $penghuni->rumah) { + $rumah = $penghuni->rumah; + + // 🔥 ambil user RT dari rt_id + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser')); + } + + public function editProfile() + { + $user = Auth::user(); + return view('rt.profile.edit', compact('user')); + } + + public function updateProfile(Request $request) + { + $user = \App\Models\User::find(Auth::id()); + + $request->validate([ + 'photo' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + if ($request->hasFile('photo')) { + + if ($user->photo && file_exists(public_path('profile/'.$user->photo))) { + unlink(public_path('profile/'.$user->photo)); + } + + $file = $request->file('photo'); + $filename = time().'_'.$file->getClientOriginalName(); + + $file->move(public_path('profile'), $filename); + + $user->photo = $filename; + } + + $user->save(); + + Auth::login($user); // 🔥 penting + + return back()->with('success', 'Foto berhasil diupdate!'); + } + +} + diff --git a/.history/app/Http/Controllers/RT/BendaharaController_20260619090446.php b/.history/app/Http/Controllers/RT/BendaharaController_20260619090446.php new file mode 100644 index 0000000..e69de29 diff --git a/.history/app/Http/Controllers/RT/BendaharaController_20260619090459.php b/.history/app/Http/Controllers/RT/BendaharaController_20260619090459.php new file mode 100644 index 0000000..1cca1d7 --- /dev/null +++ b/.history/app/Http/Controllers/RT/BendaharaController_20260619090459.php @@ -0,0 +1,76 @@ +id) + ->where('role', 'bendahara') + ->orderBy('created_at', 'desc') + ->get(); + + $bendaharaAktif = $bendaharas->where('status_akun', 'aktif')->first(); + + return view('rt.bendahara.index', compact('bendaharas', 'bendaharaAktif')); + } + + // Simpan akun bendahara baru + public function store(Request $request) + { + $rt = Auth::user(); + + // Cek apakah RT sudah punya bendahara aktif + $sudahAda = User::where('rt_id', $rt->id) + ->where('role', 'bendahara') + ->where('status_akun', 'aktif') + ->exists(); + + if ($sudahAda) { + return back()->withErrors(['bendahara' => 'Nonaktifkan bendahara aktif dulu sebelum membuat akun baru.']); + } + + $request->validate([ + 'name' => 'required|string|max:255', + 'username' => 'required|string|unique:users,username', + 'email' => 'required|email|unique:users,email', + 'password' => 'required|min:6|confirmed', + ]); + + User::create([ + 'name' => $request->name, + 'username' => $request->username, + 'email' => $request->email, + 'password' => Hash::make($request->password), + 'role' => 'bendahara', + 'rt_id' => $rt->id, + 'status_akun' => 'aktif', + ]); + + return back()->with('success', 'Akun bendahara berhasil dibuat.'); + } + + // Nonaktifkan bendahara (bukan hapus) + public function nonaktifkan($id) + { + $rt = Auth::user(); + + $bendahara = User::where('id', $id) + ->where('rt_id', $rt->id) + ->where('role', 'bendahara') + ->firstOrFail(); + + $bendahara->update(['status_akun' => 'nonaktif']); + + return back()->with('success', 'Akun bendahara berhasil dinonaktifkan.'); + } +} diff --git a/.history/app/Http/Controllers/RT/BendaharaController_20260619105958.php b/.history/app/Http/Controllers/RT/BendaharaController_20260619105958.php new file mode 100644 index 0000000..12f2ba5 --- /dev/null +++ b/.history/app/Http/Controllers/RT/BendaharaController_20260619105958.php @@ -0,0 +1,77 @@ +id) + ->where('role', 'bendahara') + ->orderBy('created_at', 'desc') + ->get(); + + $bendaharaAktif = $bendaharas->where('status_akun', 'aktif')->first(); + + return view('rt.bendahara.index', compact('bendaharas', 'bendaharaAktif')); + } + + // Simpan akun bendahara baru + // Simpan akun bendahara baru + public function store(Request $request) + { + $rt = Auth::user(); + + // Cek apakah RT sudah punya bendahara aktif + $sudahAda = User::where('rt_id', $rt->id) + ->where('role', 'bendahara') + ->where('status_akun', 'aktif') + ->exists(); + + if ($sudahAda) { + return back()->withErrors(['bendahara' => 'Nonaktifkan bendahara aktif dulu sebelum membuat akun baru.']); + } + + $request->validate([ + 'name' => 'required|string|max:255', + 'username' => 'required|string|unique:users,username', + 'email' => 'required|email|unique:users,email', + ]); + + User::create([ + 'name' => $request->name, + 'username' => $request->username, + 'email' => $request->email, + 'password' => Hash::make('12345678'), // password default + 'role' => 'bendahara', + 'rt_id' => $rt->id, + 'status_akun' => 'aktif', + 'wajib_ganti_password' => true, + ]); + + return back()->with('success', 'Akun bendahara berhasil dibuat. Password default: 12345678 (wajib diganti saat login pertama).'); + } + + // Nonaktifkan bendahara (bukan hapus) + public function nonaktifkan($id) + { + $rt = Auth::user(); + + $bendahara = User::where('id', $id) + ->where('rt_id', $rt->id) + ->where('role', 'bendahara') + ->firstOrFail(); + + $bendahara->update(['status_akun' => 'nonaktif']); + + return back()->with('success', 'Akun bendahara berhasil dinonaktifkan.'); + } +} diff --git a/.history/app/Http/Controllers/RT/BendaharaController_20260619110049.php b/.history/app/Http/Controllers/RT/BendaharaController_20260619110049.php new file mode 100644 index 0000000..47772e9 --- /dev/null +++ b/.history/app/Http/Controllers/RT/BendaharaController_20260619110049.php @@ -0,0 +1,76 @@ +id) + ->where('role', 'bendahara') + ->orderBy('created_at', 'desc') + ->get(); + + $bendaharaAktif = $bendaharas->where('status_akun', 'aktif')->first(); + + return view('rt.bendahara.index', compact('bendaharas', 'bendaharaAktif')); + } + + // Simpan akun bendahara baru + public function store(Request $request) + { + $rt = Auth::user(); + + // Cek apakah RT sudah punya bendahara aktif + $sudahAda = User::where('rt_id', $rt->id) + ->where('role', 'bendahara') + ->where('status_akun', 'aktif') + ->exists(); + + if ($sudahAda) { + return back()->withErrors(['bendahara' => 'Nonaktifkan bendahara aktif dulu sebelum membuat akun baru.']); + } + + $request->validate([ + 'name' => 'required|string|max:255', + 'username' => 'required|string|unique:users,username', + 'email' => 'required|email|unique:users,email', + ]); + + User::create([ + 'name' => $request->name, + 'username' => $request->username, + 'email' => $request->email, + 'password' => Hash::make('12345678'), // password default + 'role' => 'bendahara', + 'rt_id' => $rt->id, + 'status_akun' => 'aktif', + 'wajib_ganti_password' => true, + ]); + + return back()->with('success', 'Akun bendahara berhasil dibuat. Password default: 12345678 (wajib diganti saat login pertama).'); + } + + // Nonaktifkan bendahara (bukan hapus) + public function nonaktifkan($id) + { + $rt = Auth::user(); + + $bendahara = User::where('id', $id) + ->where('rt_id', $rt->id) + ->where('role', 'bendahara') + ->firstOrFail(); + + $bendahara->update(['status_akun' => 'nonaktif']); + + return back()->with('success', 'Akun bendahara berhasil dinonaktifkan.'); + } +} diff --git a/.history/app/Http/Controllers/RT/BendaharaController_20260619110051.php b/.history/app/Http/Controllers/RT/BendaharaController_20260619110051.php new file mode 100644 index 0000000..452a22e --- /dev/null +++ b/.history/app/Http/Controllers/RT/BendaharaController_20260619110051.php @@ -0,0 +1,76 @@ +id) + ->where('role', 'bendahara') + ->orderBy('created_at', 'desc') + ->get(); + + $bendaharaAktif = $bendaharas->where('status_akun', 'aktif')->first(); + + return view('rt.bendahara.index', compact('bendaharas', 'bendaharaAktif')); + } + + // Simpan akun bendahara baru + public function store(Request $request) + { + $rt = Auth::user(); + + // Cek apakah RT sudah punya bendahara aktif + $sudahAda = User::where('rt_id', $rt->id) + ->where('role', 'bendahara') + ->where('status_akun', 'aktif') + ->exists(); + + if ($sudahAda) { + return back()->withErrors(['bendahara' => 'Nonaktifkan bendahara aktif dulu sebelum membuat akun baru.']); + } + + $request->validate([ + 'name' => 'required|string|max:255', + 'username' => 'required|string|unique:users,username', + 'email' => 'required|email|unique:users,email', + ]); + + User::create([ + 'name' => $request->name, + 'username' => $request->username, + 'email' => $request->email, + 'password' => Hash::make('12345678'), // password default + 'role' => 'bendahara', + 'rt_id' => $rt->id, + 'status_akun' => 'aktif', + 'wajib_ganti_password' => true, + ]); + + return back()->with('success', 'Akun bendahara berhasil dibuat. Password default: 12345678 (wajib diganti saat login pertama).'); + } + + // Nonaktifkan bendahara (bukan hapus) + public function nonaktifkan($id) + { + $rt = Auth::user(); + + $bendahara = User::where('id', $id) + ->where('rt_id', $rt->id) + ->where('role', 'bendahara') + ->firstOrFail(); + + $bendahara->update(['status_akun' => 'nonaktif']); + + return back()->with('success', 'Akun bendahara berhasil dinonaktifkan.'); + } +} diff --git a/.history/app/Http/Controllers/RT/KasController_20260619185519.php b/.history/app/Http/Controllers/RT/KasController_20260619185519.php new file mode 100644 index 0000000..e69de29 diff --git a/.history/app/Http/Controllers/RT/KasController_20260619185522.php b/.history/app/Http/Controllers/RT/KasController_20260619185522.php new file mode 100644 index 0000000..13d1e6a --- /dev/null +++ b/.history/app/Http/Controllers/RT/KasController_20260619185522.php @@ -0,0 +1,27 @@ +id) + ->orderBy('created_at', 'asc') + ->get(); + + $totalMasuk = $kas->where('jenis', 'masuk')->sum('jumlah'); + $totalKeluar = $kas->where('jenis', 'keluar')->sum('jumlah'); + $saldo = $totalMasuk - $totalKeluar; + + $kas = $kas->sortByDesc('created_at'); + + return view('rt.kas.index', compact('kas', 'totalMasuk', 'totalKeluar', 'saldo')); + } +} diff --git a/.history/app/Http/Controllers/RT/KasController_20260619185527.php b/.history/app/Http/Controllers/RT/KasController_20260619185527.php new file mode 100644 index 0000000..13d1e6a --- /dev/null +++ b/.history/app/Http/Controllers/RT/KasController_20260619185527.php @@ -0,0 +1,27 @@ +id) + ->orderBy('created_at', 'asc') + ->get(); + + $totalMasuk = $kas->where('jenis', 'masuk')->sum('jumlah'); + $totalKeluar = $kas->where('jenis', 'keluar')->sum('jumlah'); + $saldo = $totalMasuk - $totalKeluar; + + $kas = $kas->sortByDesc('created_at'); + + return view('rt.kas.index', compact('kas', 'totalMasuk', 'totalKeluar', 'saldo')); + } +} diff --git a/.history/app/Http/Controllers/RT/KasController_20260619191405.php b/.history/app/Http/Controllers/RT/KasController_20260619191405.php new file mode 100644 index 0000000..13d1e6a --- /dev/null +++ b/.history/app/Http/Controllers/RT/KasController_20260619191405.php @@ -0,0 +1,27 @@ +id) + ->orderBy('created_at', 'asc') + ->get(); + + $totalMasuk = $kas->where('jenis', 'masuk')->sum('jumlah'); + $totalKeluar = $kas->where('jenis', 'keluar')->sum('jumlah'); + $saldo = $totalMasuk - $totalKeluar; + + $kas = $kas->sortByDesc('created_at'); + + return view('rt.kas.index', compact('kas', 'totalMasuk', 'totalKeluar', 'saldo')); + } +} diff --git a/.history/app/Http/Controllers/RT/KasRTController_20260619191404.php b/.history/app/Http/Controllers/RT/KasRTController_20260619191404.php new file mode 100644 index 0000000..13d1e6a --- /dev/null +++ b/.history/app/Http/Controllers/RT/KasRTController_20260619191404.php @@ -0,0 +1,27 @@ +id) + ->orderBy('created_at', 'asc') + ->get(); + + $totalMasuk = $kas->where('jenis', 'masuk')->sum('jumlah'); + $totalKeluar = $kas->where('jenis', 'keluar')->sum('jumlah'); + $saldo = $totalMasuk - $totalKeluar; + + $kas = $kas->sortByDesc('created_at'); + + return view('rt.kas.index', compact('kas', 'totalMasuk', 'totalKeluar', 'saldo')); + } +} diff --git a/.history/app/Http/Controllers/RT/KasRTController_20260620081459.php b/.history/app/Http/Controllers/RT/KasRTController_20260620081459.php new file mode 100644 index 0000000..e15b479 --- /dev/null +++ b/.history/app/Http/Controllers/RT/KasRTController_20260620081459.php @@ -0,0 +1,27 @@ +id) + ->orderBy('created_at', 'asc') + ->get(); + + $kasTerhitung = $kas->whereIn('status', ['manual', 'lunas']); + + $totalMasuk = $kasTerhitung->where('jenis', 'masuk')->sum('jumlah'); + $totalKeluar = $kasTerhitung->where('jenis', 'keluar')->sum('jumlah'); + $saldo = $totalMasuk - $totalKeluar; + + return view('rt.kas.index', compact('kas', 'totalMasuk', 'totalKeluar', 'saldo')); + } +} diff --git a/.history/app/Http/Controllers/RT/KasRTController_20260620081519.php b/.history/app/Http/Controllers/RT/KasRTController_20260620081519.php new file mode 100644 index 0000000..13d1e6a --- /dev/null +++ b/.history/app/Http/Controllers/RT/KasRTController_20260620081519.php @@ -0,0 +1,27 @@ +id) + ->orderBy('created_at', 'asc') + ->get(); + + $totalMasuk = $kas->where('jenis', 'masuk')->sum('jumlah'); + $totalKeluar = $kas->where('jenis', 'keluar')->sum('jumlah'); + $saldo = $totalMasuk - $totalKeluar; + + $kas = $kas->sortByDesc('created_at'); + + return view('rt.kas.index', compact('kas', 'totalMasuk', 'totalKeluar', 'saldo')); + } +} diff --git a/.history/app/Http/Controllers/RT/KasRTController_20260620081649.php b/.history/app/Http/Controllers/RT/KasRTController_20260620081649.php new file mode 100644 index 0000000..e15b479 --- /dev/null +++ b/.history/app/Http/Controllers/RT/KasRTController_20260620081649.php @@ -0,0 +1,27 @@ +id) + ->orderBy('created_at', 'asc') + ->get(); + + $kasTerhitung = $kas->whereIn('status', ['manual', 'lunas']); + + $totalMasuk = $kasTerhitung->where('jenis', 'masuk')->sum('jumlah'); + $totalKeluar = $kasTerhitung->where('jenis', 'keluar')->sum('jumlah'); + $saldo = $totalMasuk - $totalKeluar; + + return view('rt.kas.index', compact('kas', 'totalMasuk', 'totalKeluar', 'saldo')); + } +} diff --git a/.history/app/Http/Controllers/RT/KasRTController_20260620082003.php b/.history/app/Http/Controllers/RT/KasRTController_20260620082003.php new file mode 100644 index 0000000..13d1e6a --- /dev/null +++ b/.history/app/Http/Controllers/RT/KasRTController_20260620082003.php @@ -0,0 +1,27 @@ +id) + ->orderBy('created_at', 'asc') + ->get(); + + $totalMasuk = $kas->where('jenis', 'masuk')->sum('jumlah'); + $totalKeluar = $kas->where('jenis', 'keluar')->sum('jumlah'); + $saldo = $totalMasuk - $totalKeluar; + + $kas = $kas->sortByDesc('created_at'); + + return view('rt.kas.index', compact('kas', 'totalMasuk', 'totalKeluar', 'saldo')); + } +} diff --git a/.history/app/Http/Controllers/RT/KasRTController_20260620082010.php b/.history/app/Http/Controllers/RT/KasRTController_20260620082010.php new file mode 100644 index 0000000..90aa3f1 --- /dev/null +++ b/.history/app/Http/Controllers/RT/KasRTController_20260620082010.php @@ -0,0 +1,27 @@ +id) + ->orderBy('created_at', 'asc') + ->get(); + + $kasTerhitung = $kas->whereIn('status', ['manual', 'lunas']); + + $totalMasuk = $kasTerhitung->where('jenis', 'masuk')->sum('jumlah'); + $totalKeluar = $kasTerhitung->where('jenis', 'keluar')->sum('jumlah'); + $saldo = $totalMasuk - $totalKeluar; + + return view('rt.kas.index', compact('kas', 'totalMasuk', 'totalKeluar', 'saldo')); + } +} diff --git a/.history/app/Http/Controllers/RT/KasRTController_20260620082012.php b/.history/app/Http/Controllers/RT/KasRTController_20260620082012.php new file mode 100644 index 0000000..13d1e6a --- /dev/null +++ b/.history/app/Http/Controllers/RT/KasRTController_20260620082012.php @@ -0,0 +1,27 @@ +id) + ->orderBy('created_at', 'asc') + ->get(); + + $totalMasuk = $kas->where('jenis', 'masuk')->sum('jumlah'); + $totalKeluar = $kas->where('jenis', 'keluar')->sum('jumlah'); + $saldo = $totalMasuk - $totalKeluar; + + $kas = $kas->sortByDesc('created_at'); + + return view('rt.kas.index', compact('kas', 'totalMasuk', 'totalKeluar', 'saldo')); + } +} diff --git a/.history/app/Http/Controllers/RT/KasRTController_20260620082018.php b/.history/app/Http/Controllers/RT/KasRTController_20260620082018.php new file mode 100644 index 0000000..90aa3f1 --- /dev/null +++ b/.history/app/Http/Controllers/RT/KasRTController_20260620082018.php @@ -0,0 +1,27 @@ +id) + ->orderBy('created_at', 'asc') + ->get(); + + $kasTerhitung = $kas->whereIn('status', ['manual', 'lunas']); + + $totalMasuk = $kasTerhitung->where('jenis', 'masuk')->sum('jumlah'); + $totalKeluar = $kasTerhitung->where('jenis', 'keluar')->sum('jumlah'); + $saldo = $totalMasuk - $totalKeluar; + + return view('rt.kas.index', compact('kas', 'totalMasuk', 'totalKeluar', 'saldo')); + } +} diff --git a/.history/app/Http/Controllers/RT/ReviewIuranController_20260619091258.php b/.history/app/Http/Controllers/RT/ReviewIuranController_20260619091258.php new file mode 100644 index 0000000..e69de29 diff --git a/.history/app/Http/Controllers/RT/ReviewIuranController_20260619091314.php b/.history/app/Http/Controllers/RT/ReviewIuranController_20260619091314.php new file mode 100644 index 0000000..a0d2108 --- /dev/null +++ b/.history/app/Http/Controllers/RT/ReviewIuranController_20260619091314.php @@ -0,0 +1,61 @@ +id) + ->where('status', 'diajukan') + ->orderBy('created_at', 'desc') + ->get(); + + return view('rt.review-iuran.index', compact('iurans')); + } + + // RT setujui -> status jadi 'aktif' (tampil ke penghuni) + public function setujui($id) + { + $rt = Auth::user(); + + $iuran = Iuran::where('id', $id) + ->where('rt_id', $rt->id) + ->where('status', 'diajukan') + ->firstOrFail(); + + $iuran->update(['status' => 'aktif']); + + return back()->with('success', 'Iuran disetujui dan tampil ke penghuni.'); + } + + // RT tolak -> status jadi 'ditolak' + catatan alasan + public function tolak(Request $request, $id) + { + $rt = Auth::user(); + + $request->validate([ + 'catatan_rt' => 'required|string', + ]); + + $iuran = Iuran::where('id', $id) + ->where('rt_id', $rt->id) + ->where('status', 'diajukan') + ->firstOrFail(); + + $iuran->update([ + 'status' => 'ditolak', + 'catatan_rt' => $request->catatan_rt, + ]); + + return back()->with('success', 'Iuran ditolak, bendahara akan diminta merevisi.'); + } +} diff --git a/.history/app/Http/Controllers/RT/ReviewIuranController_20260619115439.php b/.history/app/Http/Controllers/RT/ReviewIuranController_20260619115439.php new file mode 100644 index 0000000..cadf419 --- /dev/null +++ b/.history/app/Http/Controllers/RT/ReviewIuranController_20260619115439.php @@ -0,0 +1,76 @@ +id) + ->where('status', 'diajukan') + ->orderBy('created_at', 'desc') + ->get(); + + return view('rt.review-iuran.index', compact('iurans')); + } + + // RT setujui -> status jadi 'aktif' (tampil ke penghuni) + public function setujui($id) + { + $rt = Auth::user(); + + $iuran = Iuran::where('id', $id) + ->where('rt_id', $rt->id) + ->where('status', 'diajukan') + ->firstOrFail(); + + $iuran->update(['status' => 'aktif']); + + // Kirim notifikasi WhatsApp ke penghuni + $penghuni = $iuran->penghuni; + + if ($penghuni && $penghuni->telepon) { + $pesan = "Halo {$penghuni->nama},\n"; + $pesan .= "Iuran Anda telah *disetujui RT* dan siap dibayar:\n"; + $pesan .= "Bulan: {$iuran->bulan} {$iuran->tahun}\n"; + $pesan .= "Jumlah: Rp " . number_format($iuran->jumlah, 0, ',', '.') . "\n"; + $pesan .= "Jenis: {$iuran->jenis_iuran}\n"; + $pesan .= "Silakan lakukan pembayaran melalui aplikasi.\n"; + $pesan .= "Terima kasih 🙏"; + + WhatsappService::send($penghuni->telepon, $pesan); + } + + return back()->with('success', 'Iuran disetujui dan tampil ke penghuni.'); + } + + // RT tolak -> status jadi 'ditolak' + catatan alasan + public function tolak(Request $request, $id) + { + $rt = Auth::user(); + + $request->validate([ + 'catatan_rt' => 'required|string', + ]); + + $iuran = Iuran::where('id', $id) + ->where('rt_id', $rt->id) + ->where('status', 'diajukan') + ->firstOrFail(); + + $iuran->update([ + 'status' => 'ditolak', + 'catatan_rt' => $request->catatan_rt, + ]); + + return back()->with('success', 'Iuran ditolak, bendahara akan diminta merevisi.'); + } +} diff --git a/.history/app/Http/Controllers/RT/ReviewIuranController_20260619115450.php b/.history/app/Http/Controllers/RT/ReviewIuranController_20260619115450.php new file mode 100644 index 0000000..aeba9d1 --- /dev/null +++ b/.history/app/Http/Controllers/RT/ReviewIuranController_20260619115450.php @@ -0,0 +1,77 @@ +id) + ->where('status', 'diajukan') + ->orderBy('created_at', 'desc') + ->get(); + + return view('rt.review-iuran.index', compact('iurans')); + } + + // RT setujui -> status jadi 'aktif' (tampil ke penghuni) + public function setujui($id) + { + $rt = Auth::user(); + + $iuran = Iuran::where('id', $id) + ->where('rt_id', $rt->id) + ->where('status', 'diajukan') + ->firstOrFail(); + + $iuran->update(['status' => 'aktif']); + + // Kirim notifikasi WhatsApp ke penghuni + $penghuni = $iuran->penghuni; + + if ($penghuni && $penghuni->telepon) { + $pesan = "Halo {$penghuni->nama},\n"; + $pesan .= "Iuran Anda telah *disetujui RT* dan siap dibayar:\n"; + $pesan .= "Bulan: {$iuran->bulan} {$iuran->tahun}\n"; + $pesan .= "Jumlah: Rp " . number_format($iuran->jumlah, 0, ',', '.') . "\n"; + $pesan .= "Jenis: {$iuran->jenis_iuran}\n"; + $pesan .= "Silakan lakukan pembayaran melalui aplikasi.\n"; + $pesan .= "Terima kasih 🙏"; + + WhatsappService::send($penghuni->telepon, $pesan); + } + + return back()->with('success', 'Iuran disetujui dan tampil ke penghuni.'); + } + + // RT tolak -> status jadi 'ditolak' + catatan alasan + public function tolak(Request $request, $id) + { + $rt = Auth::user(); + + $request->validate([ + 'catatan_rt' => 'required|string', + ]); + + $iuran = Iuran::where('id', $id) + ->where('rt_id', $rt->id) + ->where('status', 'diajukan') + ->firstOrFail(); + + $iuran->update([ + 'status' => 'ditolak', + 'catatan_rt' => $request->catatan_rt, + ]); + + return back()->with('success', 'Iuran ditolak, bendahara akan diminta merevisi.'); + } +} diff --git a/.history/app/Http/Controllers/RT/ReviewRekapController_20260619095716.php b/.history/app/Http/Controllers/RT/ReviewRekapController_20260619095716.php new file mode 100644 index 0000000..e69de29 diff --git a/.history/app/Http/Controllers/RT/ReviewRekapController_20260619095826.php b/.history/app/Http/Controllers/RT/ReviewRekapController_20260619095826.php new file mode 100644 index 0000000..217e226 --- /dev/null +++ b/.history/app/Http/Controllers/RT/ReviewRekapController_20260619095826.php @@ -0,0 +1,82 @@ +id) + ->where('status', 'diajukan') + ->orderBy('created_at', 'desc') + ->get(); + + return view('rt.review-rekap.index', compact('rekaps')); + } + + // Lihat detail isi rekap sebelum setuju/tolak + public function show($id) + { + $rt = Auth::user(); + + $rekap = RekapIuran::where('id', $id) + ->where('rt_id', $rt->id) + ->with('iurans.penghuni', 'bendahara') + ->firstOrFail(); + + return view('rt.review-rekap.show', compact('rekap')); + } + + // RT setujui -> semua iuran di rekap ini otomatis jadi 'lunas' + public function setujui($id) + { + $rt = Auth::user(); + + $rekap = RekapIuran::where('id', $id) + ->where('rt_id', $rt->id) + ->where('status', 'diajukan') + ->firstOrFail(); + + $rekap->update(['status' => 'disetujui']); + + $rekap->iurans()->update([ + 'status' => 'lunas', + 'tanggal_bayar' => now(), + ]); + + return redirect()->route('rt.review-rekap.index')->with('success', 'Rekap disetujui, semua iuran di dalamnya jadi lunas.'); + } + + // RT tolak -> rekap_id dilepas dari semua iuran, supaya bisa direkap ulang + public function tolak(Request $request, $id) + { + $rt = Auth::user(); + + $request->validate([ + 'catatan_rt' => 'required|string', + ]); + + $rekap = RekapIuran::where('id', $id) + ->where('rt_id', $rt->id) + ->where('status', 'diajukan') + ->firstOrFail(); + + // Lepas rekap_id dari semua iuran di dalamnya + $rekap->iurans()->update(['rekap_id' => null]); + + $rekap->update([ + 'status' => 'ditolak', + 'catatan_rt' => $request->catatan_rt, + ]); + + return redirect()->route('rt.review-rekap.index')->with('success', 'Rekap ditolak, iuran dikembalikan untuk direkap ulang.'); + } +} diff --git a/.history/app/Http/Controllers/RT/ReviewRekapController_20260619095848.php b/.history/app/Http/Controllers/RT/ReviewRekapController_20260619095848.php new file mode 100644 index 0000000..0565ab3 --- /dev/null +++ b/.history/app/Http/Controllers/RT/ReviewRekapController_20260619095848.php @@ -0,0 +1,83 @@ +id) + ->where('status', 'diajukan') + ->orderBy('created_at', 'desc') + ->get(); + + return view('rt.review-rekap.index', compact('rekaps')); + } + + // Lihat detail isi rekap sebelum setuju/tolak + public function show($id) + { + $rt = Auth::user(); + + $rekap = RekapIuran::where('id', $id) + ->where('rt_id', $rt->id) + ->with('iurans.penghuni', 'bendahara') + ->firstOrFail(); + + return view('rt.review-rekap.show', compact('rekap')); + } + + // RT setujui -> semua iuran di rekap ini otomatis jadi 'lunas' + public function setujui($id) + { + $rt = Auth::user(); + + $rekap = RekapIuran::where('id', $id) + ->where('rt_id', $rt->id) + ->where('status', 'diajukan') + ->firstOrFail(); + + $rekap->update(['status' => 'disetujui']); + + $rekap->iurans()->update([ + 'status' => 'lunas', + 'tanggal_bayar' => now(), + ]); + + return redirect()->route('rt.review-rekap.index')->with('success', 'Rekap disetujui, semua iuran di dalamnya jadi lunas.'); + } + + // RT tolak -> rekap_id dilepas dari semua iuran, supaya bisa direkap ulang + public function tolak(Request $request, $id) + { + $rt = Auth::user(); + + $request->validate([ + 'catatan_rt' => 'required|string', + ]); + + $rekap = RekapIuran::where('id', $id) + ->where('rt_id', $rt->id) + ->where('status', 'diajukan') + ->firstOrFail(); + + // Lepas rekap_id dari semua iuran di dalamnya + $rekap->iurans()->update(['rekap_id' => null]); + + $rekap->update([ + 'status' => 'ditolak', + 'catatan_rt' => $request->catatan_rt, + ]); + + return redirect()->route('rt.review-rekap.index')->with('success', 'Rekap ditolak, iuran dikembalikan untuk direkap ulang.'); + } +} diff --git a/.history/app/Http/Controllers/RT/ReviewRekapController_20260619095852.php b/.history/app/Http/Controllers/RT/ReviewRekapController_20260619095852.php new file mode 100644 index 0000000..217e226 --- /dev/null +++ b/.history/app/Http/Controllers/RT/ReviewRekapController_20260619095852.php @@ -0,0 +1,82 @@ +id) + ->where('status', 'diajukan') + ->orderBy('created_at', 'desc') + ->get(); + + return view('rt.review-rekap.index', compact('rekaps')); + } + + // Lihat detail isi rekap sebelum setuju/tolak + public function show($id) + { + $rt = Auth::user(); + + $rekap = RekapIuran::where('id', $id) + ->where('rt_id', $rt->id) + ->with('iurans.penghuni', 'bendahara') + ->firstOrFail(); + + return view('rt.review-rekap.show', compact('rekap')); + } + + // RT setujui -> semua iuran di rekap ini otomatis jadi 'lunas' + public function setujui($id) + { + $rt = Auth::user(); + + $rekap = RekapIuran::where('id', $id) + ->where('rt_id', $rt->id) + ->where('status', 'diajukan') + ->firstOrFail(); + + $rekap->update(['status' => 'disetujui']); + + $rekap->iurans()->update([ + 'status' => 'lunas', + 'tanggal_bayar' => now(), + ]); + + return redirect()->route('rt.review-rekap.index')->with('success', 'Rekap disetujui, semua iuran di dalamnya jadi lunas.'); + } + + // RT tolak -> rekap_id dilepas dari semua iuran, supaya bisa direkap ulang + public function tolak(Request $request, $id) + { + $rt = Auth::user(); + + $request->validate([ + 'catatan_rt' => 'required|string', + ]); + + $rekap = RekapIuran::where('id', $id) + ->where('rt_id', $rt->id) + ->where('status', 'diajukan') + ->firstOrFail(); + + // Lepas rekap_id dari semua iuran di dalamnya + $rekap->iurans()->update(['rekap_id' => null]); + + $rekap->update([ + 'status' => 'ditolak', + 'catatan_rt' => $request->catatan_rt, + ]); + + return redirect()->route('rt.review-rekap.index')->with('success', 'Rekap ditolak, iuran dikembalikan untuk direkap ulang.'); + } +} diff --git a/.history/app/Http/Controllers/RT/ReviewRekapController_20260619101839.php b/.history/app/Http/Controllers/RT/ReviewRekapController_20260619101839.php new file mode 100644 index 0000000..c38a3f3 --- /dev/null +++ b/.history/app/Http/Controllers/RT/ReviewRekapController_20260619101839.php @@ -0,0 +1,82 @@ +id) + ->where('status', 'diajukan') + ->orderBy('created_at', 'desc') + ->get(); + + return view('rt.review-rekap.index', compact('rekaps')); + } + + // Lihat detail isi rekap sebelum setuju/tolak + public function show($id) + { + $rt = Auth::user(); + + $rekap = RekapIuran::where('id', $id) + ->where('rt_id', $rt->id) + ->with('iurans.penghuni', 'bendahara') + ->firstOrFail(); + + return view('rt.review-rekap.show', compact('rekap')); + } + + // RT setujui -> semua iuran di rekap ini otomatis jadi 'lunas' + public function setujui($id) + { + $rt = Auth::user(); + + $rekap = RekapIuran::where('id', $id) + ->where('rt_id', $rt->id) + ->where('status', 'diajukan') + ->firstOrFail(); + + $rekap->update(['status' => 'disetujui']); + + $rekap->iurans()->update([ + 'status' => 'lunas', + 'tanggal_bayar' => now(), + ]); + + return redirect()->route('rt.review-rekap.index')->with('success', 'Rekap disetujui, semua iuran di dalamnya jadi lunas.'); + } + + // RT tolak -> rekap_id dilepas dari semua iuran, supaya bisa direkap ulang + public function tolak(Request $request, $id) + { + $rt = Auth::user(); + + $request->validate([ + 'catatan_rt' => 'required|string', + ]); + + $rekap = RekapIuran::where('id', $id) + ->where('rt_id', $rt->id) + ->where('status', 'diajukan') + ->firstOrFail(); + + // Lepas rekap_id dari semua iuran di dalamnya + $rekap->iurans()->update(['rekap_id' => null]); + + $rekap->update([ + 'status' => 'ditolak', + 'catatan_rt' => $request->catatan_rt, + ]); + + return redirect()->route('rt.review-rekap.index')->with('success', 'Rekap ditolak, iuran dikembalikan untuk direkap ulang.'); + } +} diff --git a/.history/app/Http/Controllers/RT/ReviewRekapController_20260619101840.php b/.history/app/Http/Controllers/RT/ReviewRekapController_20260619101840.php new file mode 100644 index 0000000..f8b068d --- /dev/null +++ b/.history/app/Http/Controllers/RT/ReviewRekapController_20260619101840.php @@ -0,0 +1,82 @@ +id) + ->where('status', 'diajukan') + ->orderBy('created_at', 'desc') + ->get(); + + return view('rt.review-rekap.index', compact('rekaps')); + } + + // Lihat detail isi rekap sebelum setuju/tolak + public function show($id) + { + $rt = Auth::user(); + + $rekap = RekapIuran::where('id', $id) + ->where('rt_id', $rt->id) + ->with('iurans.penghuni', 'bendahara') + ->firstOrFail(); + + return view('rt.review-rekap.show', compact('rekap')); + } + + // RT setujui -> semua iuran di rekap ini otomatis jadi 'lunas' + public function setujui($id) + { + $rt = Auth::user(); + + $rekap = RekapIuran::where('id', $id) + ->where('rt_id', $rt->id) + ->where('status', 'diajukan') + ->firstOrFail(); + + $rekap->update(['status' => 'disetujui']); + + $rekap->iurans()->update([ + 'status' => 'lunas', + 'tanggal_bayar' => now(), + ]); + + return redirect()->route('rt.review-rekap.index')->with('success', 'Rekap disetujui, semua iuran di dalamnya jadi lunas.'); + } + + // RT tolak -> rekap_id dilepas dari semua iuran, supaya bisa direkap ulang + public function tolak(Request $request, $id) + { + $rt = Auth::user(); + + $request->validate([ + 'catatan_rt' => 'required|string', + ]); + + $rekap = RekapIuran::where('id', $id) + ->where('rt_id', $rt->id) + ->where('status', 'diajukan') + ->firstOrFail(); + + // Lepas rekap_id dari semua iuran di dalamnya + $rekap->iurans()->update(['rekap_id' => null]); + + $rekap->update([ + 'status' => 'ditolak', + 'catatan_rt' => $request->catatan_rt, + ]); + + return redirect()->route('rt.review-rekap.index')->with('success', 'Rekap ditolak, iuran dikembalikan untuk direkap ulang.'); + } +} diff --git a/.history/app/Http/Controllers/RT/ReviewRekapController_20260619101847.php b/.history/app/Http/Controllers/RT/ReviewRekapController_20260619101847.php new file mode 100644 index 0000000..ca72d04 --- /dev/null +++ b/.history/app/Http/Controllers/RT/ReviewRekapController_20260619101847.php @@ -0,0 +1,81 @@ +id) + ->where('status', 'diajukan') + ->orderBy('created_at', 'desc') + ->get(); + + return view('rt.review-rekap.index', compact('rekaps')); + } + + // Lihat detail isi rekap sebelum setuju/tolak + public function show($id) + { + $rt = Auth::user(); + + $rekap = RekapIuran::where('id', $id) + ->where('rt_id', $rt->id) + ->with('iurans.penghuni', 'bendahara') + ->firstOrFail(); + + return view('rt.review-rekap.show', compact('rekap')); + } + + // RT setujui -> semua iuran di rekap ini otomatis jadi 'lunas' + public function setujui($id) + { + $rt = Auth::user(); + + $rekap = RekapIuran::where('id', $id) + ->where('rt_id', $rt->id) + ->where('status', 'diajukan') + ->firstOrFail(); + + $rekap->update(['status' => 'disetujui']); + + $rekap->iurans()->update([ + 'status' => 'lunas', + 'tanggal_bayar' => now(), + ]); + + return redirect()->route('rt.review-rekap.index')->with('success', 'Rekap disetujui, semua iuran di dalamnya jadi lunas.'); + } + + // RT tolak -> rekap_id dilepas dari semua iuran, supaya bisa direkap ulang + public function tolak(Request $request, $id) + { + $rt = Auth::user(); + + $request->validate([ + 'catatan_rt' => 'required|string', + ]); + + $rekap = RekapIuran::where('id', $id) + ->where('rt_id', $rt->id) + ->where('status', 'diajukan') + ->firstOrFail(); + + // Lepas rekap_id dari semua iuran di dalamnya + $rekap->iurans()->update(['rekap_id' => null]); + + $rekap->update([ + 'status' => 'ditolak', + 'catatan_rt' => $request->catatan_rt, + ]); + + return redirect()->route('rt.review-rekap.index')->with('success', 'Rekap ditolak, iuran dikembalikan untuk direkap ulang.'); + } +} diff --git a/.history/app/Http/Controllers/RT/ReviewRekapController_20260620132653.php b/.history/app/Http/Controllers/RT/ReviewRekapController_20260620132653.php new file mode 100644 index 0000000..f0d5006 --- /dev/null +++ b/.history/app/Http/Controllers/RT/ReviewRekapController_20260620132653.php @@ -0,0 +1,35 @@ +id) + ->orderBy('created_at', 'desc') + ->get(); + + return view('rt.review-rekap.index', compact('rekaps')); + } + + // Lihat detail isi rekap (read only) + public function show($id) + { + $rt = Auth::user(); + + $rekap = RekapIuran::where('id', $id) + ->where('rt_id', $rt->id) + ->with('iurans.penghuni', 'bendahara') + ->firstOrFail(); + + return view('rt.review-rekap.show', compact('rekap')); + } +} diff --git a/.history/app/Http/Controllers/RT/ReviewRekapController_20260620134923.php b/.history/app/Http/Controllers/RT/ReviewRekapController_20260620134923.php new file mode 100644 index 0000000..09b9503 --- /dev/null +++ b/.history/app/Http/Controllers/RT/ReviewRekapController_20260620134923.php @@ -0,0 +1,78 @@ +id) + ->where('status', 'diajukan') + ->orderBy('created_at', 'desc') + ->get(); + + return view('rt.review-rekap.index', compact('rekaps')); + } + + public function show($id) + { + $rt = Auth::user(); + + $rekap = RekapIuran::where('id', $id) + ->where('rt_id', $rt->id) + ->with('iurans.penghuni', 'bendahara') + ->firstOrFail(); + + return view('rt.review-rekap.show', compact('rekap')); + } + + // RT setujui -> rekap selesai, iuran TETAP lunas (sudah lunas duluan dari bendahara) + public function setujui($id) + { + $rt = Auth::user(); + + $rekap = RekapIuran::where('id', $id) + ->where('rt_id', $rt->id) + ->where('status', 'diajukan') + ->firstOrFail(); + + $rekap->update(['status' => 'disetujui']); + + return redirect()->route('rt.review-rekap.index')->with('success', 'Rekap disetujui.'); + } + + // RT tolak -> rekap_id dilepas, iuran balik jadi 'menunggu' lagi + public function tolak(Request $request, $id) + { + $rt = Auth::user(); + + $request->validate([ + 'catatan_rt' => 'required|string', + ]); + + $rekap = RekapIuran::where('id', $id) + ->where('rt_id', $rt->id) + ->where('status', 'diajukan') + ->firstOrFail(); + + // Lepas rekap_id + balikin status iuran jadi 'menunggu' + $rekap->iurans()->update([ + 'rekap_id' => null, + 'status' => 'menunggu', + ]); + + $rekap->update([ + 'status' => 'ditolak', + 'catatan_rt' => $request->catatan_rt, + ]); + + return redirect()->route('rt.review-rekap.index')->with('success', 'Rekap ditolak, iuran dikembalikan ke bendahara.'); + } +} diff --git a/.history/app/Http/Controllers/UserController_20260505205724.php b/.history/app/Http/Controllers/UserController_20260505205724.php new file mode 100644 index 0000000..a7dc7cc --- /dev/null +++ b/.history/app/Http/Controllers/UserController_20260505205724.php @@ -0,0 +1,376 @@ +where('email', $user->email) + ->latest() + ->first(); + + $rumah = $penghuni ? $penghuni->rumah : null; + + // 🔥 WAJIB ADA - dipakai di hero stats view + $rumahList = \App\Models\Rumah::all(); + + $rtUser = null; + if ($rumah && $rumah->rt_id) { + $rtUser = \App\Models\User::where('id', $rumah->rt_id)->first(); + } + + $iuran = collect(); + $hidden = session()->get('hidden_iuran', []); + $hiddenLayanan = session()->get('hidden_layanan', []); + + if ($penghuni) { + $iuran = \App\Models\Iuran::where('penghuni_id', $penghuni->id) + ->whereNotIn('id', $hidden) + ->orderBy('tahun', 'desc') + ->orderBy('bulan', 'asc') + ->get(); + } + + $pengaduan = collect(); + $informasi = \App\Models\Informasi::orderBy('is_penting', 'desc') + ->orderBy('tanggal', 'desc') + ->get(); + + if ($penghuni) { + $pengaduan = \App\Models\Layanan::where('penghuni_id', $penghuni->id) + ->whereNotIn('id', $hiddenLayanan) + ->latest() + ->get(); + } + + $isExpired = false; + if ($penghuni && $penghuni->status == 'Tidak Aktif') { + $isExpired = true; + } + + return view('user.home', compact( + 'penghuni', 'rumah', 'rumahList', 'rtUser', + 'iuran', 'pengaduan', 'informasi', 'isExpired' + )); +} + // ========================= + // PROFIL + // ========================= + public function profil() + { + $penghuni = Penghuni::where('email', Auth::user()->email)->first(); + return view('user.profile.edit', compact('penghuni')); + } + + public function updateProfil(Request $request) + { + $penghuni = Penghuni::where('email', Auth::user()->email)->first(); + + $penghuni->update([ + 'nama' => $request->nama, + 'telepon' => $request->telepon, + 'alamat' => $request->alamat, + ]); + + return back()->with('success', 'Profil berhasil diupdate'); + } + + // ========================= + // RUMAH + // ========================= +public function rumah() +{ + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::with('rumah') + ->where('email', $user->email) // 🔥 BY EMAIL, BUKAN user_id + ->latest() + ->first(); + + $rumah = $penghuni ? $penghuni->rumah : null; + + $rtUser = null; + if ($rumah && $rumah->rt_id) { + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + $rumahList = \App\Models\Rumah::all(); + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser', 'rumahList')); +} + // ========================= + // 🔥 TAMBAHAN: PILIH RUMAH + // ========================= +public function pilihRumah($id) +{ + $user = Auth::user(); + + $rumah = \App\Models\Rumah::findOrFail($id); + + // ❌ kalau rumah sudah terisi + if ($rumah->status == 'Terisi') { + return back()->with('error', 'Rumah sudah diambil!'); + } + + // 🔥 cari penghuni berdasarkan EMAIL ATAU USER_ID + $penghuni = \App\Models\Penghuni::where('user_id', $user->id) + ->orWhere('email', $user->email) + ->first(); + + // 🔥 kalau belum ada sama sekali + if (!$penghuni) { + $penghuni = new \App\Models\Penghuni(); + } + + // 🔥 SET DATA WAJIB (update juga kalau sudah ada) + $penghuni->user_id = $user->id; + $penghuni->nama = $user->name; + // $penghuni->no_ktp = $user->no_ktp ?? '-'; + $penghuni->email = $user->email; + // $penghuni->telepon = $user->telepon ?? 'Belum diisi'; + // $penghuni->alamat = $user->alamat ?? 'Belum diisi'; + $penghuni->status = 'Aktif'; + $penghuni->status_huni = 'Tetap'; + + // 🔥 kalau belum ada tanggal masuk + if (!$penghuni->tanggal_masuk) { + $penghuni->tanggal_masuk = now(); + } + + // 🔥 SET RUMAH + $penghuni->rumah_id = $rumah->id; + + // ✅ TAMBAHKAN INI (PENTING BANGET) + $penghuni->rt_id = $rumah->rt_id; + + $penghuni->save(); + + // 🔥 UPDATE STATUS RUMAH + $rumah->status = 'Terisi'; + $rumah->save(); + + return redirect()->route('user.rumah')->with('success', 'Berhasil pilih rumah!'); +} + + // // ========================= + // // IURAN + // // ========================= + // public function iuran() + // { + // return view('user.iuran'); + // } + + // // ========================= + // // PENGADUAN + // // ========================= + // public function pengaduan() + // { + // return view('user.pengaduan'); + // } + + // public function storePengaduan(Request $request) + // { + // // sementara dummy dulu + // return back()->with('success', 'Pengaduan berhasil dikirim'); + // } + + // // ========================= + // // PENGUMUMAN + // // ========================= + // public function pengumuman() + // { + // return view('user.pengumuman'); + // } + +public function ambilRumah(Request $request) +{ + $user = Auth::user(); + + $rumah = \App\Models\Rumah::findOrFail($request->rumah_id); + + // 🔥 ambil penghuni yang SUDAH ADA + $penghuni = \App\Models\Penghuni::where('email', $user->email)->first(); + + if (!$penghuni) { + return back()->with('error', 'Data penghuni belum ada!'); + } + + // 🔥 hanya update yang penting saja + $penghuni->user_id = $user->id; // pastikan tidak null + $penghuni->rumah_id = $rumah->id; + $penghuni->rt_id = $rumah->rt_id; + + $penghuni->save(); + + // 🔥 update status rumah + $rumah->status = 'Terisi'; + $rumah->save(); + + return redirect()->route('user.rumah')->with('success', 'Berhasil ambil rumah!'); +} + + public function simpanPenghuni(Request $request) +{ + $request->validate([ + 'nama' => 'required', + 'no_ktp' => 'required', + 'telepon' => 'required', + 'alamat' => 'required', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_keluar' => 'nullable|date' + ]); + + $user = Auth::user(); + + // 🔥 Cek duplikat by EMAIL + if (Penghuni::where('email', $user->email)->exists()) { + return redirect()->route('user.rumah') + ->with('info', 'Data penghuni sudah ada!'); + } + + Penghuni::create([ + 'nama' => $request->nama, + 'email' => $user->email, + 'no_ktp' => $request->no_ktp, + 'telepon' => $request->telepon, + 'alamat' => $request->alamat, + 'status_huni' => $request->status_huni, + 'tanggal_masuk' => now(), + 'tanggal_keluar' => $request->status_huni == 'Kontrak' + ? $request->tanggal_keluar + : null, + 'status' => 'Aktif', + ]); + + // 🔥 REDIRECT KE user.rumah (bukan user.home) + return redirect()->route('user.rumah') + ->with('success', 'Data penghuni berhasil disimpan!'); +} + +// public function ambilRumah(Request $request) +// { +// $request->validate([ +// 'rumah_id' => 'required|exists:rumah,id' +// ]); + +// $rumah = Rumah::findOrFail($request->rumah_id); + +// if ($rumah->status == 'Terisi') { +// return back()->with('error', 'Rumah sudah diambil!'); +// } + +// $penghuni = Penghuni::where('email', Auth::user()->email)->first(); + +// if (!$penghuni) { +// return back()->with('error', 'Isi data penghuni dulu!'); +// } + +// if ($penghuni->rumah_id) { +// return back()->with('error', 'Anda sudah memiliki rumah!'); +// } + +// DB::transaction(function () use ($rumah, $penghuni) { +// $rumah->update(['status' => 'Terisi']); +// $penghuni->update(['rumah_id' => $rumah->id]); +// }); + +// return redirect()->route('user.rumah') +// ->with('success', 'Berhasil mengambil rumah!'); +// } + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + // 🔥 HANDLE FOTO + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + + $file->move(public_path('foto_rumah'), $namaFile); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile // 🔥 INI WAJIB ADA + ]); + + return back()->with('success', 'Rumah berhasil ditambahkan'); + } + + public function updateRumah(Request $request, $id) + { + $rumah = \App\Models\Rumah::findOrFail($id); + + $rumah->update([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + ]); + + return back()->with('success', 'Berhasil update rumah'); + } + + public function detailInformasi($id) + { + $info = Informasi::findOrFail($id); + $info->increment('views'); + + return view('user.informasi.detail', compact('info')); + } + + // ========================= + // UPLOAD PEMBAYARAN + // ========================= + // public function uploadPembayaran() + // { + // return view('user.upload_pembayaran'); + // } + + // // ========================= + // // STATUS PEMBAYARAN + // // ========================= + // public function statusPembayaran() + // { + // return view('user.status_pembayaran'); + // } + + // // ========================= + // // STATUS PENGADUAN + // // ========================= + // public function statusPengaduan() + // { + // return view('user.status_pengaduan'); + // } +} diff --git a/.history/app/Http/Controllers/UserController_20260521214525.php b/.history/app/Http/Controllers/UserController_20260521214525.php new file mode 100644 index 0000000..a82f4cc --- /dev/null +++ b/.history/app/Http/Controllers/UserController_20260521214525.php @@ -0,0 +1,366 @@ +where('email', $user->email) + ->latest() + ->first(); + + $rumah = $penghuni ? $penghuni->rumah : null; + + // 🔥 WAJIB ADA - dipakai di hero stats view + $rumahList = \App\Models\Rumah::all(); + + $rtUser = null; + if ($rumah && $rumah->rt_id) { + $rtUser = \App\Models\User::where('id', $rumah->rt_id)->first(); + } + + $iuran = collect(); + $hidden = session()->get('hidden_iuran', []); + $hiddenLayanan = session()->get('hidden_layanan', []); + + if ($penghuni) { + $iuran = \App\Models\Iuran::where('penghuni_id', $penghuni->id) + ->whereNotIn('id', $hidden) + ->orderBy('tahun', 'desc') + ->orderBy('bulan', 'asc') + ->get(); + } + + $pengaduan = collect(); + $informasi = \App\Models\Informasi::orderBy('is_penting', 'desc') + ->orderBy('tanggal', 'desc') + ->get(); + + if ($penghuni) { + $pengaduan = \App\Models\Layanan::where('penghuni_id', $penghuni->id) + ->whereNotIn('id', $hiddenLayanan) + ->latest() + ->get(); + } + + $isExpired = false; + if ($penghuni && $penghuni->status == 'Tidak Aktif') { + $isExpired = true; + } + + return view('user.home', compact( + 'penghuni', 'rumah', 'rumahList', 'rtUser', + 'iuran', 'pengaduan', 'informasi', 'isExpired' + )); +} + // ========================= + // PROFIL + // ========================= + public function profil() + { + $penghuni = Penghuni::where('email', Auth::user()->email)->first(); + return view('user.profile.edit', compact('penghuni')); + } + + public function updateProfil(Request $request) + { + $penghuni = Penghuni::where('email', Auth::user()->email)->first(); + + $penghuni->update([ + 'nama' => $request->nama, + 'telepon' => $request->telepon, + 'alamat' => $request->alamat, + ]); + + return back()->with('success', 'Profil berhasil diupdate'); + } + + // ========================= + // RUMAH + // ========================= +public function rumah() +{ + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::with('rumah') + ->where('email', $user->email) // 🔥 BY EMAIL, BUKAN user_id + ->latest() + ->first(); + + $rumah = $penghuni ? $penghuni->rumah : null; + + $rtUser = null; + if ($rumah && $rumah->rt_id) { + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + $rumahList = \App\Models\Rumah::all(); + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser', 'rumahList')); +} + // ========================= + // 🔥 TAMBAHAN: PILIH RUMAH + // ========================= +public function pilihRumah($id) +{ + $user = Auth::user(); + + $rumah = \App\Models\Rumah::findOrFail($id); + + if ($rumah->status == 'Terisi') { + return back()->with('error', 'Rumah sudah diambil!'); + } + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id) + ->orWhere('email', $user->email) + ->first(); + + if (!$penghuni) { + $penghuni = new \App\Models\Penghuni(); + $penghuni->status_huni = 'Tetap'; // 🔥 hanya set kalau penghuni BARU + } + + $penghuni->user_id = $user->id; + $penghuni->nama = $user->name; + $penghuni->email = $user->email; + $penghuni->status = 'Aktif'; + + // 🔥 HAPUS baris $penghuni->status_huni = 'Tetap'; yang lama + + if (!$penghuni->tanggal_masuk) { + $penghuni->tanggal_masuk = now(); + } + + $penghuni->rumah_id = $rumah->id; + $penghuni->rt_id = $rumah->rt_id; + + $penghuni->save(); + + $rumah->status = 'Terisi'; + $rumah->save(); + + return redirect()->route('user.rumah')->with('success', 'Berhasil pilih rumah!'); +} + + // // ========================= + // // IURAN + // // ========================= + // public function iuran() + // { + // return view('user.iuran'); + // } + + // // ========================= + // // PENGADUAN + // // ========================= + // public function pengaduan() + // { + // return view('user.pengaduan'); + // } + + // public function storePengaduan(Request $request) + // { + // // sementara dummy dulu + // return back()->with('success', 'Pengaduan berhasil dikirim'); + // } + + // // ========================= + // // PENGUMUMAN + // // ========================= + // public function pengumuman() + // { + // return view('user.pengumuman'); + // } + +public function ambilRumah(Request $request) +{ + $user = Auth::user(); + + $rumah = \App\Models\Rumah::findOrFail($request->rumah_id); + + // 🔥 ambil penghuni yang SUDAH ADA + $penghuni = \App\Models\Penghuni::where('email', $user->email)->first(); + + if (!$penghuni) { + return back()->with('error', 'Data penghuni belum ada!'); + } + + // 🔥 hanya update yang penting saja + $penghuni->user_id = $user->id; // pastikan tidak null + $penghuni->rumah_id = $rumah->id; + $penghuni->rt_id = $rumah->rt_id; + + $penghuni->save(); + + // 🔥 update status rumah + $rumah->status = 'Terisi'; + $rumah->save(); + + return redirect()->route('user.rumah')->with('success', 'Berhasil ambil rumah!'); +} + + public function simpanPenghuni(Request $request) +{ + $request->validate([ + 'nama' => 'required', + 'no_ktp' => 'required', + 'telepon' => 'required', + 'alamat' => 'required', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_keluar' => 'nullable|date' + ]); + + $user = Auth::user(); + + // 🔥 Cek duplikat by EMAIL + if (Penghuni::where('email', $user->email)->exists()) { + return redirect()->route('user.rumah') + ->with('info', 'Data penghuni sudah ada!'); + } + + Penghuni::create([ + 'nama' => $request->nama, + 'email' => $user->email, + 'no_ktp' => $request->no_ktp, + 'telepon' => $request->telepon, + 'alamat' => $request->alamat, + 'status_huni' => $request->status_huni, + 'tanggal_masuk' => now(), + 'tanggal_keluar' => $request->status_huni == 'Kontrak' + ? $request->tanggal_keluar + : null, + 'status' => 'Aktif', + ]); + + // 🔥 REDIRECT KE user.rumah (bukan user.home) + return redirect()->route('user.rumah') + ->with('success', 'Data penghuni berhasil disimpan!'); +} + +// public function ambilRumah(Request $request) +// { +// $request->validate([ +// 'rumah_id' => 'required|exists:rumah,id' +// ]); + +// $rumah = Rumah::findOrFail($request->rumah_id); + +// if ($rumah->status == 'Terisi') { +// return back()->with('error', 'Rumah sudah diambil!'); +// } + +// $penghuni = Penghuni::where('email', Auth::user()->email)->first(); + +// if (!$penghuni) { +// return back()->with('error', 'Isi data penghuni dulu!'); +// } + +// if ($penghuni->rumah_id) { +// return back()->with('error', 'Anda sudah memiliki rumah!'); +// } + +// DB::transaction(function () use ($rumah, $penghuni) { +// $rumah->update(['status' => 'Terisi']); +// $penghuni->update(['rumah_id' => $rumah->id]); +// }); + +// return redirect()->route('user.rumah') +// ->with('success', 'Berhasil mengambil rumah!'); +// } + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + // 🔥 HANDLE FOTO + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + + $file->move(public_path('foto_rumah'), $namaFile); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile // 🔥 INI WAJIB ADA + ]); + + return back()->with('success', 'Rumah berhasil ditambahkan'); + } + + public function updateRumah(Request $request, $id) + { + $rumah = \App\Models\Rumah::findOrFail($id); + + $rumah->update([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + ]); + + return back()->with('success', 'Berhasil update rumah'); + } + + public function detailInformasi($id) + { + $info = Informasi::findOrFail($id); + $info->increment('views'); + + return view('user.informasi.detail', compact('info')); + } + + // ========================= + // UPLOAD PEMBAYARAN + // ========================= + // public function uploadPembayaran() + // { + // return view('user.upload_pembayaran'); + // } + + // // ========================= + // // STATUS PEMBAYARAN + // // ========================= + // public function statusPembayaran() + // { + // return view('user.status_pembayaran'); + // } + + // // ========================= + // // STATUS PENGADUAN + // // ========================= + // public function statusPengaduan() + // { + // return view('user.status_pengaduan'); + // } +} diff --git a/.history/app/Http/Controllers/UserController_20260521214527.php b/.history/app/Http/Controllers/UserController_20260521214527.php new file mode 100644 index 0000000..a7dc7cc --- /dev/null +++ b/.history/app/Http/Controllers/UserController_20260521214527.php @@ -0,0 +1,376 @@ +where('email', $user->email) + ->latest() + ->first(); + + $rumah = $penghuni ? $penghuni->rumah : null; + + // 🔥 WAJIB ADA - dipakai di hero stats view + $rumahList = \App\Models\Rumah::all(); + + $rtUser = null; + if ($rumah && $rumah->rt_id) { + $rtUser = \App\Models\User::where('id', $rumah->rt_id)->first(); + } + + $iuran = collect(); + $hidden = session()->get('hidden_iuran', []); + $hiddenLayanan = session()->get('hidden_layanan', []); + + if ($penghuni) { + $iuran = \App\Models\Iuran::where('penghuni_id', $penghuni->id) + ->whereNotIn('id', $hidden) + ->orderBy('tahun', 'desc') + ->orderBy('bulan', 'asc') + ->get(); + } + + $pengaduan = collect(); + $informasi = \App\Models\Informasi::orderBy('is_penting', 'desc') + ->orderBy('tanggal', 'desc') + ->get(); + + if ($penghuni) { + $pengaduan = \App\Models\Layanan::where('penghuni_id', $penghuni->id) + ->whereNotIn('id', $hiddenLayanan) + ->latest() + ->get(); + } + + $isExpired = false; + if ($penghuni && $penghuni->status == 'Tidak Aktif') { + $isExpired = true; + } + + return view('user.home', compact( + 'penghuni', 'rumah', 'rumahList', 'rtUser', + 'iuran', 'pengaduan', 'informasi', 'isExpired' + )); +} + // ========================= + // PROFIL + // ========================= + public function profil() + { + $penghuni = Penghuni::where('email', Auth::user()->email)->first(); + return view('user.profile.edit', compact('penghuni')); + } + + public function updateProfil(Request $request) + { + $penghuni = Penghuni::where('email', Auth::user()->email)->first(); + + $penghuni->update([ + 'nama' => $request->nama, + 'telepon' => $request->telepon, + 'alamat' => $request->alamat, + ]); + + return back()->with('success', 'Profil berhasil diupdate'); + } + + // ========================= + // RUMAH + // ========================= +public function rumah() +{ + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::with('rumah') + ->where('email', $user->email) // 🔥 BY EMAIL, BUKAN user_id + ->latest() + ->first(); + + $rumah = $penghuni ? $penghuni->rumah : null; + + $rtUser = null; + if ($rumah && $rumah->rt_id) { + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + $rumahList = \App\Models\Rumah::all(); + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser', 'rumahList')); +} + // ========================= + // 🔥 TAMBAHAN: PILIH RUMAH + // ========================= +public function pilihRumah($id) +{ + $user = Auth::user(); + + $rumah = \App\Models\Rumah::findOrFail($id); + + // ❌ kalau rumah sudah terisi + if ($rumah->status == 'Terisi') { + return back()->with('error', 'Rumah sudah diambil!'); + } + + // 🔥 cari penghuni berdasarkan EMAIL ATAU USER_ID + $penghuni = \App\Models\Penghuni::where('user_id', $user->id) + ->orWhere('email', $user->email) + ->first(); + + // 🔥 kalau belum ada sama sekali + if (!$penghuni) { + $penghuni = new \App\Models\Penghuni(); + } + + // 🔥 SET DATA WAJIB (update juga kalau sudah ada) + $penghuni->user_id = $user->id; + $penghuni->nama = $user->name; + // $penghuni->no_ktp = $user->no_ktp ?? '-'; + $penghuni->email = $user->email; + // $penghuni->telepon = $user->telepon ?? 'Belum diisi'; + // $penghuni->alamat = $user->alamat ?? 'Belum diisi'; + $penghuni->status = 'Aktif'; + $penghuni->status_huni = 'Tetap'; + + // 🔥 kalau belum ada tanggal masuk + if (!$penghuni->tanggal_masuk) { + $penghuni->tanggal_masuk = now(); + } + + // 🔥 SET RUMAH + $penghuni->rumah_id = $rumah->id; + + // ✅ TAMBAHKAN INI (PENTING BANGET) + $penghuni->rt_id = $rumah->rt_id; + + $penghuni->save(); + + // 🔥 UPDATE STATUS RUMAH + $rumah->status = 'Terisi'; + $rumah->save(); + + return redirect()->route('user.rumah')->with('success', 'Berhasil pilih rumah!'); +} + + // // ========================= + // // IURAN + // // ========================= + // public function iuran() + // { + // return view('user.iuran'); + // } + + // // ========================= + // // PENGADUAN + // // ========================= + // public function pengaduan() + // { + // return view('user.pengaduan'); + // } + + // public function storePengaduan(Request $request) + // { + // // sementara dummy dulu + // return back()->with('success', 'Pengaduan berhasil dikirim'); + // } + + // // ========================= + // // PENGUMUMAN + // // ========================= + // public function pengumuman() + // { + // return view('user.pengumuman'); + // } + +public function ambilRumah(Request $request) +{ + $user = Auth::user(); + + $rumah = \App\Models\Rumah::findOrFail($request->rumah_id); + + // 🔥 ambil penghuni yang SUDAH ADA + $penghuni = \App\Models\Penghuni::where('email', $user->email)->first(); + + if (!$penghuni) { + return back()->with('error', 'Data penghuni belum ada!'); + } + + // 🔥 hanya update yang penting saja + $penghuni->user_id = $user->id; // pastikan tidak null + $penghuni->rumah_id = $rumah->id; + $penghuni->rt_id = $rumah->rt_id; + + $penghuni->save(); + + // 🔥 update status rumah + $rumah->status = 'Terisi'; + $rumah->save(); + + return redirect()->route('user.rumah')->with('success', 'Berhasil ambil rumah!'); +} + + public function simpanPenghuni(Request $request) +{ + $request->validate([ + 'nama' => 'required', + 'no_ktp' => 'required', + 'telepon' => 'required', + 'alamat' => 'required', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_keluar' => 'nullable|date' + ]); + + $user = Auth::user(); + + // 🔥 Cek duplikat by EMAIL + if (Penghuni::where('email', $user->email)->exists()) { + return redirect()->route('user.rumah') + ->with('info', 'Data penghuni sudah ada!'); + } + + Penghuni::create([ + 'nama' => $request->nama, + 'email' => $user->email, + 'no_ktp' => $request->no_ktp, + 'telepon' => $request->telepon, + 'alamat' => $request->alamat, + 'status_huni' => $request->status_huni, + 'tanggal_masuk' => now(), + 'tanggal_keluar' => $request->status_huni == 'Kontrak' + ? $request->tanggal_keluar + : null, + 'status' => 'Aktif', + ]); + + // 🔥 REDIRECT KE user.rumah (bukan user.home) + return redirect()->route('user.rumah') + ->with('success', 'Data penghuni berhasil disimpan!'); +} + +// public function ambilRumah(Request $request) +// { +// $request->validate([ +// 'rumah_id' => 'required|exists:rumah,id' +// ]); + +// $rumah = Rumah::findOrFail($request->rumah_id); + +// if ($rumah->status == 'Terisi') { +// return back()->with('error', 'Rumah sudah diambil!'); +// } + +// $penghuni = Penghuni::where('email', Auth::user()->email)->first(); + +// if (!$penghuni) { +// return back()->with('error', 'Isi data penghuni dulu!'); +// } + +// if ($penghuni->rumah_id) { +// return back()->with('error', 'Anda sudah memiliki rumah!'); +// } + +// DB::transaction(function () use ($rumah, $penghuni) { +// $rumah->update(['status' => 'Terisi']); +// $penghuni->update(['rumah_id' => $rumah->id]); +// }); + +// return redirect()->route('user.rumah') +// ->with('success', 'Berhasil mengambil rumah!'); +// } + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + // 🔥 HANDLE FOTO + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + + $file->move(public_path('foto_rumah'), $namaFile); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile // 🔥 INI WAJIB ADA + ]); + + return back()->with('success', 'Rumah berhasil ditambahkan'); + } + + public function updateRumah(Request $request, $id) + { + $rumah = \App\Models\Rumah::findOrFail($id); + + $rumah->update([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + ]); + + return back()->with('success', 'Berhasil update rumah'); + } + + public function detailInformasi($id) + { + $info = Informasi::findOrFail($id); + $info->increment('views'); + + return view('user.informasi.detail', compact('info')); + } + + // ========================= + // UPLOAD PEMBAYARAN + // ========================= + // public function uploadPembayaran() + // { + // return view('user.upload_pembayaran'); + // } + + // // ========================= + // // STATUS PEMBAYARAN + // // ========================= + // public function statusPembayaran() + // { + // return view('user.status_pembayaran'); + // } + + // // ========================= + // // STATUS PENGADUAN + // // ========================= + // public function statusPengaduan() + // { + // return view('user.status_pengaduan'); + // } +} diff --git a/.history/app/Http/Controllers/UserController_20260521214529.php b/.history/app/Http/Controllers/UserController_20260521214529.php new file mode 100644 index 0000000..a82f4cc --- /dev/null +++ b/.history/app/Http/Controllers/UserController_20260521214529.php @@ -0,0 +1,366 @@ +where('email', $user->email) + ->latest() + ->first(); + + $rumah = $penghuni ? $penghuni->rumah : null; + + // 🔥 WAJIB ADA - dipakai di hero stats view + $rumahList = \App\Models\Rumah::all(); + + $rtUser = null; + if ($rumah && $rumah->rt_id) { + $rtUser = \App\Models\User::where('id', $rumah->rt_id)->first(); + } + + $iuran = collect(); + $hidden = session()->get('hidden_iuran', []); + $hiddenLayanan = session()->get('hidden_layanan', []); + + if ($penghuni) { + $iuran = \App\Models\Iuran::where('penghuni_id', $penghuni->id) + ->whereNotIn('id', $hidden) + ->orderBy('tahun', 'desc') + ->orderBy('bulan', 'asc') + ->get(); + } + + $pengaduan = collect(); + $informasi = \App\Models\Informasi::orderBy('is_penting', 'desc') + ->orderBy('tanggal', 'desc') + ->get(); + + if ($penghuni) { + $pengaduan = \App\Models\Layanan::where('penghuni_id', $penghuni->id) + ->whereNotIn('id', $hiddenLayanan) + ->latest() + ->get(); + } + + $isExpired = false; + if ($penghuni && $penghuni->status == 'Tidak Aktif') { + $isExpired = true; + } + + return view('user.home', compact( + 'penghuni', 'rumah', 'rumahList', 'rtUser', + 'iuran', 'pengaduan', 'informasi', 'isExpired' + )); +} + // ========================= + // PROFIL + // ========================= + public function profil() + { + $penghuni = Penghuni::where('email', Auth::user()->email)->first(); + return view('user.profile.edit', compact('penghuni')); + } + + public function updateProfil(Request $request) + { + $penghuni = Penghuni::where('email', Auth::user()->email)->first(); + + $penghuni->update([ + 'nama' => $request->nama, + 'telepon' => $request->telepon, + 'alamat' => $request->alamat, + ]); + + return back()->with('success', 'Profil berhasil diupdate'); + } + + // ========================= + // RUMAH + // ========================= +public function rumah() +{ + $user = Auth::user(); + + $penghuni = \App\Models\Penghuni::with('rumah') + ->where('email', $user->email) // 🔥 BY EMAIL, BUKAN user_id + ->latest() + ->first(); + + $rumah = $penghuni ? $penghuni->rumah : null; + + $rtUser = null; + if ($rumah && $rumah->rt_id) { + $rtUser = \App\Models\User::where('id', $rumah->rt_id) + ->where('role', 'rt') + ->first(); + } + + $rumahList = \App\Models\Rumah::all(); + + return view('user.rumah', compact('penghuni', 'rumah', 'rtUser', 'rumahList')); +} + // ========================= + // 🔥 TAMBAHAN: PILIH RUMAH + // ========================= +public function pilihRumah($id) +{ + $user = Auth::user(); + + $rumah = \App\Models\Rumah::findOrFail($id); + + if ($rumah->status == 'Terisi') { + return back()->with('error', 'Rumah sudah diambil!'); + } + + $penghuni = \App\Models\Penghuni::where('user_id', $user->id) + ->orWhere('email', $user->email) + ->first(); + + if (!$penghuni) { + $penghuni = new \App\Models\Penghuni(); + $penghuni->status_huni = 'Tetap'; // 🔥 hanya set kalau penghuni BARU + } + + $penghuni->user_id = $user->id; + $penghuni->nama = $user->name; + $penghuni->email = $user->email; + $penghuni->status = 'Aktif'; + + // 🔥 HAPUS baris $penghuni->status_huni = 'Tetap'; yang lama + + if (!$penghuni->tanggal_masuk) { + $penghuni->tanggal_masuk = now(); + } + + $penghuni->rumah_id = $rumah->id; + $penghuni->rt_id = $rumah->rt_id; + + $penghuni->save(); + + $rumah->status = 'Terisi'; + $rumah->save(); + + return redirect()->route('user.rumah')->with('success', 'Berhasil pilih rumah!'); +} + + // // ========================= + // // IURAN + // // ========================= + // public function iuran() + // { + // return view('user.iuran'); + // } + + // // ========================= + // // PENGADUAN + // // ========================= + // public function pengaduan() + // { + // return view('user.pengaduan'); + // } + + // public function storePengaduan(Request $request) + // { + // // sementara dummy dulu + // return back()->with('success', 'Pengaduan berhasil dikirim'); + // } + + // // ========================= + // // PENGUMUMAN + // // ========================= + // public function pengumuman() + // { + // return view('user.pengumuman'); + // } + +public function ambilRumah(Request $request) +{ + $user = Auth::user(); + + $rumah = \App\Models\Rumah::findOrFail($request->rumah_id); + + // 🔥 ambil penghuni yang SUDAH ADA + $penghuni = \App\Models\Penghuni::where('email', $user->email)->first(); + + if (!$penghuni) { + return back()->with('error', 'Data penghuni belum ada!'); + } + + // 🔥 hanya update yang penting saja + $penghuni->user_id = $user->id; // pastikan tidak null + $penghuni->rumah_id = $rumah->id; + $penghuni->rt_id = $rumah->rt_id; + + $penghuni->save(); + + // 🔥 update status rumah + $rumah->status = 'Terisi'; + $rumah->save(); + + return redirect()->route('user.rumah')->with('success', 'Berhasil ambil rumah!'); +} + + public function simpanPenghuni(Request $request) +{ + $request->validate([ + 'nama' => 'required', + 'no_ktp' => 'required', + 'telepon' => 'required', + 'alamat' => 'required', + 'status_huni' => 'required|in:Tetap,Kontrak', + 'tanggal_keluar' => 'nullable|date' + ]); + + $user = Auth::user(); + + // 🔥 Cek duplikat by EMAIL + if (Penghuni::where('email', $user->email)->exists()) { + return redirect()->route('user.rumah') + ->with('info', 'Data penghuni sudah ada!'); + } + + Penghuni::create([ + 'nama' => $request->nama, + 'email' => $user->email, + 'no_ktp' => $request->no_ktp, + 'telepon' => $request->telepon, + 'alamat' => $request->alamat, + 'status_huni' => $request->status_huni, + 'tanggal_masuk' => now(), + 'tanggal_keluar' => $request->status_huni == 'Kontrak' + ? $request->tanggal_keluar + : null, + 'status' => 'Aktif', + ]); + + // 🔥 REDIRECT KE user.rumah (bukan user.home) + return redirect()->route('user.rumah') + ->with('success', 'Data penghuni berhasil disimpan!'); +} + +// public function ambilRumah(Request $request) +// { +// $request->validate([ +// 'rumah_id' => 'required|exists:rumah,id' +// ]); + +// $rumah = Rumah::findOrFail($request->rumah_id); + +// if ($rumah->status == 'Terisi') { +// return back()->with('error', 'Rumah sudah diambil!'); +// } + +// $penghuni = Penghuni::where('email', Auth::user()->email)->first(); + +// if (!$penghuni) { +// return back()->with('error', 'Isi data penghuni dulu!'); +// } + +// if ($penghuni->rumah_id) { +// return back()->with('error', 'Anda sudah memiliki rumah!'); +// } + +// DB::transaction(function () use ($rumah, $penghuni) { +// $rumah->update(['status' => 'Terisi']); +// $penghuni->update(['rumah_id' => $rumah->id]); +// }); + +// return redirect()->route('user.rumah') +// ->with('success', 'Berhasil mengambil rumah!'); +// } + public function storeRumah(Request $request) + { + $request->validate([ + 'blok' => 'required', + 'no_rumah' => 'required', + 'status' => 'required', + 'foto' => 'nullable|image|mimes:jpg,png,jpeg|max:2048' + ]); + + // 🔥 HANDLE FOTO + $namaFile = null; + + if ($request->hasFile('foto')) { + $file = $request->file('foto'); + $namaFile = time() . '.' . $file->getClientOriginalExtension(); + + $file->move(public_path('foto_rumah'), $namaFile); + } + + Rumah::create([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + 'foto' => $namaFile // 🔥 INI WAJIB ADA + ]); + + return back()->with('success', 'Rumah berhasil ditambahkan'); + } + + public function updateRumah(Request $request, $id) + { + $rumah = \App\Models\Rumah::findOrFail($id); + + $rumah->update([ + 'blok' => $request->blok, + 'no_rumah' => $request->no_rumah, + 'status' => $request->status, + 'luas_tanah' => $request->luas_tanah, + 'harga' => $request->harga, + 'keterangan' => $request->keterangan, + ]); + + return back()->with('success', 'Berhasil update rumah'); + } + + public function detailInformasi($id) + { + $info = Informasi::findOrFail($id); + $info->increment('views'); + + return view('user.informasi.detail', compact('info')); + } + + // ========================= + // UPLOAD PEMBAYARAN + // ========================= + // public function uploadPembayaran() + // { + // return view('user.upload_pembayaran'); + // } + + // // ========================= + // // STATUS PEMBAYARAN + // // ========================= + // public function statusPembayaran() + // { + // return view('user.status_pembayaran'); + // } + + // // ========================= + // // STATUS PENGADUAN + // // ========================= + // public function statusPengaduan() + // { + // return view('user.status_pengaduan'); + // } +} diff --git a/.history/app/Http/Controllers/UserIuranController_20260416200452.php b/.history/app/Http/Controllers/UserIuranController_20260416200452.php new file mode 100644 index 0000000..46ea17d --- /dev/null +++ b/.history/app/Http/Controllers/UserIuranController_20260416200452.php @@ -0,0 +1,103 @@ +email)->first(); + + if (!$penghuni) { + return back()->with('error', 'Data penghuni tidak ditemukan'); + } + + $iuran = Iuran::where('penghuni_id', $penghuni->id)->get(); + + $penghuni = \App\Models\Penghuni::where('email', Auth::user()->email)->first(); + + if ($penghuni && $penghuni->status_huni == 'Kontrak' && $penghuni->tanggal_keluar) { + if (now()->gt($penghuni->tanggal_keluar)) { + return redirect()->route('user.home') + ->with('error', 'Kontrak Anda telah berakhir!'); + } + } + + return view('user.iuran.index', compact('iuran')); + } + + public function bayarQris($id) + { + $iuran = Iuran::findOrFail($id); + + $iuran->update([ + 'status' => 'lunas', + 'metode' => 'qris', + 'tanggal_bayar' => now() + ]); + + return response()->json([ + 'success' => true + ]); + } + + // 🔥 HALAMAN UPLOAD + public function upload($id) + { + $iuran = Iuran::findOrFail($id); + return view('user.iuran.upload', compact('iuran')); + } + + // 🔥 SIMPAN BUKTI + public function storeUpload(Request $request, $id) + { + $request->validate([ + 'bukti_pembayaran' => 'required|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $iuran = Iuran::findOrFail($id); + + if ($request->hasFile('bukti_pembayaran')) { + + $file = $request->file('bukti_pembayaran'); + $namaFile = time().'.'.$file->getClientOriginalExtension(); + + $file->move(public_path('bukti'), $namaFile); + + $iuran->update([ + 'bukti_pembayaran' => $namaFile, + 'status' => 'belum' // menunggu approve admin + ]); + } + + return redirect()->route('user.iuran.index') + ->with('success', 'Bukti berhasil diupload, menunggu konfirmasi admin'); + } + + public function status() + { + $penghuni = \App\Models\Penghuni::where('email', Auth::user()->email)->first(); + + $iuran = Iuran::where('penghuni_id', $penghuni->id)->get(); + + return view('user.iuran.status', compact('iuran')); + } + + public function delete($id) + { + // ambil data dari session + $hidden = session()->get('hidden_iuran', []); + + // tambahkan id ke list hidden + $hidden[] = $id; + + // simpan kembali ke session + session()->put('hidden_iuran', $hidden); + + return back()->with('success', 'Data disembunyikan dari halaman ini'); + } +} diff --git a/.history/app/Http/Controllers/UserIuranController_20260615175138.php b/.history/app/Http/Controllers/UserIuranController_20260615175138.php new file mode 100644 index 0000000..7222dea --- /dev/null +++ b/.history/app/Http/Controllers/UserIuranController_20260615175138.php @@ -0,0 +1,101 @@ +email)->first(); + + if (!$penghuni) { + return back()->with('error', 'Data penghuni tidak ditemukan'); + } + + $iuran = Iuran::where('penghuni_id', $penghuni->id)->get(); + + $penghuni = \App\Models\Penghuni::where('email', Auth::user()->email)->first(); + + if ($penghuni && $penghuni->status_huni == 'Kontrak' && $penghuni->tanggal_keluar) { + if (now()->gt($penghuni->tanggal_keluar)) { + return redirect()->route('user.home') + ->with('error', 'Kontrak Anda telah berakhir!'); + } + } + + return view('user.iuran.index', compact('iuran')); + } + + public function bayarQris($id) + { + $iuran = Iuran::findOrFail($id); + + $iuran->update([ + 'status' => 'lunas', + 'metode' => 'qris', + 'tanggal_bayar' => now() + ]); + + return response()->json([ + 'success' => true + ]); + } + + // 🔥 HALAMAN UPLOAD + public function upload($id) + { + $iuran = Iuran::findOrFail($id); + return view('user.iuran.upload', compact('iuran')); + } + + // 🔥 SIMPAN BUKTI + public function storeUpload(Request $request, $id) +{ + $request->validate([ + 'bukti_pembayaran' => 'required|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $iuran = Iuran::findOrFail($id); + + if ($request->hasFile('bukti_pembayaran')) { + $file = $request->file('bukti_pembayaran'); + $namaFile = time().'.'.$file->getClientOriginalExtension(); + $file->move(public_path('bukti'), $namaFile); + + $iuran->update([ + 'bukti_pembayaran' => $namaFile, + 'status' => 'menunggu', // ✅ GANTI dari 'belum' ke 'menunggu' + ]); + } + + return redirect()->route('user.iuran.index') + ->with('success', 'Bukti berhasil diupload, menunggu konfirmasi RT'); +} + + public function status() + { + $penghuni = \App\Models\Penghuni::where('email', Auth::user()->email)->first(); + + $iuran = Iuran::where('penghuni_id', $penghuni->id)->get(); + + return view('user.iuran.status', compact('iuran')); + } + + public function delete($id) + { + // ambil data dari session + $hidden = session()->get('hidden_iuran', []); + + // tambahkan id ke list hidden + $hidden[] = $id; + + // simpan kembali ke session + session()->put('hidden_iuran', $hidden); + + return back()->with('success', 'Data disembunyikan dari halaman ini'); + } +} diff --git a/.history/app/Http/Controllers/UserIuranController_20260615175149.php b/.history/app/Http/Controllers/UserIuranController_20260615175149.php new file mode 100644 index 0000000..597a97d --- /dev/null +++ b/.history/app/Http/Controllers/UserIuranController_20260615175149.php @@ -0,0 +1,101 @@ +email)->first(); + + if (!$penghuni) { + return back()->with('error', 'Data penghuni tidak ditemukan'); + } + + $iuran = Iuran::where('penghuni_id', $penghuni->id)->get(); + + $penghuni = \App\Models\Penghuni::where('email', Auth::user()->email)->first(); + + if ($penghuni && $penghuni->status_huni == 'Kontrak' && $penghuni->tanggal_keluar) { + if (now()->gt($penghuni->tanggal_keluar)) { + return redirect()->route('user.home') + ->with('error', 'Kontrak Anda telah berakhir!'); + } + } + + return view('user.iuran.index', compact('iuran')); + } + + public function bayarQris($id) + { + $iuran = Iuran::findOrFail($id); + + $iuran->update([ + 'status' => 'lunas', + 'metode' => 'qris', + 'tanggal_bayar' => now() + ]); + + return response()->json([ + 'success' => true + ]); + } + + // 🔥 HALAMAN UPLOAD + public function upload($id) + { + $iuran = Iuran::findOrFail($id); + return view('user.iuran.upload', compact('iuran')); + } + + // 🔥 SIMPAN BUKTI + public function storeUpload(Request $request, $id) + { + $request->validate([ + 'bukti_pembayaran' => 'required|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $iuran = Iuran::findOrFail($id); + + if ($request->hasFile('bukti_pembayaran')) { + $file = $request->file('bukti_pembayaran'); + $namaFile = time().'.'.$file->getClientOriginalExtension(); + $file->move(public_path('bukti'), $namaFile); + + $iuran->update([ + 'bukti_pembayaran' => $namaFile, + 'status' => 'menunggu', // ✅ GANTI dari 'belum' ke 'menunggu' + ]); + } + + return redirect()->route('user.iuran.index') + ->with('success', 'Bukti berhasil diupload, menunggu konfirmasi RT'); + } + + public function status() + { + $penghuni = \App\Models\Penghuni::where('email', Auth::user()->email)->first(); + + $iuran = Iuran::where('penghuni_id', $penghuni->id)->get(); + + return view('user.iuran.status', compact('iuran')); + } + + public function delete($id) + { + // ambil data dari session + $hidden = session()->get('hidden_iuran', []); + + // tambahkan id ke list hidden + $hidden[] = $id; + + // simpan kembali ke session + session()->put('hidden_iuran', $hidden); + + return back()->with('success', 'Data disembunyikan dari halaman ini'); + } +} diff --git a/.history/app/Http/Controllers/UserIuranController_20260615175302.php b/.history/app/Http/Controllers/UserIuranController_20260615175302.php new file mode 100644 index 0000000..26a2de5 --- /dev/null +++ b/.history/app/Http/Controllers/UserIuranController_20260615175302.php @@ -0,0 +1,96 @@ +email)->first(); + + if (!$penghuni) { + return back()->with('error', 'Data penghuni tidak ditemukan'); + } + + $iuran = Iuran::where('penghuni_id', $penghuni->id)->get(); + + $penghuni = \App\Models\Penghuni::where('email', Auth::user()->email)->first(); + + if ($penghuni && $penghuni->status_huni == 'Kontrak' && $penghuni->tanggal_keluar) { + if (now()->gt($penghuni->tanggal_keluar)) { + return redirect()->route('user.home') + ->with('error', 'Kontrak Anda telah berakhir!'); + } + } + + return view('user.iuran.index', compact('iuran')); + } + + public function bayarQris($id) + { + public function bayarQris($id) +{ + // Jangan langsung lunas, redirect ke halaman upload bukti + return redirect()->route('user.iuran.upload', $id) + ->with('info', 'Setelah bayar via QRIS, upload bukti pembayaran di bawah ini'); +} + } + + // 🔥 HALAMAN UPLOAD + public function upload($id) + { + $iuran = Iuran::findOrFail($id); + return view('user.iuran.upload', compact('iuran')); + } + + // 🔥 SIMPAN BUKTI + public function storeUpload(Request $request, $id) + { + $request->validate([ + 'bukti_pembayaran' => 'required|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $iuran = Iuran::findOrFail($id); + + if ($request->hasFile('bukti_pembayaran')) { + $file = $request->file('bukti_pembayaran'); + $namaFile = time().'.'.$file->getClientOriginalExtension(); + $file->move(public_path('bukti'), $namaFile); + + $iuran->update([ + 'bukti_pembayaran' => $namaFile, + 'status' => 'menunggu', // ✅ GANTI dari 'belum' ke 'menunggu' + ]); + } + + return redirect()->route('user.iuran.index') + ->with('success', 'Bukti berhasil diupload, menunggu konfirmasi RT'); + } + + public function status() + { + $penghuni = \App\Models\Penghuni::where('email', Auth::user()->email)->first(); + + $iuran = Iuran::where('penghuni_id', $penghuni->id)->get(); + + return view('user.iuran.status', compact('iuran')); + } + + public function delete($id) + { + // ambil data dari session + $hidden = session()->get('hidden_iuran', []); + + // tambahkan id ke list hidden + $hidden[] = $id; + + // simpan kembali ke session + session()->put('hidden_iuran', $hidden); + + return back()->with('success', 'Data disembunyikan dari halaman ini'); + } +} diff --git a/.history/app/Http/Controllers/UserIuranController_20260615175304.php b/.history/app/Http/Controllers/UserIuranController_20260615175304.php new file mode 100644 index 0000000..597a97d --- /dev/null +++ b/.history/app/Http/Controllers/UserIuranController_20260615175304.php @@ -0,0 +1,101 @@ +email)->first(); + + if (!$penghuni) { + return back()->with('error', 'Data penghuni tidak ditemukan'); + } + + $iuran = Iuran::where('penghuni_id', $penghuni->id)->get(); + + $penghuni = \App\Models\Penghuni::where('email', Auth::user()->email)->first(); + + if ($penghuni && $penghuni->status_huni == 'Kontrak' && $penghuni->tanggal_keluar) { + if (now()->gt($penghuni->tanggal_keluar)) { + return redirect()->route('user.home') + ->with('error', 'Kontrak Anda telah berakhir!'); + } + } + + return view('user.iuran.index', compact('iuran')); + } + + public function bayarQris($id) + { + $iuran = Iuran::findOrFail($id); + + $iuran->update([ + 'status' => 'lunas', + 'metode' => 'qris', + 'tanggal_bayar' => now() + ]); + + return response()->json([ + 'success' => true + ]); + } + + // 🔥 HALAMAN UPLOAD + public function upload($id) + { + $iuran = Iuran::findOrFail($id); + return view('user.iuran.upload', compact('iuran')); + } + + // 🔥 SIMPAN BUKTI + public function storeUpload(Request $request, $id) + { + $request->validate([ + 'bukti_pembayaran' => 'required|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $iuran = Iuran::findOrFail($id); + + if ($request->hasFile('bukti_pembayaran')) { + $file = $request->file('bukti_pembayaran'); + $namaFile = time().'.'.$file->getClientOriginalExtension(); + $file->move(public_path('bukti'), $namaFile); + + $iuran->update([ + 'bukti_pembayaran' => $namaFile, + 'status' => 'menunggu', // ✅ GANTI dari 'belum' ke 'menunggu' + ]); + } + + return redirect()->route('user.iuran.index') + ->with('success', 'Bukti berhasil diupload, menunggu konfirmasi RT'); + } + + public function status() + { + $penghuni = \App\Models\Penghuni::where('email', Auth::user()->email)->first(); + + $iuran = Iuran::where('penghuni_id', $penghuni->id)->get(); + + return view('user.iuran.status', compact('iuran')); + } + + public function delete($id) + { + // ambil data dari session + $hidden = session()->get('hidden_iuran', []); + + // tambahkan id ke list hidden + $hidden[] = $id; + + // simpan kembali ke session + session()->put('hidden_iuran', $hidden); + + return back()->with('success', 'Data disembunyikan dari halaman ini'); + } +} diff --git a/.history/app/Http/Controllers/UserIuranController_20260615175324.php b/.history/app/Http/Controllers/UserIuranController_20260615175324.php new file mode 100644 index 0000000..e89f673 --- /dev/null +++ b/.history/app/Http/Controllers/UserIuranController_20260615175324.php @@ -0,0 +1,93 @@ +email)->first(); + + if (!$penghuni) { + return back()->with('error', 'Data penghuni tidak ditemukan'); + } + + $iuran = Iuran::where('penghuni_id', $penghuni->id)->get(); + + $penghuni = \App\Models\Penghuni::where('email', Auth::user()->email)->first(); + + if ($penghuni && $penghuni->status_huni == 'Kontrak' && $penghuni->tanggal_keluar) { + if (now()->gt($penghuni->tanggal_keluar)) { + return redirect()->route('user.home') + ->with('error', 'Kontrak Anda telah berakhir!'); + } + } + + return view('user.iuran.index', compact('iuran')); + } + + public function bayarQris($id) +{ + // Jangan langsung lunas, redirect ke halaman upload bukti + return redirect()->route('user.iuran.upload', $id) + ->with('info', 'Setelah bayar via QRIS, upload bukti pembayaran di bawah ini'); +} + + // 🔥 HALAMAN UPLOAD + public function upload($id) + { + $iuran = Iuran::findOrFail($id); + return view('user.iuran.upload', compact('iuran')); + } + + // 🔥 SIMPAN BUKTI + public function storeUpload(Request $request, $id) + { + $request->validate([ + 'bukti_pembayaran' => 'required|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $iuran = Iuran::findOrFail($id); + + if ($request->hasFile('bukti_pembayaran')) { + $file = $request->file('bukti_pembayaran'); + $namaFile = time().'.'.$file->getClientOriginalExtension(); + $file->move(public_path('bukti'), $namaFile); + + $iuran->update([ + 'bukti_pembayaran' => $namaFile, + 'status' => 'menunggu', // ✅ GANTI dari 'belum' ke 'menunggu' + ]); + } + + return redirect()->route('user.iuran.index') + ->with('success', 'Bukti berhasil diupload, menunggu konfirmasi RT'); + } + + public function status() + { + $penghuni = \App\Models\Penghuni::where('email', Auth::user()->email)->first(); + + $iuran = Iuran::where('penghuni_id', $penghuni->id)->get(); + + return view('user.iuran.status', compact('iuran')); + } + + public function delete($id) + { + // ambil data dari session + $hidden = session()->get('hidden_iuran', []); + + // tambahkan id ke list hidden + $hidden[] = $id; + + // simpan kembali ke session + session()->put('hidden_iuran', $hidden); + + return back()->with('success', 'Data disembunyikan dari halaman ini'); + } +} diff --git a/.history/app/Http/Controllers/UserIuranController_20260615175327.php b/.history/app/Http/Controllers/UserIuranController_20260615175327.php new file mode 100644 index 0000000..fe66665 --- /dev/null +++ b/.history/app/Http/Controllers/UserIuranController_20260615175327.php @@ -0,0 +1,93 @@ +email)->first(); + + if (!$penghuni) { + return back()->with('error', 'Data penghuni tidak ditemukan'); + } + + $iuran = Iuran::where('penghuni_id', $penghuni->id)->get(); + + $penghuni = \App\Models\Penghuni::where('email', Auth::user()->email)->first(); + + if ($penghuni && $penghuni->status_huni == 'Kontrak' && $penghuni->tanggal_keluar) { + if (now()->gt($penghuni->tanggal_keluar)) { + return redirect()->route('user.home') + ->with('error', 'Kontrak Anda telah berakhir!'); + } + } + + return view('user.iuran.index', compact('iuran')); + } + + public function bayarQris($id) + { + // Jangan langsung lunas, redirect ke halaman upload bukti + return redirect()->route('user.iuran.upload', $id) + ->with('info', 'Setelah bayar via QRIS, upload bukti pembayaran di bawah ini'); + } + + // 🔥 HALAMAN UPLOAD + public function upload($id) + { + $iuran = Iuran::findOrFail($id); + return view('user.iuran.upload', compact('iuran')); + } + + // 🔥 SIMPAN BUKTI + public function storeUpload(Request $request, $id) + { + $request->validate([ + 'bukti_pembayaran' => 'required|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $iuran = Iuran::findOrFail($id); + + if ($request->hasFile('bukti_pembayaran')) { + $file = $request->file('bukti_pembayaran'); + $namaFile = time().'.'.$file->getClientOriginalExtension(); + $file->move(public_path('bukti'), $namaFile); + + $iuran->update([ + 'bukti_pembayaran' => $namaFile, + 'status' => 'menunggu', // ✅ GANTI dari 'belum' ke 'menunggu' + ]); + } + + return redirect()->route('user.iuran.index') + ->with('success', 'Bukti berhasil diupload, menunggu konfirmasi RT'); + } + + public function status() + { + $penghuni = \App\Models\Penghuni::where('email', Auth::user()->email)->first(); + + $iuran = Iuran::where('penghuni_id', $penghuni->id)->get(); + + return view('user.iuran.status', compact('iuran')); + } + + public function delete($id) + { + // ambil data dari session + $hidden = session()->get('hidden_iuran', []); + + // tambahkan id ke list hidden + $hidden[] = $id; + + // simpan kembali ke session + session()->put('hidden_iuran', $hidden); + + return back()->with('success', 'Data disembunyikan dari halaman ini'); + } +} diff --git a/.history/app/Http/Controllers/UserIuranController_20260619094756.php b/.history/app/Http/Controllers/UserIuranController_20260619094756.php new file mode 100644 index 0000000..3592049 --- /dev/null +++ b/.history/app/Http/Controllers/UserIuranController_20260619094756.php @@ -0,0 +1,113 @@ +email)->first(); + + if (!$penghuni) { + return back()->with('error', 'Data penghuni tidak ditemukan'); + } + + $iuran = Iuran::where('penghuni_id', $penghuni->id)->get(); + + $penghuni = \App\Models\Penghuni::where('email', Auth::user()->email)->first(); + + if ($penghuni && $penghuni->status_huni == 'Kontrak' && $penghuni->tanggal_keluar) { + if (now()->gt($penghuni->tanggal_keluar)) { + return redirect()->route('user.home') + ->with('error', 'Kontrak Anda telah berakhir!'); + } + } + + return view('user.iuran.index', compact('iuran')); + } + +public function bayarQris($id) + { + $iuran = Iuran::findOrFail($id); + + $iuran->update([ + 'status' => 'menunggu', + 'metode' => 'qris', + 'tanggal_bayar' => now() + ]); + + // Catat otomatis ke kas bendahara (uang masuk) + if ($iuran->dibuat_oleh) { + \App\Models\KasBendahara::create([ + 'bendahara_id' => $iuran->dibuat_oleh, + 'rt_id' => $iuran->rt_id, + 'jenis' => 'masuk', + 'jumlah' => $iuran->jumlah, + 'keterangan' => 'Pembayaran QRIS - ' . $iuran->jenis_iuran . ' (' . $iuran->bulan . ' ' . $iuran->tahun . ')', + 'iuran_id' => $iuran->id, + ]); + } + + return response()->json([ + 'success' => true + ]); + } + + // 🔥 HALAMAN UPLOAD + public function upload($id) + { + $iuran = Iuran::findOrFail($id); + return view('user.iuran.upload', compact('iuran')); + } + + // 🔥 SIMPAN BUKTI + public function storeUpload(Request $request, $id) + { + $request->validate([ + 'bukti_pembayaran' => 'required|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $iuran = Iuran::findOrFail($id); + + if ($request->hasFile('bukti_pembayaran')) { + $file = $request->file('bukti_pembayaran'); + $namaFile = time().'.'.$file->getClientOriginalExtension(); + $file->move(public_path('bukti'), $namaFile); + + $iuran->update([ + 'bukti_pembayaran' => $namaFile, + 'status' => 'menunggu', // ✅ GANTI dari 'belum' ke 'menunggu' + ]); + } + + return redirect()->route('user.iuran.index') + ->with('success', 'Bukti berhasil diupload, menunggu konfirmasi RT'); + } + + public function status() + { + $penghuni = \App\Models\Penghuni::where('email', Auth::user()->email)->first(); + + $iuran = Iuran::where('penghuni_id', $penghuni->id)->get(); + + return view('user.iuran.status', compact('iuran')); + } + + public function delete($id) + { + // ambil data dari session + $hidden = session()->get('hidden_iuran', []); + + // tambahkan id ke list hidden + $hidden[] = $id; + + // simpan kembali ke session + session()->put('hidden_iuran', $hidden); + + return back()->with('success', 'Data disembunyikan dari halaman ini'); + } +} diff --git a/.history/app/Http/Controllers/UserIuranController_20260619094803.php b/.history/app/Http/Controllers/UserIuranController_20260619094803.php new file mode 100644 index 0000000..7e3eebe --- /dev/null +++ b/.history/app/Http/Controllers/UserIuranController_20260619094803.php @@ -0,0 +1,113 @@ +email)->first(); + + if (!$penghuni) { + return back()->with('error', 'Data penghuni tidak ditemukan'); + } + + $iuran = Iuran::where('penghuni_id', $penghuni->id)->get(); + + $penghuni = \App\Models\Penghuni::where('email', Auth::user()->email)->first(); + + if ($penghuni && $penghuni->status_huni == 'Kontrak' && $penghuni->tanggal_keluar) { + if (now()->gt($penghuni->tanggal_keluar)) { + return redirect()->route('user.home') + ->with('error', 'Kontrak Anda telah berakhir!'); + } + } + + return view('user.iuran.index', compact('iuran')); + } + + public function bayarQris($id) + { + $iuran = Iuran::findOrFail($id); + + $iuran->update([ + 'status' => 'menunggu', + 'metode' => 'qris', + 'tanggal_bayar' => now() + ]); + + // Catat otomatis ke kas bendahara (uang masuk) + if ($iuran->dibuat_oleh) { + \App\Models\KasBendahara::create([ + 'bendahara_id' => $iuran->dibuat_oleh, + 'rt_id' => $iuran->rt_id, + 'jenis' => 'masuk', + 'jumlah' => $iuran->jumlah, + 'keterangan' => 'Pembayaran QRIS - ' . $iuran->jenis_iuran . ' (' . $iuran->bulan . ' ' . $iuran->tahun . ')', + 'iuran_id' => $iuran->id, + ]); + } + + return response()->json([ + 'success' => true + ]); + } + + // 🔥 HALAMAN UPLOAD + public function upload($id) + { + $iuran = Iuran::findOrFail($id); + return view('user.iuran.upload', compact('iuran')); + } + + // 🔥 SIMPAN BUKTI + public function storeUpload(Request $request, $id) + { + $request->validate([ + 'bukti_pembayaran' => 'required|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $iuran = Iuran::findOrFail($id); + + if ($request->hasFile('bukti_pembayaran')) { + $file = $request->file('bukti_pembayaran'); + $namaFile = time().'.'.$file->getClientOriginalExtension(); + $file->move(public_path('bukti'), $namaFile); + + $iuran->update([ + 'bukti_pembayaran' => $namaFile, + 'status' => 'menunggu', // ✅ GANTI dari 'belum' ke 'menunggu' + ]); + } + + return redirect()->route('user.iuran.index') + ->with('success', 'Bukti berhasil diupload, menunggu konfirmasi RT'); + } + + public function status() + { + $penghuni = \App\Models\Penghuni::where('email', Auth::user()->email)->first(); + + $iuran = Iuran::where('penghuni_id', $penghuni->id)->get(); + + return view('user.iuran.status', compact('iuran')); + } + + public function delete($id) + { + // ambil data dari session + $hidden = session()->get('hidden_iuran', []); + + // tambahkan id ke list hidden + $hidden[] = $id; + + // simpan kembali ke session + session()->put('hidden_iuran', $hidden); + + return back()->with('success', 'Data disembunyikan dari halaman ini'); + } +} diff --git a/.history/app/Http/Controllers/UserIuranController_20260619094845.php b/.history/app/Http/Controllers/UserIuranController_20260619094845.php new file mode 100644 index 0000000..4b34a08 --- /dev/null +++ b/.history/app/Http/Controllers/UserIuranController_20260619094845.php @@ -0,0 +1,128 @@ +email)->first(); + + if (!$penghuni) { + return back()->with('error', 'Data penghuni tidak ditemukan'); + } + + $iuran = Iuran::where('penghuni_id', $penghuni->id)->get(); + + $penghuni = \App\Models\Penghuni::where('email', Auth::user()->email)->first(); + + if ($penghuni && $penghuni->status_huni == 'Kontrak' && $penghuni->tanggal_keluar) { + if (now()->gt($penghuni->tanggal_keluar)) { + return redirect()->route('user.home') + ->with('error', 'Kontrak Anda telah berakhir!'); + } + } + + return view('user.iuran.index', compact('iuran')); + } + + public function bayarQris($id) + { + $iuran = Iuran::findOrFail($id); + + $iuran->update([ + 'status' => 'menunggu', + 'metode' => 'qris', + 'tanggal_bayar' => now() + ]); + + // Catat otomatis ke kas bendahara (uang masuk) + if ($iuran->dibuat_oleh) { + \App\Models\KasBendahara::create([ + 'bendahara_id' => $iuran->dibuat_oleh, + 'rt_id' => $iuran->rt_id, + 'jenis' => 'masuk', + 'jumlah' => $iuran->jumlah, + 'keterangan' => 'Pembayaran QRIS - ' . $iuran->jenis_iuran . ' (' . $iuran->bulan . ' ' . $iuran->tahun . ')', + 'iuran_id' => $iuran->id, + ]); + } + + return response()->json([ + 'success' => true + ]); + } + + // 🔥 HALAMAN UPLOAD + public function upload($id) + { + $iuran = Iuran::findOrFail($id); + return view('user.iuran.upload', compact('iuran')); + } + + // 🔥 SIMPAN BUKTI + // 🔥 SIMPAN BUKTI + public function storeUpload(Request $request, $id) + { + $request->validate([ + 'bukti_pembayaran' => 'required|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $iuran = Iuran::findOrFail($id); + + if ($request->hasFile('bukti_pembayaran')) { + + $file = $request->file('bukti_pembayaran'); + $namaFile = time().'.'.$file->getClientOriginalExtension(); + + $file->move(public_path('bukti'), $namaFile); + + $iuran->update([ + 'bukti_pembayaran' => $namaFile, + 'status' => 'menunggu' // fix: dulu salah jadi 'belum' + ]); + + // Catat otomatis ke kas bendahara (uang masuk) + if ($iuran->dibuat_oleh) { + \App\Models\KasBendahara::create([ + 'bendahara_id' => $iuran->dibuat_oleh, + 'rt_id' => $iuran->rt_id, + 'jenis' => 'masuk', + 'jumlah' => $iuran->jumlah, + 'keterangan' => 'Upload bukti transfer - ' . $iuran->jenis_iuran . ' (' . $iuran->bulan . ' ' . $iuran->tahun . ')', + 'iuran_id' => $iuran->id, + ]); + } + } + + return redirect()->route('user.iuran.index') + ->with('success', 'Bukti berhasil diupload, menunggu konfirmasi bendahara & RT'); + } + + public function status() + { + $penghuni = \App\Models\Penghuni::where('email', Auth::user()->email)->first(); + + $iuran = Iuran::where('penghuni_id', $penghuni->id)->get(); + + return view('user.iuran.status', compact('iuran')); + } + + public function delete($id) + { + // ambil data dari session + $hidden = session()->get('hidden_iuran', []); + + // tambahkan id ke list hidden + $hidden[] = $id; + + // simpan kembali ke session + session()->put('hidden_iuran', $hidden); + + return back()->with('success', 'Data disembunyikan dari halaman ini'); + } +} diff --git a/.history/app/Http/Controllers/UserIuranController_20260619094849.php b/.history/app/Http/Controllers/UserIuranController_20260619094849.php new file mode 100644 index 0000000..f29fd97 --- /dev/null +++ b/.history/app/Http/Controllers/UserIuranController_20260619094849.php @@ -0,0 +1,128 @@ +email)->first(); + + if (!$penghuni) { + return back()->with('error', 'Data penghuni tidak ditemukan'); + } + + $iuran = Iuran::where('penghuni_id', $penghuni->id)->get(); + + $penghuni = \App\Models\Penghuni::where('email', Auth::user()->email)->first(); + + if ($penghuni && $penghuni->status_huni == 'Kontrak' && $penghuni->tanggal_keluar) { + if (now()->gt($penghuni->tanggal_keluar)) { + return redirect()->route('user.home') + ->with('error', 'Kontrak Anda telah berakhir!'); + } + } + + return view('user.iuran.index', compact('iuran')); + } + + public function bayarQris($id) + { + $iuran = Iuran::findOrFail($id); + + $iuran->update([ + 'status' => 'menunggu', + 'metode' => 'qris', + 'tanggal_bayar' => now() + ]); + + // Catat otomatis ke kas bendahara (uang masuk) + if ($iuran->dibuat_oleh) { + \App\Models\KasBendahara::create([ + 'bendahara_id' => $iuran->dibuat_oleh, + 'rt_id' => $iuran->rt_id, + 'jenis' => 'masuk', + 'jumlah' => $iuran->jumlah, + 'keterangan' => 'Pembayaran QRIS - ' . $iuran->jenis_iuran . ' (' . $iuran->bulan . ' ' . $iuran->tahun . ')', + 'iuran_id' => $iuran->id, + ]); + } + + return response()->json([ + 'success' => true + ]); + } + + // 🔥 HALAMAN UPLOAD + public function upload($id) + { + $iuran = Iuran::findOrFail($id); + return view('user.iuran.upload', compact('iuran')); + } + + // 🔥 SIMPAN BUKTI + // 🔥 SIMPAN BUKTI + public function storeUpload(Request $request, $id) + { + $request->validate([ + 'bukti_pembayaran' => 'required|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $iuran = Iuran::findOrFail($id); + + if ($request->hasFile('bukti_pembayaran')) { + + $file = $request->file('bukti_pembayaran'); + $namaFile = time().'.'.$file->getClientOriginalExtension(); + + $file->move(public_path('bukti'), $namaFile); + + $iuran->update([ + 'bukti_pembayaran' => $namaFile, + 'status' => 'menunggu' // fix: dulu salah jadi 'belum' + ]); + + // Catat otomatis ke kas bendahara (uang masuk) + if ($iuran->dibuat_oleh) { + \App\Models\KasBendahara::create([ + 'bendahara_id' => $iuran->dibuat_oleh, + 'rt_id' => $iuran->rt_id, + 'jenis' => 'masuk', + 'jumlah' => $iuran->jumlah, + 'keterangan' => 'Upload bukti transfer - ' . $iuran->jenis_iuran . ' (' . $iuran->bulan . ' ' . $iuran->tahun . ')', + 'iuran_id' => $iuran->id, + ]); + } + } + + return redirect()->route('user.iuran.index') + ->with('success', 'Bukti berhasil diupload, menunggu konfirmasi bendahara & RT'); + } + + public function status() + { + $penghuni = \App\Models\Penghuni::where('email', Auth::user()->email)->first(); + + $iuran = Iuran::where('penghuni_id', $penghuni->id)->get(); + + return view('user.iuran.status', compact('iuran')); + } + + public function delete($id) + { + // ambil data dari session + $hidden = session()->get('hidden_iuran', []); + + // tambahkan id ke list hidden + $hidden[] = $id; + + // simpan kembali ke session + session()->put('hidden_iuran', $hidden); + + return back()->with('success', 'Data disembunyikan dari halaman ini'); + } +} diff --git a/.history/app/Http/Controllers/UserIuranController_20260619095405.php b/.history/app/Http/Controllers/UserIuranController_20260619095405.php new file mode 100644 index 0000000..9a882af --- /dev/null +++ b/.history/app/Http/Controllers/UserIuranController_20260619095405.php @@ -0,0 +1,129 @@ +email)->first(); + + if (!$penghuni) { + return back()->with('error', 'Data penghuni tidak ditemukan'); + } + + // Hanya tampilkan iuran yang sudah disetujui RT (bukan 'diajukan' atau 'ditolak') + $iuran = Iuran::where('penghuni_id', $penghuni->id) + ->whereIn('status', ['aktif', 'menunggu', 'lunas']) + ->get(); + + if ($penghuni && $penghuni->status_huni == 'Kontrak' && $penghuni->tanggal_keluar) { + if (now()->gt($penghuni->tanggal_keluar)) { + return redirect()->route('user.home') + ->with('error', 'Kontrak Anda telah berakhir!'); + } + } + + return view('user.iuran.index', compact('iuran')); + } + + public function bayarQris($id) + { + $iuran = Iuran::findOrFail($id); + + $iuran->update([ + 'status' => 'menunggu', + 'metode' => 'qris', + 'tanggal_bayar' => now() + ]); + + // Catat otomatis ke kas bendahara (uang masuk) + if ($iuran->dibuat_oleh) { + \App\Models\KasBendahara::create([ + 'bendahara_id' => $iuran->dibuat_oleh, + 'rt_id' => $iuran->rt_id, + 'jenis' => 'masuk', + 'jumlah' => $iuran->jumlah, + 'keterangan' => 'Pembayaran QRIS - ' . $iuran->jenis_iuran . ' (' . $iuran->bulan . ' ' . $iuran->tahun . ')', + 'iuran_id' => $iuran->id, + ]); + } + + return response()->json([ + 'success' => true + ]); + } + + // 🔥 HALAMAN UPLOAD + public function upload($id) + { + $iuran = Iuran::findOrFail($id); + return view('user.iuran.upload', compact('iuran')); + } + + // 🔥 SIMPAN BUKTI + // 🔥 SIMPAN BUKTI + public function storeUpload(Request $request, $id) + { + $request->validate([ + 'bukti_pembayaran' => 'required|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $iuran = Iuran::findOrFail($id); + + if ($request->hasFile('bukti_pembayaran')) { + + $file = $request->file('bukti_pembayaran'); + $namaFile = time().'.'.$file->getClientOriginalExtension(); + + $file->move(public_path('bukti'), $namaFile); + + $iuran->update([ + 'bukti_pembayaran' => $namaFile, + 'status' => 'menunggu' // fix: dulu salah jadi 'belum' + ]); + + // Catat otomatis ke kas bendahara (uang masuk) + if ($iuran->dibuat_oleh) { + \App\Models\KasBendahara::create([ + 'bendahara_id' => $iuran->dibuat_oleh, + 'rt_id' => $iuran->rt_id, + 'jenis' => 'masuk', + 'jumlah' => $iuran->jumlah, + 'keterangan' => 'Upload bukti transfer - ' . $iuran->jenis_iuran . ' (' . $iuran->bulan . ' ' . $iuran->tahun . ')', + 'iuran_id' => $iuran->id, + ]); + } + } + + return redirect()->route('user.iuran.index') + ->with('success', 'Bukti berhasil diupload, menunggu konfirmasi bendahara & RT'); + } + + public function status() + { + $penghuni = \App\Models\Penghuni::where('email', Auth::user()->email)->first(); + + $iuran = Iuran::where('penghuni_id', $penghuni->id)->get(); + + return view('user.iuran.status', compact('iuran')); + } + + public function delete($id) + { + // ambil data dari session + $hidden = session()->get('hidden_iuran', []); + + // tambahkan id ke list hidden + $hidden[] = $id; + + // simpan kembali ke session + session()->put('hidden_iuran', $hidden); + + return back()->with('success', 'Data disembunyikan dari halaman ini'); + } +} diff --git a/.history/app/Http/Controllers/UserIuranController_20260619095428.php b/.history/app/Http/Controllers/UserIuranController_20260619095428.php new file mode 100644 index 0000000..3411884 --- /dev/null +++ b/.history/app/Http/Controllers/UserIuranController_20260619095428.php @@ -0,0 +1,129 @@ +email)->first(); + + if (!$penghuni) { + return back()->with('error', 'Data penghuni tidak ditemukan'); + } + + // Hanya tampilkan iuran yang sudah disetujui RT (bukan 'diajukan' atau 'ditolak') + $iuran = Iuran::where('penghuni_id', $penghuni->id) + ->whereIn('status', ['aktif', 'menunggu', 'lunas']) + ->get(); + + if ($penghuni && $penghuni->status_huni == 'Kontrak' && $penghuni->tanggal_keluar) { + if (now()->gt($penghuni->tanggal_keluar)) { + return redirect()->route('user.home') + ->with('error', 'Kontrak Anda telah berakhir!'); + } + } + + return view('user.iuran.index', compact('iuran')); + } + + public function bayarQris($id) + { + $iuran = Iuran::findOrFail($id); + + $iuran->update([ + 'status' => 'menunggu', + 'metode' => 'qris', + 'tanggal_bayar' => now() + ]); + + // Catat otomatis ke kas bendahara (uang masuk) + if ($iuran->dibuat_oleh) { + \App\Models\KasBendahara::create([ + 'bendahara_id' => $iuran->dibuat_oleh, + 'rt_id' => $iuran->rt_id, + 'jenis' => 'masuk', + 'jumlah' => $iuran->jumlah, + 'keterangan' => 'Pembayaran QRIS - ' . $iuran->jenis_iuran . ' (' . $iuran->bulan . ' ' . $iuran->tahun . ')', + 'iuran_id' => $iuran->id, + ]); + } + + return response()->json([ + 'success' => true + ]); + } + + // 🔥 HALAMAN UPLOAD + public function upload($id) + { + $iuran = Iuran::findOrFail($id); + return view('user.iuran.upload', compact('iuran')); + } + + // 🔥 SIMPAN BUKTI + // 🔥 SIMPAN BUKTI + public function storeUpload(Request $request, $id) + { + $request->validate([ + 'bukti_pembayaran' => 'required|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $iuran = Iuran::findOrFail($id); + + if ($request->hasFile('bukti_pembayaran')) { + + $file = $request->file('bukti_pembayaran'); + $namaFile = time().'.'.$file->getClientOriginalExtension(); + + $file->move(public_path('bukti'), $namaFile); + + $iuran->update([ + 'bukti_pembayaran' => $namaFile, + 'status' => 'menunggu' // fix: dulu salah jadi 'belum' + ]); + + // Catat otomatis ke kas bendahara (uang masuk) + if ($iuran->dibuat_oleh) { + \App\Models\KasBendahara::create([ + 'bendahara_id' => $iuran->dibuat_oleh, + 'rt_id' => $iuran->rt_id, + 'jenis' => 'masuk', + 'jumlah' => $iuran->jumlah, + 'keterangan' => 'Upload bukti transfer - ' . $iuran->jenis_iuran . ' (' . $iuran->bulan . ' ' . $iuran->tahun . ')', + 'iuran_id' => $iuran->id, + ]); + } + } + + return redirect()->route('user.iuran.index') + ->with('success', 'Bukti berhasil diupload, menunggu konfirmasi bendahara & RT'); + } + + public function status() + { + $penghuni = \App\Models\Penghuni::where('email', Auth::user()->email)->first(); + + $iuran = Iuran::where('penghuni_id', $penghuni->id)->get(); + + return view('user.iuran.status', compact('iuran')); + } + + public function delete($id) + { + // ambil data dari session + $hidden = session()->get('hidden_iuran', []); + + // tambahkan id ke list hidden + $hidden[] = $id; + + // simpan kembali ke session + session()->put('hidden_iuran', $hidden); + + return back()->with('success', 'Data disembunyikan dari halaman ini'); + } +} diff --git a/.history/app/Http/Controllers/UserIuranController_20260619101939.php b/.history/app/Http/Controllers/UserIuranController_20260619101939.php new file mode 100644 index 0000000..8bcabab --- /dev/null +++ b/.history/app/Http/Controllers/UserIuranController_20260619101939.php @@ -0,0 +1,130 @@ +email)->first(); + + if (!$penghuni) { + return back()->with('error', 'Data penghuni tidak ditemukan'); + } + + // Hanya tampilkan iuran yang sudah disetujui RT (bukan 'diajukan' atau 'ditolak') + $iuran = Iuran::where('penghuni_id', $penghuni->id) + ->whereIn('status', ['aktif', 'menunggu', 'lunas']) + ->get(); + + if ($penghuni && $penghuni->status_huni == 'Kontrak' && $penghuni->tanggal_keluar) { + if (now()->gt($penghuni->tanggal_keluar)) { + return redirect()->route('user.home') + ->with('error', 'Kontrak Anda telah berakhir!'); + } + } + + return view('user.iuran.index', compact('iuran')); + } + + public function bayarQris($id) + { + $iuran = Iuran::findOrFail($id); + + $iuran->update([ + 'status' => 'menunggu', + 'metode' => 'qris', + 'tanggal_bayar' => now() + ]); + + // Catat otomatis ke kas bendahara (uang masuk) + if ($iuran->dibuat_oleh) { + \App\Models\KasBendahara::create([ + 'bendahara_id' => $iuran->dibuat_oleh, + 'rt_id' => $iuran->rt_id, + 'jenis' => 'masuk', + 'jumlah' => $iuran->jumlah, + 'keterangan' => 'Pembayaran QRIS - ' . $iuran->jenis_iuran . ' (' . $iuran->bulan . ' ' . $iuran->tahun . ')', + 'iuran_id' => $iuran->id, + ]); + } + + return response()->json([ + 'success' => true + ]); + } + + // 🔥 HALAMAN UPLOAD + public function upload($id) + { + $iuran = Iuran::findOrFail($id); + return view('user.iuran.upload', compact('iuran')); + } + + // 🔥 SIMPAN BUKTI + // 🔥 SIMPAN BUKTI + public function storeUpload(Request $request, $id) + { + $request->validate([ + 'bukti_pembayaran' => 'required|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $iuran = Iuran::findOrFail($id); + + if ($request->hasFile('bukti_pembayaran')) { + + $file = $request->file('bukti_pembayaran'); + $namaFile = time().'.'.$file->getClientOriginalExtension(); + + $file->move(public_path('bukti'), $namaFile); + + $iuran->update([ + 'bukti_pembayaran' => $namaFile, + 'status' => 'menunggu' // fix: dulu salah jadi 'belum' + ]); + + // Catat otomatis ke kas bendahara (uang masuk) + if ($iuran->dibuat_oleh) { + \App\Models\KasBendahara::create([ + 'bendahara_id' => $iuran->dibuat_oleh, + 'rt_id' => $iuran->rt_id, + 'jenis' => 'masuk', + 'jumlah' => $iuran->jumlah, + 'keterangan' => 'Upload bukti transfer - ' . $iuran->jenis_iuran . ' (' . $iuran->bulan . ' ' . $iuran->tahun . ')', + 'iuran_id' => $iuran->id, + ]); + } + } + + return redirect()->route('user.iuran.index') + ->with('success', 'Bukti berhasil diupload, menunggu konfirmasi bendahara & RT'); + } + + public function status() + { + $penghuni = \App\Models\Penghuni::where('email', Auth::user()->email)->first(); + + $iuran = Iuran::where('penghuni_id', $penghuni->id)->get(); + + return view('user.iuran.status', compact('iuran')); + } + + public function delete($id) + { + // ambil data dari session + $hidden = session()->get('hidden_iuran', []); + + // tambahkan id ke list hidden + $hidden[] = $id; + + // simpan kembali ke session + session()->put('hidden_iuran', $hidden); + + return back()->with('success', 'Data disembunyikan dari halaman ini'); + } +} diff --git a/.history/app/Http/Controllers/UserIuranController_20260619101940.php b/.history/app/Http/Controllers/UserIuranController_20260619101940.php new file mode 100644 index 0000000..1bb2986 --- /dev/null +++ b/.history/app/Http/Controllers/UserIuranController_20260619101940.php @@ -0,0 +1,130 @@ +email)->first(); + + if (!$penghuni) { + return back()->with('error', 'Data penghuni tidak ditemukan'); + } + + // Hanya tampilkan iuran yang sudah disetujui RT (bukan 'diajukan' atau 'ditolak') + $iuran = Iuran::where('penghuni_id', $penghuni->id) + ->whereIn('status', ['aktif', 'menunggu', 'lunas']) + ->get(); + + if ($penghuni && $penghuni->status_huni == 'Kontrak' && $penghuni->tanggal_keluar) { + if (now()->gt($penghuni->tanggal_keluar)) { + return redirect()->route('user.home') + ->with('error', 'Kontrak Anda telah berakhir!'); + } + } + + return view('user.iuran.index', compact('iuran')); + } + + public function bayarQris($id) + { + $iuran = Iuran::findOrFail($id); + + $iuran->update([ + 'status' => 'menunggu', + 'metode' => 'qris', + 'tanggal_bayar' => now() + ]); + + // Catat otomatis ke kas bendahara (uang masuk) + if ($iuran->dibuat_oleh) { + \App\Models\KasBendahara::create([ + 'bendahara_id' => $iuran->dibuat_oleh, + 'rt_id' => $iuran->rt_id, + 'jenis' => 'masuk', + 'jumlah' => $iuran->jumlah, + 'keterangan' => 'Pembayaran QRIS - ' . $iuran->jenis_iuran . ' (' . $iuran->bulan . ' ' . $iuran->tahun . ')', + 'iuran_id' => $iuran->id, + ]); + } + + return response()->json([ + 'success' => true + ]); + } + + // 🔥 HALAMAN UPLOAD + public function upload($id) + { + $iuran = Iuran::findOrFail($id); + return view('user.iuran.upload', compact('iuran')); + } + + // 🔥 SIMPAN BUKTI + // 🔥 SIMPAN BUKTI + public function storeUpload(Request $request, $id) + { + $request->validate([ + 'bukti_pembayaran' => 'required|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $iuran = Iuran::findOrFail($id); + + if ($request->hasFile('bukti_pembayaran')) { + + $file = $request->file('bukti_pembayaran'); + $namaFile = time().'.'.$file->getClientOriginalExtension(); + + $file->move(public_path('bukti'), $namaFile); + + $iuran->update([ + 'bukti_pembayaran' => $namaFile, + 'status' => 'menunggu' // fix: dulu salah jadi 'belum' + ]); + + // Catat otomatis ke kas bendahara (uang masuk) + if ($iuran->dibuat_oleh) { + \App\Models\KasBendahara::create([ + 'bendahara_id' => $iuran->dibuat_oleh, + 'rt_id' => $iuran->rt_id, + 'jenis' => 'masuk', + 'jumlah' => $iuran->jumlah, + 'keterangan' => 'Upload bukti transfer - ' . $iuran->jenis_iuran . ' (' . $iuran->bulan . ' ' . $iuran->tahun . ')', + 'iuran_id' => $iuran->id, + ]); + } + } + + return redirect()->route('user.iuran.index') + ->with('success', 'Bukti berhasil diupload, menunggu konfirmasi bendahara & RT'); + } + + public function status() + { + $penghuni = \App\Models\Penghuni::where('email', Auth::user()->email)->first(); + + $iuran = Iuran::where('penghuni_id', $penghuni->id)->get(); + + return view('user.iuran.status', compact('iuran')); + } + + public function delete($id) + { + // ambil data dari session + $hidden = session()->get('hidden_iuran', []); + + // tambahkan id ke list hidden + $hidden[] = $id; + + // simpan kembali ke session + session()->put('hidden_iuran', $hidden); + + return back()->with('success', 'Data disembunyikan dari halaman ini'); + } +} diff --git a/.history/app/Http/Controllers/UserIuranController_20260619213550.php b/.history/app/Http/Controllers/UserIuranController_20260619213550.php new file mode 100644 index 0000000..b6cbdd3 --- /dev/null +++ b/.history/app/Http/Controllers/UserIuranController_20260619213550.php @@ -0,0 +1,132 @@ +email)->first(); + + if (!$penghuni) { + return back()->with('error', 'Data penghuni tidak ditemukan'); + } + + // Hanya tampilkan iuran yang sudah disetujui RT (bukan 'diajukan' atau 'ditolak') + $iuran = Iuran::where('penghuni_id', $penghuni->id) + ->whereIn('status', ['aktif', 'menunggu', 'lunas']) + ->get(); + + + + if ($penghuni && $penghuni->status_huni == 'Kontrak' && $penghuni->tanggal_keluar) { + if (now()->gt($penghuni->tanggal_keluar)) { + return redirect()->route('user.home') + ->with('error', 'Kontrak Anda telah berakhir!'); + } + } + + return view('user.iuran.index', compact('iuran')); + } + + public function bayarQris($id) + { + $iuran = Iuran::findOrFail($id); + + $iuran->update([ + 'status' => 'menunggu', + 'metode' => 'qris', + 'tanggal_bayar' => now() + ]); + + // Catat otomatis ke kas bendahara (uang masuk) + if ($iuran->dibuat_oleh) { + \App\Models\KasBendahara::create([ + 'bendahara_id' => $iuran->dibuat_oleh, + 'rt_id' => $iuran->rt_id, + 'jenis' => 'masuk', + 'jumlah' => $iuran->jumlah, + 'keterangan' => 'Pembayaran QRIS - ' . $iuran->jenis_iuran . ' (' . $iuran->bulan . ' ' . $iuran->tahun . ')', + 'iuran_id' => $iuran->id, + ]); + } + + return response()->json([ + 'success' => true + ]); + } + + // 🔥 HALAMAN UPLOAD + public function upload($id) + { + $iuran = Iuran::findOrFail($id); + return view('user.iuran.upload', compact('iuran')); + } + + // 🔥 SIMPAN BUKTI + // 🔥 SIMPAN BUKTI + public function storeUpload(Request $request, $id) + { + $request->validate([ + 'bukti_pembayaran' => 'required|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $iuran = Iuran::findOrFail($id); + + if ($request->hasFile('bukti_pembayaran')) { + + $file = $request->file('bukti_pembayaran'); + $namaFile = time().'.'.$file->getClientOriginalExtension(); + + $file->move(public_path('bukti'), $namaFile); + + $iuran->update([ + 'bukti_pembayaran' => $namaFile, + 'status' => 'menunggu' // fix: dulu salah jadi 'belum' + ]); + + // Catat otomatis ke kas bendahara (uang masuk) + if ($iuran->dibuat_oleh) { + \App\Models\KasBendahara::create([ + 'bendahara_id' => $iuran->dibuat_oleh, + 'rt_id' => $iuran->rt_id, + 'jenis' => 'masuk', + 'jumlah' => $iuran->jumlah, + 'keterangan' => 'Upload bukti transfer - ' . $iuran->jenis_iuran . ' (' . $iuran->bulan . ' ' . $iuran->tahun . ')', + 'iuran_id' => $iuran->id, + ]); + } + } + + return redirect()->route('user.iuran.index') + ->with('success', 'Bukti berhasil diupload, menunggu konfirmasi bendahara & RT'); + } + + public function status() + { + $penghuni = \App\Models\Penghuni::where('email', Auth::user()->email)->first(); + + $iuran = Iuran::where('penghuni_id', $penghuni->id)->get(); + + return view('user.iuran.status', compact('iuran')); + } + + public function delete($id) + { + // ambil data dari session + $hidden = session()->get('hidden_iuran', []); + + // tambahkan id ke list hidden + $hidden[] = $id; + + // simpan kembali ke session + session()->put('hidden_iuran', $hidden); + + return back()->with('success', 'Data disembunyikan dari halaman ini'); + } +} diff --git a/.history/app/Http/Controllers/UserIuranController_20260619213554.php b/.history/app/Http/Controllers/UserIuranController_20260619213554.php new file mode 100644 index 0000000..151cbe6 --- /dev/null +++ b/.history/app/Http/Controllers/UserIuranController_20260619213554.php @@ -0,0 +1,134 @@ +email)->first(); + + if (!$penghuni) { + return back()->with('error', 'Data penghuni tidak ditemukan'); + } + + // Hanya tampilkan iuran yang sudah disetujui RT (bukan 'diajukan' atau 'ditolak') + $iuran = Iuran::where('penghuni_id', $penghuni->id) + ->whereIn('status', ['aktif', 'menunggu', 'lunas']) + ->get(); + + $kas = \App\Models\KasBendahara::where('penghuni_id', $penghuni->id) + ->whereIn('status', ['menunggu_bayar', 'menunggu_konfirmasi', 'lunas']) + ->get(); + + if ($penghuni && $penghuni->status_huni == 'Kontrak' && $penghuni->tanggal_keluar) { + if (now()->gt($penghuni->tanggal_keluar)) { + return redirect()->route('user.home') + ->with('error', 'Kontrak Anda telah berakhir!'); + } + } + + return view('user.iuran.index', compact('iuran')); + } + + public function bayarQris($id) + { + $iuran = Iuran::findOrFail($id); + + $iuran->update([ + 'status' => 'menunggu', + 'metode' => 'qris', + 'tanggal_bayar' => now() + ]); + + // Catat otomatis ke kas bendahara (uang masuk) + if ($iuran->dibuat_oleh) { + \App\Models\KasBendahara::create([ + 'bendahara_id' => $iuran->dibuat_oleh, + 'rt_id' => $iuran->rt_id, + 'jenis' => 'masuk', + 'jumlah' => $iuran->jumlah, + 'keterangan' => 'Pembayaran QRIS - ' . $iuran->jenis_iuran . ' (' . $iuran->bulan . ' ' . $iuran->tahun . ')', + 'iuran_id' => $iuran->id, + ]); + } + + return response()->json([ + 'success' => true + ]); + } + + // 🔥 HALAMAN UPLOAD + public function upload($id) + { + $iuran = Iuran::findOrFail($id); + return view('user.iuran.upload', compact('iuran')); + } + + // 🔥 SIMPAN BUKTI + // 🔥 SIMPAN BUKTI + public function storeUpload(Request $request, $id) + { + $request->validate([ + 'bukti_pembayaran' => 'required|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $iuran = Iuran::findOrFail($id); + + if ($request->hasFile('bukti_pembayaran')) { + + $file = $request->file('bukti_pembayaran'); + $namaFile = time().'.'.$file->getClientOriginalExtension(); + + $file->move(public_path('bukti'), $namaFile); + + $iuran->update([ + 'bukti_pembayaran' => $namaFile, + 'status' => 'menunggu' // fix: dulu salah jadi 'belum' + ]); + + // Catat otomatis ke kas bendahara (uang masuk) + if ($iuran->dibuat_oleh) { + \App\Models\KasBendahara::create([ + 'bendahara_id' => $iuran->dibuat_oleh, + 'rt_id' => $iuran->rt_id, + 'jenis' => 'masuk', + 'jumlah' => $iuran->jumlah, + 'keterangan' => 'Upload bukti transfer - ' . $iuran->jenis_iuran . ' (' . $iuran->bulan . ' ' . $iuran->tahun . ')', + 'iuran_id' => $iuran->id, + ]); + } + } + + return redirect()->route('user.iuran.index') + ->with('success', 'Bukti berhasil diupload, menunggu konfirmasi bendahara & RT'); + } + + public function status() + { + $penghuni = \App\Models\Penghuni::where('email', Auth::user()->email)->first(); + + $iuran = Iuran::where('penghuni_id', $penghuni->id)->get(); + + return view('user.iuran.status', compact('iuran')); + } + + public function delete($id) + { + // ambil data dari session + $hidden = session()->get('hidden_iuran', []); + + // tambahkan id ke list hidden + $hidden[] = $id; + + // simpan kembali ke session + session()->put('hidden_iuran', $hidden); + + return back()->with('success', 'Data disembunyikan dari halaman ini'); + } +} diff --git a/.history/app/Http/Controllers/UserIuranController_20260619213608.php b/.history/app/Http/Controllers/UserIuranController_20260619213608.php new file mode 100644 index 0000000..4c6759d --- /dev/null +++ b/.history/app/Http/Controllers/UserIuranController_20260619213608.php @@ -0,0 +1,134 @@ +email)->first(); + + if (!$penghuni) { + return back()->with('error', 'Data penghuni tidak ditemukan'); + } + + // Hanya tampilkan iuran yang sudah disetujui RT (bukan 'diajukan' atau 'ditolak') + $iuran = Iuran::where('penghuni_id', $penghuni->id) + ->whereIn('status', ['aktif', 'menunggu', 'lunas']) + ->get(); + + $kas = \App\Models\KasBendahara::where('penghuni_id', $penghuni->id) + ->whereIn('status', ['menunggu_bayar', 'menunggu_konfirmasi', 'lunas']) + ->get(); + + if ($penghuni && $penghuni->status_huni == 'Kontrak' && $penghuni->tanggal_keluar) { + if (now()->gt($penghuni->tanggal_keluar)) { + return redirect()->route('user.home') + ->with('error', 'Kontrak Anda telah berakhir!'); + } + } + + return view('user.iuran.index', compact('iuran', 'kas')); + } + + public function bayarQris($id) + { + $iuran = Iuran::findOrFail($id); + + $iuran->update([ + 'status' => 'menunggu', + 'metode' => 'qris', + 'tanggal_bayar' => now() + ]); + + // Catat otomatis ke kas bendahara (uang masuk) + if ($iuran->dibuat_oleh) { + \App\Models\KasBendahara::create([ + 'bendahara_id' => $iuran->dibuat_oleh, + 'rt_id' => $iuran->rt_id, + 'jenis' => 'masuk', + 'jumlah' => $iuran->jumlah, + 'keterangan' => 'Pembayaran QRIS - ' . $iuran->jenis_iuran . ' (' . $iuran->bulan . ' ' . $iuran->tahun . ')', + 'iuran_id' => $iuran->id, + ]); + } + + return response()->json([ + 'success' => true + ]); + } + + // 🔥 HALAMAN UPLOAD + public function upload($id) + { + $iuran = Iuran::findOrFail($id); + return view('user.iuran.upload', compact('iuran')); + } + + // 🔥 SIMPAN BUKTI + // 🔥 SIMPAN BUKTI + public function storeUpload(Request $request, $id) + { + $request->validate([ + 'bukti_pembayaran' => 'required|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $iuran = Iuran::findOrFail($id); + + if ($request->hasFile('bukti_pembayaran')) { + + $file = $request->file('bukti_pembayaran'); + $namaFile = time().'.'.$file->getClientOriginalExtension(); + + $file->move(public_path('bukti'), $namaFile); + + $iuran->update([ + 'bukti_pembayaran' => $namaFile, + 'status' => 'menunggu' // fix: dulu salah jadi 'belum' + ]); + + // Catat otomatis ke kas bendahara (uang masuk) + if ($iuran->dibuat_oleh) { + \App\Models\KasBendahara::create([ + 'bendahara_id' => $iuran->dibuat_oleh, + 'rt_id' => $iuran->rt_id, + 'jenis' => 'masuk', + 'jumlah' => $iuran->jumlah, + 'keterangan' => 'Upload bukti transfer - ' . $iuran->jenis_iuran . ' (' . $iuran->bulan . ' ' . $iuran->tahun . ')', + 'iuran_id' => $iuran->id, + ]); + } + } + + return redirect()->route('user.iuran.index') + ->with('success', 'Bukti berhasil diupload, menunggu konfirmasi bendahara & RT'); + } + + public function status() + { + $penghuni = \App\Models\Penghuni::where('email', Auth::user()->email)->first(); + + $iuran = Iuran::where('penghuni_id', $penghuni->id)->get(); + + return view('user.iuran.status', compact('iuran')); + } + + public function delete($id) + { + // ambil data dari session + $hidden = session()->get('hidden_iuran', []); + + // tambahkan id ke list hidden + $hidden[] = $id; + + // simpan kembali ke session + session()->put('hidden_iuran', $hidden); + + return back()->with('success', 'Data disembunyikan dari halaman ini'); + } +} diff --git a/.history/app/Http/Controllers/UserIuranController_20260620090407.php b/.history/app/Http/Controllers/UserIuranController_20260620090407.php new file mode 100644 index 0000000..5d204cc --- /dev/null +++ b/.history/app/Http/Controllers/UserIuranController_20260620090407.php @@ -0,0 +1,122 @@ +email)->first(); + + if (!$penghuni) { + return back()->with('error', 'Data penghuni tidak ditemukan'); + } + + // Hanya tampilkan iuran yang sudah disetujui RT (bukan 'diajukan' atau 'ditolak') + $iuran = Iuran::where('penghuni_id', $penghuni->id) + ->whereIn('status', ['aktif', 'menunggu', 'lunas']) + ->get(); + + $kas = \App\Models\KasBendahara::where('penghuni_id', $penghuni->id) + ->whereIn('status', ['menunggu_bayar', 'menunggu_konfirmasi', 'lunas']) + ->get(); + + if ($penghuni && $penghuni->status_huni == 'Kontrak' && $penghuni->tanggal_keluar) { + if (now()->gt($penghuni->tanggal_keluar)) { + return redirect()->route('user.home') + ->with('error', 'Kontrak Anda telah berakhir!'); + } + } + + return view('user.iuran.index', compact('iuran', 'kas')); + } + + public function bayarQris($id) + { + $iuran = Iuran::findOrFail($id); + + $iuran->update([ + 'status' => 'menunggu', + 'metode' => 'qris', + 'tanggal_bayar' => now() + ]); + + return response()->json([ + 'success' => true + ]); + } + + // 🔥 HALAMAN UPLOAD + public function upload($id) + { + $iuran = Iuran::findOrFail($id); + return view('user.iuran.upload', compact('iuran')); + } + + // 🔥 SIMPAN BUKTI + // 🔥 SIMPAN BUKTI + public function storeUpload(Request $request, $id) + { + $request->validate([ + 'bukti_pembayaran' => 'required|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $iuran = Iuran::findOrFail($id); + + if ($request->hasFile('bukti_pembayaran')) { + + $file = $request->file('bukti_pembayaran'); + $namaFile = time().'.'.$file->getClientOriginalExtension(); + + $file->move(public_path('bukti'), $namaFile); + + $iuran->update([ + 'bukti_pembayaran' => $namaFile, + 'status' => 'menunggu' // fix: dulu salah jadi 'belum' + ]); + + // Catat otomatis ke kas bendahara (uang masuk) + if ($iuran->dibuat_oleh) { + \App\Models\KasBendahara::create([ + 'bendahara_id' => $iuran->dibuat_oleh, + 'rt_id' => $iuran->rt_id, + 'jenis' => 'masuk', + 'jumlah' => $iuran->jumlah, + 'keterangan' => 'Upload bukti transfer - ' . $iuran->jenis_iuran . ' (' . $iuran->bulan . ' ' . $iuran->tahun . ')', + 'iuran_id' => $iuran->id, + ]); + } + } + + return redirect()->route('user.iuran.index') + ->with('success', 'Bukti berhasil diupload, menunggu konfirmasi bendahara & RT'); + } + + public function status() + { + $penghuni = \App\Models\Penghuni::where('email', Auth::user()->email)->first(); + + $iuran = Iuran::where('penghuni_id', $penghuni->id)->get(); + + return view('user.iuran.status', compact('iuran')); + } + + public function delete($id) + { + // ambil data dari session + $hidden = session()->get('hidden_iuran', []); + + // tambahkan id ke list hidden + $hidden[] = $id; + + // simpan kembali ke session + session()->put('hidden_iuran', $hidden); + + return back()->with('success', 'Data disembunyikan dari halaman ini'); + } +} diff --git a/.history/app/Http/Controllers/UserIuranController_20260620090422.php b/.history/app/Http/Controllers/UserIuranController_20260620090422.php new file mode 100644 index 0000000..889c100 --- /dev/null +++ b/.history/app/Http/Controllers/UserIuranController_20260620090422.php @@ -0,0 +1,120 @@ +email)->first(); + + if (!$penghuni) { + return back()->with('error', 'Data penghuni tidak ditemukan'); + } + + // Hanya tampilkan iuran yang sudah disetujui RT (bukan 'diajukan' atau 'ditolak') + $iuran = Iuran::where('penghuni_id', $penghuni->id) + ->whereIn('status', ['aktif', 'menunggu', 'lunas']) + ->get(); + + $kas = \App\Models\KasBendahara::where('penghuni_id', $penghuni->id) + ->whereIn('status', ['menunggu_bayar', 'menunggu_konfirmasi', 'lunas']) + ->get(); + + if ($penghuni && $penghuni->status_huni == 'Kontrak' && $penghuni->tanggal_keluar) { + if (now()->gt($penghuni->tanggal_keluar)) { + return redirect()->route('user.home') + ->with('error', 'Kontrak Anda telah berakhir!'); + } + } + + return view('user.iuran.index', compact('iuran', 'kas')); + } + + public function bayarQris($id) + { + $iuran = Iuran::findOrFail($id); + + $iuran->update([ + 'status' => 'menunggu', + 'metode' => 'qris', + 'tanggal_bayar' => now() + ]); + + return response()->json([ + 'success' => true + ]); + } + + // 🔥 HALAMAN UPLOAD + public function upload($id) + { + $iuran = Iuran::findOrFail($id); + return view('user.iuran.upload', compact('iuran')); + } + // 🔥 SIMPAN BUKTI + public function storeUpload(Request $request, $id) + { + $request->validate([ + 'bukti_pembayaran' => 'required|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $iuran = Iuran::findOrFail($id); + + if ($request->hasFile('bukti_pembayaran')) { + + $file = $request->file('bukti_pembayaran'); + $namaFile = time().'.'.$file->getClientOriginalExtension(); + + $file->move(public_path('bukti'), $namaFile); + + $iuran->update([ + 'bukti_pembayaran' => $namaFile, + 'status' => 'menunggu' // fix: dulu salah jadi 'belum' + ]); + + // Catat otomatis ke kas bendahara (uang masuk) + if ($iuran->dibuat_oleh) { + \App\Models\KasBendahara::create([ + 'bendahara_id' => $iuran->dibuat_oleh, + 'rt_id' => $iuran->rt_id, + 'jenis' => 'masuk', + 'jumlah' => $iuran->jumlah, + 'keterangan' => 'Upload bukti transfer - ' . $iuran->jenis_iuran . ' (' . $iuran->bulan . ' ' . $iuran->tahun . ')', + 'iuran_id' => $iuran->id, + ]); + } + } + + return redirect()->route('user.iuran.index') + ->with('success', 'Bukti berhasil diupload, menunggu konfirmasi bendahara & RT'); + } + + public function status() + { + $penghuni = \App\Models\Penghuni::where('email', Auth::user()->email)->first(); + + $iuran = Iuran::where('penghuni_id', $penghuni->id)->get(); + + return view('user.iuran.status', compact('iuran')); + } + + public function delete($id) + { + // ambil data dari session + $hidden = session()->get('hidden_iuran', []); + + // tambahkan id ke list hidden + $hidden[] = $id; + + // simpan kembali ke session + session()->put('hidden_iuran', $hidden); + + return back()->with('success', 'Data disembunyikan dari halaman ini'); + } +} diff --git a/.history/app/Http/Controllers/UserIuranController_20260620090436.php b/.history/app/Http/Controllers/UserIuranController_20260620090436.php new file mode 100644 index 0000000..3d7b63a --- /dev/null +++ b/.history/app/Http/Controllers/UserIuranController_20260620090436.php @@ -0,0 +1,108 @@ +email)->first(); + + if (!$penghuni) { + return back()->with('error', 'Data penghuni tidak ditemukan'); + } + + // Hanya tampilkan iuran yang sudah disetujui RT (bukan 'diajukan' atau 'ditolak') + $iuran = Iuran::where('penghuni_id', $penghuni->id) + ->whereIn('status', ['aktif', 'menunggu', 'lunas']) + ->get(); + + $kas = \App\Models\KasBendahara::where('penghuni_id', $penghuni->id) + ->whereIn('status', ['menunggu_bayar', 'menunggu_konfirmasi', 'lunas']) + ->get(); + + if ($penghuni && $penghuni->status_huni == 'Kontrak' && $penghuni->tanggal_keluar) { + if (now()->gt($penghuni->tanggal_keluar)) { + return redirect()->route('user.home') + ->with('error', 'Kontrak Anda telah berakhir!'); + } + } + + return view('user.iuran.index', compact('iuran', 'kas')); + } + + public function bayarQris($id) + { + $iuran = Iuran::findOrFail($id); + + $iuran->update([ + 'status' => 'menunggu', + 'metode' => 'qris', + 'tanggal_bayar' => now() + ]); + + return response()->json([ + 'success' => true + ]); + } + + // 🔥 HALAMAN UPLOAD + public function upload($id) + { + $iuran = Iuran::findOrFail($id); + return view('user.iuran.upload', compact('iuran')); + } + // 🔥 SIMPAN BUKTI + public function storeUpload(Request $request, $id) + { + $request->validate([ + 'bukti_pembayaran' => 'required|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $iuran = Iuran::findOrFail($id); + + if ($request->hasFile('bukti_pembayaran')) { + + $file = $request->file('bukti_pembayaran'); + $namaFile = time().'.'.$file->getClientOriginalExtension(); + + $file->move(public_path('bukti'), $namaFile); + + $iuran->update([ + 'bukti_pembayaran' => $namaFile, + 'status' => 'menunggu' // fix: dulu salah jadi 'belum' + ]); + } + + return redirect()->route('user.iuran.index') + ->with('success', 'Bukti berhasil diupload, menunggu konfirmasi bendahara & RT'); + } + + public function status() + { + $penghuni = \App\Models\Penghuni::where('email', Auth::user()->email)->first(); + + $iuran = Iuran::where('penghuni_id', $penghuni->id)->get(); + + return view('user.iuran.status', compact('iuran')); + } + + public function delete($id) + { + // ambil data dari session + $hidden = session()->get('hidden_iuran', []); + + // tambahkan id ke list hidden + $hidden[] = $id; + + // simpan kembali ke session + session()->put('hidden_iuran', $hidden); + + return back()->with('success', 'Data disembunyikan dari halaman ini'); + } +} diff --git a/.history/app/Http/Controllers/UserIuranController_20260622094632.php b/.history/app/Http/Controllers/UserIuranController_20260622094632.php new file mode 100644 index 0000000..aee6126 --- /dev/null +++ b/.history/app/Http/Controllers/UserIuranController_20260622094632.php @@ -0,0 +1,110 @@ +email)->first(); + + if (!$penghuni) { + return back()->with('error', 'Data penghuni tidak ditemukan'); + } + + // Hanya tampilkan iuran yang sudah disetujui RT (bukan 'diajukan' atau 'ditolak') + $iuran = Iuran::where('penghuni_id', $penghuni->id) + ->whereIn('status', ['aktif', 'menunggu', 'lunas']) + ->get(); + + $kas = \App\Models\KasBendahara::where('penghuni_id', $penghuni->id) + ->whereIn('status', ['menunggu_bayar', 'menunggu_konfirmasi', 'lunas']) + ->get(); + + if ($penghuni && $penghuni->status_huni == 'Kontrak' && $penghuni->tanggal_keluar) { + if (now()->gt($penghuni->tanggal_keluar)) { + return redirect()->route('user.home') + ->with('error', 'Kontrak Anda telah berakhir!'); + } + } + + $totalBelumBayar = $iuran->whereIn('status', ['aktif', 'menunggu'])->sum('jumlah'); + + return view('user.iuran.index', compact('iuran', 'kas', 'totalBelumBayar')); + } + + public function bayarQris($id) + { + $iuran = Iuran::findOrFail($id); + + $iuran->update([ + 'status' => 'menunggu', + 'metode' => 'qris', + 'tanggal_bayar' => now() + ]); + + return response()->json([ + 'success' => true + ]); + } + + // 🔥 HALAMAN UPLOAD + public function upload($id) + { + $iuran = Iuran::findOrFail($id); + return view('user.iuran.upload', compact('iuran')); + } + // 🔥 SIMPAN BUKTI + public function storeUpload(Request $request, $id) + { + $request->validate([ + 'bukti_pembayaran' => 'required|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $iuran = Iuran::findOrFail($id); + + if ($request->hasFile('bukti_pembayaran')) { + + $file = $request->file('bukti_pembayaran'); + $namaFile = time().'.'.$file->getClientOriginalExtension(); + + $file->move(public_path('bukti'), $namaFile); + + $iuran->update([ + 'bukti_pembayaran' => $namaFile, + 'status' => 'menunggu' // fix: dulu salah jadi 'belum' + ]); + } + + return redirect()->route('user.iuran.index') + ->with('success', 'Bukti berhasil diupload, menunggu konfirmasi bendahara & RT'); + } + + public function status() + { + $penghuni = \App\Models\Penghuni::where('email', Auth::user()->email)->first(); + + $iuran = Iuran::where('penghuni_id', $penghuni->id)->get(); + + return view('user.iuran.status', compact('iuran')); + } + + public function delete($id) + { + // ambil data dari session + $hidden = session()->get('hidden_iuran', []); + + // tambahkan id ke list hidden + $hidden[] = $id; + + // simpan kembali ke session + session()->put('hidden_iuran', $hidden); + + return back()->with('success', 'Data disembunyikan dari halaman ini'); + } +} diff --git a/.history/app/Http/Controllers/UserKasController_20260619212656.php b/.history/app/Http/Controllers/UserKasController_20260619212656.php new file mode 100644 index 0000000..e69de29 diff --git a/.history/app/Http/Controllers/UserKasController_20260619212704.php b/.history/app/Http/Controllers/UserKasController_20260619212704.php new file mode 100644 index 0000000..1db7e37 --- /dev/null +++ b/.history/app/Http/Controllers/UserKasController_20260619212704.php @@ -0,0 +1,48 @@ +where('status', 'menunggu_bayar')->firstOrFail(); + + $kas->update([ + 'status' => 'menunggu_konfirmasi', + 'metode' => 'qris', + ]); + + return response()->json(['success' => true]); + } + + public function upload($id) + { + $kas = KasBendahara::where('id', $id)->where('status', 'menunggu_bayar')->firstOrFail(); + return view('user.kas.upload', compact('kas')); + } + + public function storeUpload(Request $request, $id) + { + $request->validate([ + 'bukti_pembayaran' => 'required|image|mimes:jpg,png,jpeg|max:2048' + ]); + + $kas = KasBendahara::where('id', $id)->where('status', 'menunggu_bayar')->firstOrFail(); + + $file = $request->file('bukti_pembayaran'); + $namaFile = time() . '_kas.' . $file->getClientOriginalExtension(); + $file->move(public_path('bukti'), $namaFile); + + $kas->update([ + 'bukti_pembayaran' => $namaFile, + 'status' => 'menunggu_konfirmasi', + 'metode' => 'upload', + ]); + + return redirect()->route('user.iuran.index')->with('success', 'Bukti kas berhasil diupload.'); + } +} diff --git a/.history/app/Http/Middleware/CheckRole_20260619003211.php b/.history/app/Http/Middleware/CheckRole_20260619003211.php new file mode 100644 index 0000000..e69de29 diff --git a/.history/app/Http/Middleware/CheckRole_20260619003234.php b/.history/app/Http/Middleware/CheckRole_20260619003234.php new file mode 100644 index 0000000..69653ff --- /dev/null +++ b/.history/app/Http/Middleware/CheckRole_20260619003234.php @@ -0,0 +1,23 @@ +route('login'); + } + + if (!in_array(Auth::user()->role, $roles)) { + abort(403, 'Akses tidak diizinkan.'); + } + + return $next($request); + } +} diff --git a/.history/app/Http/Middleware/CheckStatusAkun_20260619003128.php b/.history/app/Http/Middleware/CheckStatusAkun_20260619003128.php new file mode 100644 index 0000000..e69de29 diff --git a/.history/app/Http/Middleware/CheckStatusAkun_20260619003152.php b/.history/app/Http/Middleware/CheckStatusAkun_20260619003152.php new file mode 100644 index 0000000..e64e741 --- /dev/null +++ b/.history/app/Http/Middleware/CheckStatusAkun_20260619003152.php @@ -0,0 +1,21 @@ +status_akun === 'nonaktif') { + Auth::logout(); + return redirect()->route('login') + ->withErrors(['login' => 'Akun kamu telah dinonaktifkan. Hubungi RT kamu.']); + } + + return $next($request); + } +} diff --git a/.history/app/Http/Middleware/CheckStatusAkun_20260619003159.php b/.history/app/Http/Middleware/CheckStatusAkun_20260619003159.php new file mode 100644 index 0000000..e64e741 --- /dev/null +++ b/.history/app/Http/Middleware/CheckStatusAkun_20260619003159.php @@ -0,0 +1,21 @@ +status_akun === 'nonaktif') { + Auth::logout(); + return redirect()->route('login') + ->withErrors(['login' => 'Akun kamu telah dinonaktifkan. Hubungi RT kamu.']); + } + + return $next($request); + } +} diff --git a/.history/app/Http/Middleware/ForcePasswordChange_20260619110357.php b/.history/app/Http/Middleware/ForcePasswordChange_20260619110357.php new file mode 100644 index 0000000..e69de29 diff --git a/.history/app/Http/Middleware/ForcePasswordChange_20260619110404.php b/.history/app/Http/Middleware/ForcePasswordChange_20260619110404.php new file mode 100644 index 0000000..49b724f --- /dev/null +++ b/.history/app/Http/Middleware/ForcePasswordChange_20260619110404.php @@ -0,0 +1,25 @@ +wajib_ganti_password) { + // Izinkan akses ke halaman ganti password itu sendiri + logout, supaya tidak infinite redirect + if (!$request->routeIs('bendahara.ganti-password.*') && !$request->routeIs('logout')) { + return redirect()->route('bendahara.ganti-password.form') + ->withErrors(['password' => 'Kamu wajib mengganti password sebelum melanjutkan.']); + } + } + + return $next($request); + } +} diff --git a/.history/app/Mail/NotifPengaduanSelesai_20260625013755.php b/.history/app/Mail/NotifPengaduanSelesai_20260625013755.php new file mode 100644 index 0000000..e69de29 diff --git a/.history/app/Mail/NotifPengaduanSelesai_20260625015248.php b/.history/app/Mail/NotifPengaduanSelesai_20260625015248.php new file mode 100644 index 0000000..9a5e6b8 --- /dev/null +++ b/.history/app/Mail/NotifPengaduanSelesai_20260625015248.php @@ -0,0 +1,21 @@ +layanan = $layanan; + } + + public function build() + { + return $this->subject('✅ Pengaduan Anda Telah Selesai Ditangani') + ->view('emails.pengaduan_selesai'); + } +} diff --git a/.history/app/Mail/NotifPengaduan_20260413213025.php b/.history/app/Mail/NotifPengaduan_20260413213025.php new file mode 100644 index 0000000..f242302 --- /dev/null +++ b/.history/app/Mail/NotifPengaduan_20260413213025.php @@ -0,0 +1,21 @@ +layanan = $layanan; + } + + public function build() + { + return $this->subject('Update Pengaduan Anda') + ->view('emails.pengaduan'); + } +} diff --git a/.history/app/Mail/NotifPengaduan_20260625022333.php b/.history/app/Mail/NotifPengaduan_20260625022333.php new file mode 100644 index 0000000..a9cccd3 --- /dev/null +++ b/.history/app/Mail/NotifPengaduan_20260625022333.php @@ -0,0 +1,28 @@ +layanan = $layanan; + $this->tipe = $tipe; + } + + public function build() + { + if ($this->tipe === 'selesai') { + return $this->subject('✅ Pengaduan Anda Telah Selesai Ditangani') + ->view('emails.pengaduan_selesai'); + } + + return $this->subject('Update Pengaduan Anda') + ->view('emails.pengaduan'); + } +} diff --git a/.history/app/Mail/NotifPengaduan_20260625022335.php b/.history/app/Mail/NotifPengaduan_20260625022335.php new file mode 100644 index 0000000..a9cccd3 --- /dev/null +++ b/.history/app/Mail/NotifPengaduan_20260625022335.php @@ -0,0 +1,28 @@ +layanan = $layanan; + $this->tipe = $tipe; + } + + public function build() + { + if ($this->tipe === 'selesai') { + return $this->subject('✅ Pengaduan Anda Telah Selesai Ditangani') + ->view('emails.pengaduan_selesai'); + } + + return $this->subject('Update Pengaduan Anda') + ->view('emails.pengaduan'); + } +} diff --git a/.history/app/Mail/NotifPengaduan_20260625022337.php b/.history/app/Mail/NotifPengaduan_20260625022337.php new file mode 100644 index 0000000..f242302 --- /dev/null +++ b/.history/app/Mail/NotifPengaduan_20260625022337.php @@ -0,0 +1,21 @@ +layanan = $layanan; + } + + public function build() + { + return $this->subject('Update Pengaduan Anda') + ->view('emails.pengaduan'); + } +} diff --git a/.history/app/Mail/NotifPengaduan_20260625022338.php b/.history/app/Mail/NotifPengaduan_20260625022338.php new file mode 100644 index 0000000..a9cccd3 --- /dev/null +++ b/.history/app/Mail/NotifPengaduan_20260625022338.php @@ -0,0 +1,28 @@ +layanan = $layanan; + $this->tipe = $tipe; + } + + public function build() + { + if ($this->tipe === 'selesai') { + return $this->subject('✅ Pengaduan Anda Telah Selesai Ditangani') + ->view('emails.pengaduan_selesai'); + } + + return $this->subject('Update Pengaduan Anda') + ->view('emails.pengaduan'); + } +} diff --git a/.history/app/Mail/NotifPengaduan_20260625093324.php b/.history/app/Mail/NotifPengaduan_20260625093324.php new file mode 100644 index 0000000..a9cccd3 --- /dev/null +++ b/.history/app/Mail/NotifPengaduan_20260625093324.php @@ -0,0 +1,28 @@ +layanan = $layanan; + $this->tipe = $tipe; + } + + public function build() + { + if ($this->tipe === 'selesai') { + return $this->subject('✅ Pengaduan Anda Telah Selesai Ditangani') + ->view('emails.pengaduan_selesai'); + } + + return $this->subject('Update Pengaduan Anda') + ->view('emails.pengaduan'); + } +} diff --git a/.history/app/Models/Iuran_20260421222156.php b/.history/app/Models/Iuran_20260421222156.php new file mode 100644 index 0000000..def87bc --- /dev/null +++ b/.history/app/Models/Iuran_20260421222156.php @@ -0,0 +1,37 @@ + 'date', + ]; + + // Relasi ke penghuni + public function penghuni() + { + return $this->belongsTo(Penghuni::class, 'penghuni_id'); + } +} diff --git a/.history/app/Models/Iuran_20260618225040.php b/.history/app/Models/Iuran_20260618225040.php new file mode 100644 index 0000000..aae892b --- /dev/null +++ b/.history/app/Models/Iuran_20260618225040.php @@ -0,0 +1,50 @@ + 'date', + ]; + + // Relasi lama (tetap) + public function penghuni() + { + return $this->belongsTo(Penghuni::class, 'penghuni_id'); + } + + // Relasi baru + public function bendahara() + { + return $this->belongsTo(User::class, 'dibuat_oleh'); + } + + public function rekap() + { + return $this->belongsTo(RekapIuran::class, 'rekap_id'); + } +} diff --git a/.history/app/Models/Iuran_20260619102004.php b/.history/app/Models/Iuran_20260619102004.php new file mode 100644 index 0000000..f4fb1e4 --- /dev/null +++ b/.history/app/Models/Iuran_20260619102004.php @@ -0,0 +1,50 @@ + 'date', + ]; + + // Relasi lama (tetap) + public function penghuni() + { + return $this->belongsTo(Penghuni::class, 'penghuni_id'); + } + + // Relasi baru + public function bendahara() + { + return $this->belongsTo(User::class, 'dibuat_oleh'); + } + + public function rekap() + { + return $this->belongsTo(RekapIuran::class, 'rekap_id'); + } +}jj diff --git a/.history/app/Models/Iuran_20260619102005.php b/.history/app/Models/Iuran_20260619102005.php new file mode 100644 index 0000000..aae892b --- /dev/null +++ b/.history/app/Models/Iuran_20260619102005.php @@ -0,0 +1,50 @@ + 'date', + ]; + + // Relasi lama (tetap) + public function penghuni() + { + return $this->belongsTo(Penghuni::class, 'penghuni_id'); + } + + // Relasi baru + public function bendahara() + { + return $this->belongsTo(User::class, 'dibuat_oleh'); + } + + public function rekap() + { + return $this->belongsTo(RekapIuran::class, 'rekap_id'); + } +} diff --git a/.history/app/Models/KasBendahara_20260619101754.php b/.history/app/Models/KasBendahara_20260619101754.php new file mode 100644 index 0000000..e69de29 diff --git a/.history/app/Models/KasBendahara_20260619101758.php b/.history/app/Models/KasBendahara_20260619101758.php new file mode 100644 index 0000000..c2ccca8 --- /dev/null +++ b/.history/app/Models/KasBendahara_20260619101758.php @@ -0,0 +1,29 @@ +belongsTo(User::class, 'bendahara_id'); + } + + public function iuran() + { + return $this->belongsTo(Iuran::class, 'iuran_id'); + } +} diff --git a/.history/app/Models/KasBendahara_20260619193847.php b/.history/app/Models/KasBendahara_20260619193847.php new file mode 100644 index 0000000..5943174 --- /dev/null +++ b/.history/app/Models/KasBendahara_20260619193847.php @@ -0,0 +1,38 @@ +belongsTo(User::class, 'bendahara_id'); + } + + public function iuran() + { + return $this->belongsTo(Iuran::class, 'iuran_id'); + } + + public function penghuni() + { + return $this->belongsTo(Penghuni::class, 'penghuni_id'); + } +} diff --git a/.history/app/Models/Layanan_20260410140848.php b/.history/app/Models/Layanan_20260410140848.php new file mode 100644 index 0000000..6d2f376 --- /dev/null +++ b/.history/app/Models/Layanan_20260410140848.php @@ -0,0 +1,31 @@ +belongsTo(\App\Models\Penghuni::class); + } +} diff --git a/.history/app/Models/Layanan_20260625013618.php b/.history/app/Models/Layanan_20260625013618.php new file mode 100644 index 0000000..029556c --- /dev/null +++ b/.history/app/Models/Layanan_20260625013618.php @@ -0,0 +1,30 @@ +belongsTo(\App\Models\Penghuni::class); + } +} diff --git a/.history/app/Models/RekapIuran_20260619101721.php b/.history/app/Models/RekapIuran_20260619101721.php new file mode 100644 index 0000000..e69de29 diff --git a/.history/app/Models/RekapIuran_20260619101725.php b/.history/app/Models/RekapIuran_20260619101725.php new file mode 100644 index 0000000..853da2b --- /dev/null +++ b/.history/app/Models/RekapIuran_20260619101725.php @@ -0,0 +1,33 @@ +belongsTo(User::class, 'bendahara_id'); + } + + public function rt() + { + return $this->belongsTo(User::class, 'rt_id'); + } + + public function iurans() + { + return $this->hasMany(Iuran::class, 'rekap_id'); + } +} diff --git a/.history/app/Models/User_20260419103641.php b/.history/app/Models/User_20260419103641.php new file mode 100644 index 0000000..1ce9fc4 --- /dev/null +++ b/.history/app/Models/User_20260419103641.php @@ -0,0 +1,60 @@ + + */ + protected $fillable = [ + 'name', + 'username', + 'email', + 'password', + 'role', + 'photo', + ]; + + /** + * The attributes that should be hidden for serialization. + * + * @var array + */ + protected $hidden = [ + 'password', + 'remember_token', + ]; + + /** + * Get the attributes that should be cast. + * + * @return array + */ + protected function casts(): array + { + return [ + 'email_verified_at' => 'datetime', + 'password' => 'hashed', + ]; + } + + public function penghuni() + { + return $this->hasOne(\App\Models\Penghuni::class, 'email', 'email'); + } + + public function rumahs() + { + return $this->hasMany(\App\Models\Rumah::class, 'rt_id'); + } +} diff --git a/.history/app/Models/User_20260618224625.php b/.history/app/Models/User_20260618224625.php new file mode 100644 index 0000000..a79cdaa --- /dev/null +++ b/.history/app/Models/User_20260618224625.php @@ -0,0 +1,45 @@ +belongsTo(User::class, 'rt_id'); + } + + // RT punya banyak bendahara + public function bendaharas() + { + return $this->hasMany(User::class, 'rt_id')->where('role', 'bendahara'); + } + + // Bendahara aktif milik RT ini + public function bendaharaAktif() + { + return $this->hasOne(User::class, 'rt_id') + ->where('role', 'bendahara') + ->where('status_akun', 'aktif'); + } +} diff --git a/.history/app/Models/User_20260618224628.php b/.history/app/Models/User_20260618224628.php new file mode 100644 index 0000000..1ce9fc4 --- /dev/null +++ b/.history/app/Models/User_20260618224628.php @@ -0,0 +1,60 @@ + + */ + protected $fillable = [ + 'name', + 'username', + 'email', + 'password', + 'role', + 'photo', + ]; + + /** + * The attributes that should be hidden for serialization. + * + * @var array + */ + protected $hidden = [ + 'password', + 'remember_token', + ]; + + /** + * Get the attributes that should be cast. + * + * @return array + */ + protected function casts(): array + { + return [ + 'email_verified_at' => 'datetime', + 'password' => 'hashed', + ]; + } + + public function penghuni() + { + return $this->hasOne(\App\Models\Penghuni::class, 'email', 'email'); + } + + public function rumahs() + { + return $this->hasMany(\App\Models\Rumah::class, 'rt_id'); + } +} diff --git a/.history/app/Models/User_20260618224631.php b/.history/app/Models/User_20260618224631.php new file mode 100644 index 0000000..a79cdaa --- /dev/null +++ b/.history/app/Models/User_20260618224631.php @@ -0,0 +1,45 @@ +belongsTo(User::class, 'rt_id'); + } + + // RT punya banyak bendahara + public function bendaharas() + { + return $this->hasMany(User::class, 'rt_id')->where('role', 'bendahara'); + } + + // Bendahara aktif milik RT ini + public function bendaharaAktif() + { + return $this->hasOne(User::class, 'rt_id') + ->where('role', 'bendahara') + ->where('status_akun', 'aktif'); + } +} diff --git a/.history/app/Models/User_20260618224635.php b/.history/app/Models/User_20260618224635.php new file mode 100644 index 0000000..a79cdaa --- /dev/null +++ b/.history/app/Models/User_20260618224635.php @@ -0,0 +1,45 @@ +belongsTo(User::class, 'rt_id'); + } + + // RT punya banyak bendahara + public function bendaharas() + { + return $this->hasMany(User::class, 'rt_id')->where('role', 'bendahara'); + } + + // Bendahara aktif milik RT ini + public function bendaharaAktif() + { + return $this->hasOne(User::class, 'rt_id') + ->where('role', 'bendahara') + ->where('status_akun', 'aktif'); + } +} diff --git a/.history/app/Models/User_20260618224638.php b/.history/app/Models/User_20260618224638.php new file mode 100644 index 0000000..1ce9fc4 --- /dev/null +++ b/.history/app/Models/User_20260618224638.php @@ -0,0 +1,60 @@ + + */ + protected $fillable = [ + 'name', + 'username', + 'email', + 'password', + 'role', + 'photo', + ]; + + /** + * The attributes that should be hidden for serialization. + * + * @var array + */ + protected $hidden = [ + 'password', + 'remember_token', + ]; + + /** + * Get the attributes that should be cast. + * + * @return array + */ + protected function casts(): array + { + return [ + 'email_verified_at' => 'datetime', + 'password' => 'hashed', + ]; + } + + public function penghuni() + { + return $this->hasOne(\App\Models\Penghuni::class, 'email', 'email'); + } + + public function rumahs() + { + return $this->hasMany(\App\Models\Rumah::class, 'rt_id'); + } +} diff --git a/.history/app/Models/User_20260618224642.php b/.history/app/Models/User_20260618224642.php new file mode 100644 index 0000000..a79cdaa --- /dev/null +++ b/.history/app/Models/User_20260618224642.php @@ -0,0 +1,45 @@ +belongsTo(User::class, 'rt_id'); + } + + // RT punya banyak bendahara + public function bendaharas() + { + return $this->hasMany(User::class, 'rt_id')->where('role', 'bendahara'); + } + + // Bendahara aktif milik RT ini + public function bendaharaAktif() + { + return $this->hasOne(User::class, 'rt_id') + ->where('role', 'bendahara') + ->where('status_akun', 'aktif'); + } +} diff --git a/.history/app/Models/User_20260618224646.php b/.history/app/Models/User_20260618224646.php new file mode 100644 index 0000000..a79cdaa --- /dev/null +++ b/.history/app/Models/User_20260618224646.php @@ -0,0 +1,45 @@ +belongsTo(User::class, 'rt_id'); + } + + // RT punya banyak bendahara + public function bendaharas() + { + return $this->hasMany(User::class, 'rt_id')->where('role', 'bendahara'); + } + + // Bendahara aktif milik RT ini + public function bendaharaAktif() + { + return $this->hasOne(User::class, 'rt_id') + ->where('role', 'bendahara') + ->where('status_akun', 'aktif'); + } +} diff --git a/.history/app/Models/User_20260618224650.php b/.history/app/Models/User_20260618224650.php new file mode 100644 index 0000000..a79cdaa --- /dev/null +++ b/.history/app/Models/User_20260618224650.php @@ -0,0 +1,45 @@ +belongsTo(User::class, 'rt_id'); + } + + // RT punya banyak bendahara + public function bendaharas() + { + return $this->hasMany(User::class, 'rt_id')->where('role', 'bendahara'); + } + + // Bendahara aktif milik RT ini + public function bendaharaAktif() + { + return $this->hasOne(User::class, 'rt_id') + ->where('role', 'bendahara') + ->where('status_akun', 'aktif'); + } +} diff --git a/.history/app/Models/User_20260618224652.php b/.history/app/Models/User_20260618224652.php new file mode 100644 index 0000000..1ce9fc4 --- /dev/null +++ b/.history/app/Models/User_20260618224652.php @@ -0,0 +1,60 @@ + + */ + protected $fillable = [ + 'name', + 'username', + 'email', + 'password', + 'role', + 'photo', + ]; + + /** + * The attributes that should be hidden for serialization. + * + * @var array + */ + protected $hidden = [ + 'password', + 'remember_token', + ]; + + /** + * Get the attributes that should be cast. + * + * @return array + */ + protected function casts(): array + { + return [ + 'email_verified_at' => 'datetime', + 'password' => 'hashed', + ]; + } + + public function penghuni() + { + return $this->hasOne(\App\Models\Penghuni::class, 'email', 'email'); + } + + public function rumahs() + { + return $this->hasMany(\App\Models\Rumah::class, 'rt_id'); + } +} diff --git a/.history/app/Models/User_20260618225014.php b/.history/app/Models/User_20260618225014.php new file mode 100644 index 0000000..7ac2f1a --- /dev/null +++ b/.history/app/Models/User_20260618225014.php @@ -0,0 +1,65 @@ + 'datetime', + 'password' => 'hashed', + ]; + } + + // Relasi lama (tetap) + public function penghuni() + { + return $this->hasOne(\App\Models\Penghuni::class, 'email', 'email'); + } + + public function rumahs() + { + return $this->hasMany(\App\Models\Rumah::class, 'rt_id'); + } + + // Relasi baru + public function rt() + { + return $this->belongsTo(User::class, 'rt_id'); + } + + public function bendaharas() + { + return $this->hasMany(User::class, 'rt_id')->where('role', 'bendahara'); + } + + public function bendaharaAktif() + { + return $this->hasOne(User::class, 'rt_id') + ->where('role', 'bendahara') + ->where('status_akun', 'aktif'); + } +} diff --git a/.history/app/Models/User_20260618225019.php b/.history/app/Models/User_20260618225019.php new file mode 100644 index 0000000..1ce9fc4 --- /dev/null +++ b/.history/app/Models/User_20260618225019.php @@ -0,0 +1,60 @@ + + */ + protected $fillable = [ + 'name', + 'username', + 'email', + 'password', + 'role', + 'photo', + ]; + + /** + * The attributes that should be hidden for serialization. + * + * @var array + */ + protected $hidden = [ + 'password', + 'remember_token', + ]; + + /** + * Get the attributes that should be cast. + * + * @return array + */ + protected function casts(): array + { + return [ + 'email_verified_at' => 'datetime', + 'password' => 'hashed', + ]; + } + + public function penghuni() + { + return $this->hasOne(\App\Models\Penghuni::class, 'email', 'email'); + } + + public function rumahs() + { + return $this->hasMany(\App\Models\Rumah::class, 'rt_id'); + } +} diff --git a/.history/app/Models/User_20260618225021.php b/.history/app/Models/User_20260618225021.php new file mode 100644 index 0000000..7ac2f1a --- /dev/null +++ b/.history/app/Models/User_20260618225021.php @@ -0,0 +1,65 @@ + 'datetime', + 'password' => 'hashed', + ]; + } + + // Relasi lama (tetap) + public function penghuni() + { + return $this->hasOne(\App\Models\Penghuni::class, 'email', 'email'); + } + + public function rumahs() + { + return $this->hasMany(\App\Models\Rumah::class, 'rt_id'); + } + + // Relasi baru + public function rt() + { + return $this->belongsTo(User::class, 'rt_id'); + } + + public function bendaharas() + { + return $this->hasMany(User::class, 'rt_id')->where('role', 'bendahara'); + } + + public function bendaharaAktif() + { + return $this->hasOne(User::class, 'rt_id') + ->where('role', 'bendahara') + ->where('status_akun', 'aktif'); + } +} diff --git a/.history/app/Models/User_20260620144354.php b/.history/app/Models/User_20260620144354.php new file mode 100644 index 0000000..7a5ddf5 --- /dev/null +++ b/.history/app/Models/User_20260620144354.php @@ -0,0 +1,66 @@ + 'datetime', + 'password' => 'hashed', + ]; + } + + // Relasi lama (tetap) + public function penghuni() + { + return $this->hasOne(\App\Models\Penghuni::class, 'email', 'email'); + } + + public function rumahs() + { + return $this->hasMany(\App\Models\Rumah::class, 'rt_id'); + } + + // Relasi baru + public function rt() + { + return $this->belongsTo(User::class, 'rt_id'); + } + + public function bendaharas() + { + return $this->hasMany(User::class, 'rt_id')->where('role', 'bendahara'); + } + + public function bendaharaAktif() + { + return $this->hasOne(User::class, 'rt_id') + ->where('role', 'bendahara') + ->where('status_akun', 'aktif'); + } +} diff --git a/.history/app/Services/WhatsappService_20260524190026.php b/.history/app/Services/WhatsappService_20260524190026.php new file mode 100644 index 0000000..e69de29 diff --git a/.history/app/Services/WhatsappService_20260524190118.php b/.history/app/Services/WhatsappService_20260524190118.php new file mode 100644 index 0000000..676984e --- /dev/null +++ b/.history/app/Services/WhatsappService_20260524190118.php @@ -0,0 +1,58 @@ +// app/Services/WhatsappService.php + env('FONNTE_TOKEN'), + ])->post('https://api.fonnte.com/send', [ + 'target' => $phone, + 'message' => $message, + ]); + + $result = $response->json(); + + if ($response->successful() && isset($result['status']) && $result['status'] === true) { + return true; + } + + Log::warning('WhatsApp send failed', ['response' => $result, 'phone' => $phone]); + return false; + + } catch (\Exception $e) { + Log::error('WhatsApp service error: ' . $e->getMessage()); + return false; + } + } + + /** + * Normalisasi nomor HP ke format internasional (628xxx) + */ + public static function normalizePhone(string $phone): string + { + $phone = preg_replace('/\D/', '', $phone); // hapus non-digit + + if (str_starts_with($phone, '0')) { + $phone = '62' . substr($phone, 1); + } elseif (str_starts_with($phone, '+')) { + $phone = ltrim($phone, '+'); + } elseif (!str_starts_with($phone, '62')) { + $phone = '62' . $phone; + } + + return $phone; + } +} diff --git a/.history/app/Services/WhatsappService_20260524190126.php b/.history/app/Services/WhatsappService_20260524190126.php new file mode 100644 index 0000000..0b23f87 --- /dev/null +++ b/.history/app/Services/WhatsappService_20260524190126.php @@ -0,0 +1,58 @@ + + env('FONNTE_TOKEN'), + ])->post('https://api.fonnte.com/send', [ + 'target' => $phone, + 'message' => $message, + ]); + + $result = $response->json(); + + if ($response->successful() && isset($result['status']) && $result['status'] === true) { + return true; + } + + Log::warning('WhatsApp send failed', ['response' => $result, 'phone' => $phone]); + return false; + + } catch (\Exception $e) { + Log::error('WhatsApp service error: ' . $e->getMessage()); + return false; + } + } + + /** + * Normalisasi nomor HP ke format internasional (628xxx) + */ + public static function normalizePhone(string $phone): string + { + $phone = preg_replace('/\D/', '', $phone); // hapus non-digit + + if (str_starts_with($phone, '0')) { + $phone = '62' . substr($phone, 1); + } elseif (str_starts_with($phone, '+')) { + $phone = ltrim($phone, '+'); + } elseif (!str_starts_with($phone, '62')) { + $phone = '62' . $phone; + } + + return $phone; + } +} diff --git a/.history/app/Services/WhatsappService_20260524190129.php b/.history/app/Services/WhatsappService_20260524190129.php new file mode 100644 index 0000000..ce19872 --- /dev/null +++ b/.history/app/Services/WhatsappService_20260524190129.php @@ -0,0 +1,57 @@ + env('FONNTE_TOKEN'), + ])->post('https://api.fonnte.com/send', [ + 'target' => $phone, + 'message' => $message, + ]); + + $result = $response->json(); + + if ($response->successful() && isset($result['status']) && $result['status'] === true) { + return true; + } + + Log::warning('WhatsApp send failed', ['response' => $result, 'phone' => $phone]); + return false; + + } catch (\Exception $e) { + Log::error('WhatsApp service error: ' . $e->getMessage()); + return false; + } + } + + /** + * Normalisasi nomor HP ke format internasional (628xxx) + */ + public static function normalizePhone(string $phone): string + { + $phone = preg_replace('/\D/', '', $phone); // hapus non-digit + + if (str_starts_with($phone, '0')) { + $phone = '62' . substr($phone, 1); + } elseif (str_starts_with($phone, '+')) { + $phone = ltrim($phone, '+'); + } elseif (!str_starts_with($phone, '62')) { + $phone = '62' . $phone; + } + + return $phone; + } +} diff --git a/.history/app/Services/WhatsappService_20260524192851.php b/.history/app/Services/WhatsappService_20260524192851.php new file mode 100644 index 0000000..331ea1e --- /dev/null +++ b/.history/app/Services/WhatsappService_20260524192851.php @@ -0,0 +1,40 @@ +public static function send(string $phone, string $message): bool +{ + try { + $phone = self::normalizePhone($phone); + + $token = env('FONNTE_TOKEN'); + + // Cek token ada atau tidak + if (empty($token)) { + \Illuminate\Support\Facades\Log::error('FONNTE_TOKEN kosong di .env'); + return false; + } + + $response = \Illuminate\Support\Facades\Http::withHeaders([ + 'Authorization' => $token, + ])->post('https://api.fonnte.com/send', [ + 'target' => $phone, + 'message' => $message, + ]); + + $result = $response->json(); + + // Log semua response untuk debug + \Illuminate\Support\Facades\Log::info('Fonnte response', [ + 'phone' => $phone, + 'status' => $response->status(), + 'response' => $result, + ]); + + if ($response->successful() && isset($result['status']) && $result['status'] === true) { + return true; + } + + return false; + + } catch (\Exception $e) { + \Illuminate\Support\Facades\Log::error('WhatsApp error: ' . $e->getMessage()); + return false; + } +} diff --git a/.history/app/Services/WhatsappService_20260524192854.php b/.history/app/Services/WhatsappService_20260524192854.php new file mode 100644 index 0000000..ce19872 --- /dev/null +++ b/.history/app/Services/WhatsappService_20260524192854.php @@ -0,0 +1,57 @@ + env('FONNTE_TOKEN'), + ])->post('https://api.fonnte.com/send', [ + 'target' => $phone, + 'message' => $message, + ]); + + $result = $response->json(); + + if ($response->successful() && isset($result['status']) && $result['status'] === true) { + return true; + } + + Log::warning('WhatsApp send failed', ['response' => $result, 'phone' => $phone]); + return false; + + } catch (\Exception $e) { + Log::error('WhatsApp service error: ' . $e->getMessage()); + return false; + } + } + + /** + * Normalisasi nomor HP ke format internasional (628xxx) + */ + public static function normalizePhone(string $phone): string + { + $phone = preg_replace('/\D/', '', $phone); // hapus non-digit + + if (str_starts_with($phone, '0')) { + $phone = '62' . substr($phone, 1); + } elseif (str_starts_with($phone, '+')) { + $phone = ltrim($phone, '+'); + } elseif (!str_starts_with($phone, '62')) { + $phone = '62' . $phone; + } + + return $phone; + } +} diff --git a/.history/app/Services/WhatsappService_20260524192902.php b/.history/app/Services/WhatsappService_20260524192902.php new file mode 100644 index 0000000..51139e3 --- /dev/null +++ b/.history/app/Services/WhatsappService_20260524192902.php @@ -0,0 +1,53 @@ + $token, + ])->post('https://api.fonnte.com/send', [ + 'target' => $phone, + 'message' => $message, + ]); + + $result = $response->json(); + + // Log semua response untuk debug + \Illuminate\Support\Facades\Log::info('Fonnte response', [ + 'phone' => $phone, + 'status' => $response->status(), + 'response' => $result, + ]); + + if ($response->successful() && isset($result['status']) && $result['status'] === true) { + return true; + } + + return false; + + } catch (\Exception $e) { + \Illuminate\Support\Facades\Log::error('WhatsApp error: ' . $e->getMessage()); + return false; + } +} +} diff --git a/.history/app/Services/WhatsappService_20260524192908.php b/.history/app/Services/WhatsappService_20260524192908.php new file mode 100644 index 0000000..ce19872 --- /dev/null +++ b/.history/app/Services/WhatsappService_20260524192908.php @@ -0,0 +1,57 @@ + env('FONNTE_TOKEN'), + ])->post('https://api.fonnte.com/send', [ + 'target' => $phone, + 'message' => $message, + ]); + + $result = $response->json(); + + if ($response->successful() && isset($result['status']) && $result['status'] === true) { + return true; + } + + Log::warning('WhatsApp send failed', ['response' => $result, 'phone' => $phone]); + return false; + + } catch (\Exception $e) { + Log::error('WhatsApp service error: ' . $e->getMessage()); + return false; + } + } + + /** + * Normalisasi nomor HP ke format internasional (628xxx) + */ + public static function normalizePhone(string $phone): string + { + $phone = preg_replace('/\D/', '', $phone); // hapus non-digit + + if (str_starts_with($phone, '0')) { + $phone = '62' . substr($phone, 1); + } elseif (str_starts_with($phone, '+')) { + $phone = ltrim($phone, '+'); + } elseif (!str_starts_with($phone, '62')) { + $phone = '62' . $phone; + } + + return $phone; + } +} diff --git a/.history/app/Services/WhatsappService_20260524192910.php b/.history/app/Services/WhatsappService_20260524192910.php new file mode 100644 index 0000000..51139e3 --- /dev/null +++ b/.history/app/Services/WhatsappService_20260524192910.php @@ -0,0 +1,53 @@ + $token, + ])->post('https://api.fonnte.com/send', [ + 'target' => $phone, + 'message' => $message, + ]); + + $result = $response->json(); + + // Log semua response untuk debug + \Illuminate\Support\Facades\Log::info('Fonnte response', [ + 'phone' => $phone, + 'status' => $response->status(), + 'response' => $result, + ]); + + if ($response->successful() && isset($result['status']) && $result['status'] === true) { + return true; + } + + return false; + + } catch (\Exception $e) { + \Illuminate\Support\Facades\Log::error('WhatsApp error: ' . $e->getMessage()); + return false; + } +} +} diff --git a/.history/app/Services/WhatsappService_20260524192920.php b/.history/app/Services/WhatsappService_20260524192920.php new file mode 100644 index 0000000..9fc953f --- /dev/null +++ b/.history/app/Services/WhatsappService_20260524192920.php @@ -0,0 +1,53 @@ + $token, + ])->post('https://api.fonnte.com/send', [ + 'target' => $phone, + 'message' => $message, + ]); + + $result = $response->json(); + + // Log semua response untuk debug + \Illuminate\Support\Facades\Log::info('Fonnte response', [ + 'phone' => $phone, + 'status' => $response->status(), + 'response' => $result, + ]); + + if ($response->successful() && isset($result['status']) && $result['status'] === true) { + return true; + } + + return false; + + } catch (\Exception $e) { + \Illuminate\Support\Facades\Log::error('WhatsApp error: ' . $e->getMessage()); + return false; + } + } +} diff --git a/.history/app/Services/WhatsappService_20260524193040.php b/.history/app/Services/WhatsappService_20260524193040.php new file mode 100644 index 0000000..3bbec68 --- /dev/null +++ b/.history/app/Services/WhatsappService_20260524193040.php @@ -0,0 +1,79 @@ + $token, + ])->post('https://api.fonnte.com/send', [ + 'target' => $phone, + 'message' => $message, + ]); + + $result = $response->json(); + + Log::info('Fonnte response', [ + 'phone' => $phone, + 'status' => $response->status(), + 'response' => $result, + ]); + + if ($response->successful() && isset($result['status']) && $result['status'] === true) { + return true; + } + + Log::warning('Fonnte gagal kirim', ['response' => $result]); + return false; + + } catch (\Exception $e) { + Log::error('WhatsApp service error: ' . $e->getMessage()); + return false; + } + } + + /** + * Normalisasi nomor HP ke format internasional (628xxx) + */ + public static function normalizePhone(string $phone): string + { + $phone = preg_replace('/\D/', '', $phone); + + if (str_starts_with($phone, '0')) { + $phone = '62' . substr($phone, 1); + } elseif (str_starts_with($phone, '+')) { + $phone = ltrim($phone, '+'); + } elseif (!str_starts_with($phone, '62')) { + $phone = '62' . $phone; + } + + return $phone; + } +} diff --git a/.history/app/Services/WhatsappService_20260524195438.php b/.history/app/Services/WhatsappService_20260524195438.php new file mode 100644 index 0000000..83aa2f6 --- /dev/null +++ b/.history/app/Services/WhatsappService_20260524195438.php @@ -0,0 +1,80 @@ +withHeaders([ + 'Authorization' => $token, + ]) + ->post('https://api.fonnte.com/send', [ + 'target' => $phone, + 'message' => $message, + 'countryCode' => '62', + ]); + + $result = $response->json(); + + Log::info('Fonnte response', [ + 'phone' => $phone, + 'http_status' => $response->status(), + 'response' => $result, + ]); + + // Fonnte kadang return status sebagai bool true atau string "true" + if ($response->successful() && !empty($result['status'])) { + return true; + } + + Log::warning('Fonnte gagal kirim', [ + 'phone' => $phone, + 'response' => $result, + ]); + return false; + + } catch (\Exception $e) { + Log::error('WhatsApp service error: ' . $e->getMessage()); + return false; + } + } + + /** + * Normalisasi nomor HP ke format internasional (628xxx) + */ + public static function normalizePhone(string $phone): string + { + // Hapus semua karakter selain angka + $phone = preg_replace('/\D/', '', $phone); + + if (str_starts_with($phone, '0')) { + $phone = '62' . substr($phone, 1); + } elseif (str_starts_with($phone, '+62')) { + $phone = '62' . substr($phone, 3); + } elseif (str_starts_with($phone, '+')) { + $phone = ltrim($phone, '+'); + } elseif (!str_starts_with($phone, '62')) { + $phone = '62' . $phone; + } + + return $phone; + } +} diff --git a/.history/app/Services/WhatsappService_20260524211140.php b/.history/app/Services/WhatsappService_20260524211140.php new file mode 100644 index 0000000..85c9457 --- /dev/null +++ b/.history/app/Services/WhatsappService_20260524211140.php @@ -0,0 +1,83 @@ +withHeaders([ + 'Authorization' => $token, + ]) + ->post('https://api.fonnte.com/send', [ + 'target' => $phone, + 'message' => $message, + 'countryCode' => '62', + ]); + + $result = $response->json(); + + Log::info('[WhatsApp] Fonnte response', [ + 'phone' => $phone, + 'http_status' => $response->status(), + 'response' => $result, + ]); + + if ($response->successful() && !empty($result['status'])) { + return true; + } + + Log::warning('[WhatsApp] Fonnte gagal kirim', [ + 'phone' => $phone, + 'response' => $result, + ]); + return false; + + } catch (\Exception $e) { + Log::error('[WhatsApp] Exception: ' . $e->getMessage()); + return false; + } + } + + /** + * Normalisasi nomor HP ke format 628xxx + * Preg_replace dulu SEBELUM cek prefix + */ + public static function normalizePhone(string $phone): string + { + // Simpan original untuk cek prefix sebelum strip + $original = $phone; + + // Hapus semua karakter selain angka + $phone = preg_replace('/\D/', '', $phone); + + // Cek prefix dari string ORIGINAL (sebelum strip) + if (str_starts_with($original, '+62')) { + // +6281xxx → sudah jadi 6281xxx setelah strip, tidak perlu ubah + } elseif (str_starts_with($phone, '62')) { + // sudah benar + } elseif (str_starts_with($phone, '0')) { + $phone = '62' . substr($phone, 1); + } else { + $phone = '62' . $phone; + } + + return $phone; + } +} diff --git a/.history/bootstrap/app_20260331095420.php b/.history/bootstrap/app_20260331095420.php new file mode 100644 index 0000000..99b735e --- /dev/null +++ b/.history/bootstrap/app_20260331095420.php @@ -0,0 +1,20 @@ +withRouting( + web: __DIR__.'/../routes/web.php', + commands: __DIR__.'/../routes/console.php', + health: '/up', + ) + ->withMiddleware(function (Middleware $middleware) { + $middleware->alias([ + 'role' => \App\Http\Middleware\RoleMiddleware::class, + ]); + }) + ->withExceptions(function (Exceptions $exceptions) { + // + })->create(); diff --git a/.history/bootstrap/app_20260619003314.php b/.history/bootstrap/app_20260619003314.php new file mode 100644 index 0000000..1fc6db8 --- /dev/null +++ b/.history/bootstrap/app_20260619003314.php @@ -0,0 +1,21 @@ +withRouting( + web: __DIR__.'/../routes/web.php', + commands: __DIR__.'/../routes/console.php', + health: '/up', + ) + ->withMiddleware(function (Middleware $middleware) { + $middleware->alias([ + 'role' => \App\Http\Middleware\RoleMiddleware::class, + 'status.akun' => \App\Http\Middleware\CheckStatusAkun::class, + ]); + }) + ->withExceptions(function (Exceptions $exceptions) { + // + })->create(); diff --git a/.history/bootstrap/app_20260619110428.php b/.history/bootstrap/app_20260619110428.php new file mode 100644 index 0000000..209c60a --- /dev/null +++ b/.history/bootstrap/app_20260619110428.php @@ -0,0 +1,22 @@ +withRouting( + web: __DIR__.'/../routes/web.php', + commands: __DIR__.'/../routes/console.php', + health: '/up', + ) + ->withMiddleware(function (Middleware $middleware) { + $middleware->alias([ + 'role' => \App\Http\Middleware\RoleMiddleware::class, + 'status.akun' => \App\Http\Middleware\CheckStatusAkun::class, + 'force.password' => \App\Http\Middleware\ForcePasswordChange::class, + ]); + }) + ->withExceptions(function (Exceptions $exceptions) { + // + })->create(); diff --git a/.history/config/services_20240312205242.php b/.history/config/services_20240312205242.php new file mode 100644 index 0000000..6bb68f6 --- /dev/null +++ b/.history/config/services_20240312205242.php @@ -0,0 +1,34 @@ + [ + 'token' => env('POSTMARK_TOKEN'), + ], + + 'ses' => [ + 'key' => env('AWS_ACCESS_KEY_ID'), + 'secret' => env('AWS_SECRET_ACCESS_KEY'), + 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), + ], + + 'slack' => [ + 'notifications' => [ + 'bot_user_oauth_token' => env('SLACK_BOT_USER_OAUTH_TOKEN'), + 'channel' => env('SLACK_BOT_USER_DEFAULT_CHANNEL'), + ], + ], + +]; diff --git a/.history/config/services_20260524193111.php b/.history/config/services_20260524193111.php new file mode 100644 index 0000000..f6746ea --- /dev/null +++ b/.history/config/services_20260524193111.php @@ -0,0 +1,39 @@ + [ + 'token' => env('POSTMARK_TOKEN'), + ], + + 'ses' => [ + 'key' => env('AWS_ACCESS_KEY_ID'), + 'secret' => env('AWS_SECRET_ACCESS_KEY'), + 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), + ], + + 'slack' => [ + 'notifications' => [ + 'bot_user_oauth_token' => env('SLACK_BOT_USER_OAUTH_TOKEN'), + 'channel' => env('SLACK_BOT_USER_DEFAULT_CHANNEL'), + ], + ], + + // config/services.php — tambah di dalam array return +'fonnte' => [ + 'token' => env('FONNTE_TOKEN'), +], + +]; diff --git a/.history/config/services_20260524193115.php b/.history/config/services_20260524193115.php new file mode 100644 index 0000000..1b09fbb --- /dev/null +++ b/.history/config/services_20260524193115.php @@ -0,0 +1,39 @@ + [ + 'token' => env('POSTMARK_TOKEN'), + ], + + 'ses' => [ + 'key' => env('AWS_ACCESS_KEY_ID'), + 'secret' => env('AWS_SECRET_ACCESS_KEY'), + 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), + ], + + 'slack' => [ + 'notifications' => [ + 'bot_user_oauth_token' => env('SLACK_BOT_USER_OAUTH_TOKEN'), + 'channel' => env('SLACK_BOT_USER_DEFAULT_CHANNEL'), + ], + ], + + // config/services.php — tambah di dalam array return + 'fonnte' => [ + 'token' => env('FONNTE_TOKEN'), + ], + +]; diff --git a/.history/config/services_20260524194140.php b/.history/config/services_20260524194140.php new file mode 100644 index 0000000..e31751b --- /dev/null +++ b/.history/config/services_20260524194140.php @@ -0,0 +1,220 @@ +cat > /mnt/user-data/outputs/forgot.blade.php << 'HTMLEOF' + + + + + Lupa Password - Green View + + + + + + + +
+ +
+
+
+
+ Green View Logo + Real Estate • Bondowoso +
+ +
+
+ +
+ +
+
🔑 Reset Password
+

Lupa Password?

+

Tenang, kami akan bantu.
Masukkan email & pilih metode pengiriman OTP.

+
+ + @if(session('error')) +
{{ session('error') }}
+ @endif + @if(session('success')) +
{{ session('success') }}
+ @endif + +
+ @csrf + + {{-- Email --}} +
+
+ ✉️ + +
+
+ + {{-- Pilihan Metode OTP --}} + Kirim OTP via: +
+ + + + + +
+ + {{-- Input No HP — muncul hanya saat pilih WhatsApp --}} + + + +
+ + + +
+
+
+ + + + + diff --git a/.history/config/services_20260524194142.php b/.history/config/services_20260524194142.php new file mode 100644 index 0000000..1b09fbb --- /dev/null +++ b/.history/config/services_20260524194142.php @@ -0,0 +1,39 @@ + [ + 'token' => env('POSTMARK_TOKEN'), + ], + + 'ses' => [ + 'key' => env('AWS_ACCESS_KEY_ID'), + 'secret' => env('AWS_SECRET_ACCESS_KEY'), + 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), + ], + + 'slack' => [ + 'notifications' => [ + 'bot_user_oauth_token' => env('SLACK_BOT_USER_OAUTH_TOKEN'), + 'channel' => env('SLACK_BOT_USER_DEFAULT_CHANNEL'), + ], + ], + + // config/services.php — tambah di dalam array return + 'fonnte' => [ + 'token' => env('FONNTE_TOKEN'), + ], + +]; diff --git a/.history/config/services_20260524194146.php b/.history/config/services_20260524194146.php new file mode 100644 index 0000000..567c31d --- /dev/null +++ b/.history/config/services_20260524194146.php @@ -0,0 +1,35 @@ + [ + 'token' => env('POSTMARK_TOKEN'), + ], + + 'ses' => [ + 'key' => env('AWS_ACCESS_KEY_ID'), + 'secret' => env('AWS_SECRET_ACCESS_KEY'), + 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), + ], + + 'slack' => [ + 'notifications' => [ + 'bot_user_oauth_token' => env('SLACK_BOT_USER_OAUTH_TOKEN'), + 'channel' => env('SLACK_BOT_USER_DEFAULT_CHANNEL'), + ], + ], + + +]; diff --git a/.history/config/services_20260524212555.php b/.history/config/services_20260524212555.php new file mode 100644 index 0000000..ed56e72 --- /dev/null +++ b/.history/config/services_20260524212555.php @@ -0,0 +1,43 @@ + [ + 'token' => env('POSTMARK_TOKEN'), + ], + + 'ses' => [ + 'key' => env('AWS_ACCESS_KEY_ID'), + 'secret' => env('AWS_SECRET_ACCESS_KEY'), + 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), + ], + + 'slack' => [ + 'notifications' => [ + 'bot_user_oauth_token' => env('SLACK_BOT_USER_OAUTH_TOKEN'), + 'channel' => env('SLACK_BOT_USER_DEFAULT_CHANNEL'), + ], + ], + + 'mailgun' => ['domain' => env('MAILGUN_DOMAIN'), 'secret' => env('MAILGUN_SECRET'), 'endpoint' => env('MAILGUN_ENDPOINT', 'api.mailgun.net'), 'scheme' => 'https'], + 'postmark' => ['token' => env('POSTMARK_TOKEN')], + 'ses' => ['key' => env('AWS_ACCESS_KEY_ID'), 'secret' => env('AWS_SECRET_ACCESS_KEY'), 'region' => env('AWS_DEFAULT_REGION', 'us-east-1')], + + // ✅ TAMBAHKAN INI + 'fonnte' => [ + 'token' => env('FONNTE_TOKEN'), + ], + +]; diff --git a/.history/config/services_20260524212557.php b/.history/config/services_20260524212557.php new file mode 100644 index 0000000..f95038c --- /dev/null +++ b/.history/config/services_20260524212557.php @@ -0,0 +1,43 @@ + [ + 'token' => env('POSTMARK_TOKEN'), + ], + + 'ses' => [ + 'key' => env('AWS_ACCESS_KEY_ID'), + 'secret' => env('AWS_SECRET_ACCESS_KEY'), + 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), + ], + + 'slack' => [ + 'notifications' => [ + 'bot_user_oauth_token' => env('SLACK_BOT_USER_OAUTH_TOKEN'), + 'channel' => env('SLACK_BOT_USER_DEFAULT_CHANNEL'), + ], + ], + + 'mailgun' => ['domain' => env('MAILGUN_DOMAIN'), 'secret' => env('MAILGUN_SECRET'), 'endpoint' => env('MAILGUN_ENDPOINT', 'api.mailgun.net'), 'scheme' => 'https'], + 'postmark' => ['token' => env('POSTMARK_TOKEN')], + 'ses' => ['key' => env('AWS_ACCESS_KEY_ID'), 'secret' => env('AWS_SECRET_ACCESS_KEY'), 'region' => env('AWS_DEFAULT_REGION', 'us-east-1')], + + // ✅ TAMBAHKAN INI + 'fonnte' => [ + 'token' => env('FONNTE_TOKEN'), + ], + +]; diff --git a/.history/database/migrations/2026_04_01_084939_add_photo_to_users_table_20260401155008.php b/.history/database/migrations/2026_04_01_084939_add_photo_to_users_table_20260401155008.php new file mode 100644 index 0000000..d6229f1 --- /dev/null +++ b/.history/database/migrations/2026_04_01_084939_add_photo_to_users_table_20260401155008.php @@ -0,0 +1,28 @@ +string('photo')->nullable(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('users', function (Blueprint $table) { + // + }); + } +}; diff --git a/.history/database/migrations/2026_04_01_084939_add_photo_to_users_table_20260524185303.php b/.history/database/migrations/2026_04_01_084939_add_photo_to_users_table_20260524185303.php new file mode 100644 index 0000000..b7d45ad --- /dev/null +++ b/.history/database/migrations/2026_04_01_084939_add_photo_to_users_table_20260524185303.php @@ -0,0 +1,38 @@ +id(); + + $table->string('name'); + $table->string('username')->unique(); + $table->string('email')->unique(); + + $table->string('password'); + + $table->enum('role', ['admin', 'rt', 'user'])->default('user'); + + $table->rememberToken(); + $table->timestamps(); + + $table->string('photo', 255)->nullable(); + + $table->string('otp_code', 10)->nullable(); + $table->dateTime('otp_expired')->nullable(); + + $table->string('phone')->nullable(); + }); + } + + public function down(): void + { + Schema::dropIfExists('users'); + } +}; diff --git a/.history/database/migrations/2026_06_18_215158_alter_users_add_bendahara_fields_20260618215157.php b/.history/database/migrations/2026_06_18_215158_alter_users_add_bendahara_fields_20260618215157.php new file mode 100644 index 0000000..88fa2f3 --- /dev/null +++ b/.history/database/migrations/2026_06_18_215158_alter_users_add_bendahara_fields_20260618215157.php @@ -0,0 +1,24 @@ +unsignedBigInteger('rt_id') + ->nullable() + ->after('role'); + + // Status akun: aktif atau nonaktif + // Dipakai untuk mekanisme ganti bendahara (nonaktifkan lama, buat baru) + $table->enum('status_akun', ['aktif', 'nonaktif']) + ->default('aktif') + ->after('rt_id'); + + $table->foreign('rt_id') + ->references('id') + ->on('users') + ->onDelete('set null'); + }); + + // SQLite menyimpan enum sebagai TEXT dengan CHECK constraint. + // Karena migration awal pakai enum(['admin','user']), + // kita perlu recreate tabel agar bisa tambah nilai 'rt' dan 'bendahara'. + // TAPI karena data production mungkin sudah ada, gunakan cara aman: + // drop constraint lama dan buat ulang via raw SQL (SQLite-safe). + + // Untuk SQLite: ubah kolom role menjadi TEXT dulu (hapus CHECK lama) + // Cara paling aman di SQLite adalah lewat migrasi manual tabel sementara. + + // Cek apakah pakai SQLite + $driver = DB::getDriverName(); + + if ($driver === 'sqlite') { + // SQLite: tidak bisa ALTER COLUMN, jadi kita rebuild tabel users + // Salin data, drop, recreate dengan enum baru, salin balik + + DB::statement('PRAGMA foreign_keys = OFF'); + + DB::statement(' + CREATE TABLE users_new ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name TEXT NOT NULL, + username TEXT NOT NULL UNIQUE, + email TEXT NOT NULL UNIQUE, + password TEXT NOT NULL, + role TEXT NOT NULL DEFAULT "user" + CHECK(role IN ("admin","user","rt","bendahara")), + rt_id INTEGER REFERENCES users(id) ON DELETE SET NULL, + status_akun TEXT NOT NULL DEFAULT "aktif" + CHECK(status_akun IN ("aktif","nonaktif")), + photo TEXT, + otp_code TEXT, + otp_expired DATETIME, + remember_token TEXT, + created_at DATETIME, + updated_at DATETIME + ) + '); + + DB::statement(' + INSERT INTO users_new + (id, name, username, email, password, role, + rt_id, status_akun, photo, otp_code, otp_expired, + remember_token, created_at, updated_at) + SELECT + id, name, username, email, password, role, + NULL, "aktif", photo, otp_code, otp_expired, + remember_token, created_at, updated_at + FROM users + '); + + DB::statement('DROP TABLE users'); + DB::statement('ALTER TABLE users_new RENAME TO users'); + + DB::statement('PRAGMA foreign_keys = ON'); + + } else { + // MySQL / PostgreSQL: langsung ALTER COLUMN + DB::statement(" + ALTER TABLE users + MODIFY COLUMN role + ENUM('admin','user','rt','bendahara') NOT NULL DEFAULT 'user' + "); + } + } + + public function down(): void + { + Schema::table('users', function (Blueprint $table) { + $table->dropForeign(['rt_id']); + $table->dropColumn(['rt_id', 'status_akun']); + }); + + // Kembalikan enum role ke semula (hanya admin & user) + $driver = DB::getDriverName(); + if ($driver !== 'sqlite') { + DB::statement(" + ALTER TABLE users + MODIFY COLUMN role + ENUM('admin','user') NOT NULL DEFAULT 'user' + "); + } + } +}; diff --git a/.history/database/migrations/2026_06_18_215158_alter_users_add_bendahara_fields_20260618221428.php b/.history/database/migrations/2026_06_18_215158_alter_users_add_bendahara_fields_20260618221428.php new file mode 100644 index 0000000..a6111cb --- /dev/null +++ b/.history/database/migrations/2026_06_18_215158_alter_users_add_bendahara_fields_20260618221428.php @@ -0,0 +1,31 @@ +unsignedBigInteger('rt_id')->nullable()->after('id'); + $table->enum('status_akun', ['aktif', 'nonaktif'])->default('aktif')->after('role'); + }); + + // 2. Perluas enum role supaya include 'bendahara' + // Laravel tidak bisa langsung ubah enum, pakai raw query + DB::statement("ALTER TABLE users MODIFY COLUMN role ENUM('admin','rt','penghuni','bendahara') NOT NULL"); + } + + public function down(): void + { + Schema::table('users', function (Blueprint $table) { + $table->dropColumn(['rt_id', 'status_akun']); + }); + + DB::statement("ALTER TABLE users MODIFY COLUMN role ENUM('admin','rt','penghuni') NOT NULL"); + } +}; diff --git a/.history/database/migrations/2026_06_18_215158_alter_users_add_bendahara_fields_20260618221432.php b/.history/database/migrations/2026_06_18_215158_alter_users_add_bendahara_fields_20260618221432.php new file mode 100644 index 0000000..a6111cb --- /dev/null +++ b/.history/database/migrations/2026_06_18_215158_alter_users_add_bendahara_fields_20260618221432.php @@ -0,0 +1,31 @@ +unsignedBigInteger('rt_id')->nullable()->after('id'); + $table->enum('status_akun', ['aktif', 'nonaktif'])->default('aktif')->after('role'); + }); + + // 2. Perluas enum role supaya include 'bendahara' + // Laravel tidak bisa langsung ubah enum, pakai raw query + DB::statement("ALTER TABLE users MODIFY COLUMN role ENUM('admin','rt','penghuni','bendahara') NOT NULL"); + } + + public function down(): void + { + Schema::table('users', function (Blueprint $table) { + $table->dropColumn(['rt_id', 'status_akun']); + }); + + DB::statement("ALTER TABLE users MODIFY COLUMN role ENUM('admin','rt','penghuni') NOT NULL"); + } +}; diff --git a/.history/database/migrations/2026_06_18_215158_alter_users_add_bendahara_fields_20260618221434.php b/.history/database/migrations/2026_06_18_215158_alter_users_add_bendahara_fields_20260618221434.php new file mode 100644 index 0000000..5aad883 --- /dev/null +++ b/.history/database/migrations/2026_06_18_215158_alter_users_add_bendahara_fields_20260618221434.php @@ -0,0 +1,118 @@ +unsignedBigInteger('rt_id') + ->nullable() + ->after('role'); + + // Status akun: aktif atau nonaktif + // Dipakai untuk mekanisme ganti bendahara (nonaktifkan lama, buat baru) + $table->enum('status_akun', ['aktif', 'nonaktif']) + ->default('aktif') + ->after('rt_id'); + + $table->foreign('rt_id') + ->references('id') + ->on('users') + ->onDelete('set null'); + }); + + // SQLite menyimpan enum sebagai TEXT dengan CHECK constraint. + // Karena migration awal pakai enum(['admin','user']), + // kita perlu recreate tabel agar bisa tambah nilai 'rt' dan 'bendahara'. + // TAPI karena data production mungkin sudah ada, gunakan cara aman: + // drop constraint lama dan buat ulang via raw SQL (SQLite-safe). + + // Untuk SQLite: ubah kolom role menjadi TEXT dulu (hapus CHECK lama) + // Cara paling aman di SQLite adalah lewat migrasi manual tabel sementara. + + // Cek apakah pakai SQLite + $driver = DB::getDriverName(); + + if ($driver === 'sqlite') { + // SQLite: tidak bisa ALTER COLUMN, jadi kita rebuild tabel users + // Salin data, drop, recreate dengan enum baru, salin balik + + DB::statement('PRAGMA foreign_keys = OFF'); + + DB::statement(' + CREATE TABLE users_new ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name TEXT NOT NULL, + username TEXT NOT NULL UNIQUE, + email TEXT NOT NULL UNIQUE, + password TEXT NOT NULL, + role TEXT NOT NULL DEFAULT "user" + CHECK(role IN ("admin","user","rt","bendahara")), + rt_id INTEGER REFERENCES users(id) ON DELETE SET NULL, + status_akun TEXT NOT NULL DEFAULT "aktif" + CHECK(status_akun IN ("aktif","nonaktif")), + photo TEXT, + otp_code TEXT, + otp_expired DATETIME, + remember_token TEXT, + created_at DATETIME, + updated_at DATETIME + ) + '); + + DB::statement(' + INSERT INTO users_new + (id, name, username, email, password, role, + rt_id, status_akun, photo, otp_code, otp_expired, + remember_token, created_at, updated_at) + SELECT + id, name, username, email, password, role, + NULL, "aktif", photo, otp_code, otp_expired, + remember_token, created_at, updated_at + FROM users + '); + + DB::statement('DROP TABLE users'); + DB::statement('ALTER TABLE users_new RENAME TO users'); + + DB::statement('PRAGMA foreign_keys = ON'); + + } else { + // MySQL / PostgreSQL: langsung ALTER COLUMN + DB::statement(" + ALTER TABLE users + MODIFY COLUMN role + ENUM('admin','user','rt','bendahara') NOT NULL DEFAULT 'user' + "); + } + } + + public function down(): void + { + Schema::table('users', function (Blueprint $table) { + $table->dropForeign(['rt_id']); + $table->dropColumn(['rt_id', 'status_akun']); + }); + + // Kembalikan enum role ke semula (hanya admin & user) + $driver = DB::getDriverName(); + if ($driver !== 'sqlite') { + DB::statement(" + ALTER TABLE users + MODIFY COLUMN role + ENUM('admin','user') NOT NULL DEFAULT 'user' + "); + } + } +}; diff --git a/.history/database/migrations/2026_06_18_222120_add_bendahara_columns_to_users_table_20260618222119.php b/.history/database/migrations/2026_06_18_222120_add_bendahara_columns_to_users_table_20260618222119.php new file mode 100644 index 0000000..5773e07 --- /dev/null +++ b/.history/database/migrations/2026_06_18_222120_add_bendahara_columns_to_users_table_20260618222119.php @@ -0,0 +1,28 @@ +unsignedBigInteger('rt_id')->nullable()->after('id'); + $table->enum('status_akun', ['aktif', 'nonaktif'])->default('aktif')->after('role'); + }); + + // 2. Perluas enum role supaya include 'bendahara' + // Laravel tidak bisa langsung ubah enum, pakai raw query + DB::statement("ALTER TABLE users MODIFY COLUMN role ENUM('admin','rt','penghuni','bendahara') NOT NULL"); + } + + public function down(): void + { + Schema::table('users', function (Blueprint $table) { + $table->dropColumn(['rt_id', 'status_akun']); + }); + + DB::statement("ALTER TABLE users MODIFY COLUMN role ENUM('admin','rt','penghuni') NOT NULL"); + } +}; diff --git a/.history/database/migrations/2026_06_18_222120_add_bendahara_columns_to_users_table_20260618222527.php b/.history/database/migrations/2026_06_18_222120_add_bendahara_columns_to_users_table_20260618222527.php new file mode 100644 index 0000000..177decf --- /dev/null +++ b/.history/database/migrations/2026_06_18_222120_add_bendahara_columns_to_users_table_20260618222527.php @@ -0,0 +1,30 @@ +unsignedBigInteger('rt_id')->nullable()->after('id'); + $table->enum('status_akun', ['aktif', 'nonaktif'])->default('aktif')->after('role'); + }); + + // Tambah role bendahara ke enum role + DB::statement("ALTER TABLE users MODIFY COLUMN role ENUM('admin','rt','penghuni','bendahara') NOT NULL"); + } + + public function down(): void + { + Schema::table('users', function (Blueprint $table) { + $table->dropColumn(['rt_id', 'status_akun']); + }); + + DB::statement("ALTER TABLE users MODIFY COLUMN role ENUM('admin','rt','penghuni') NOT NULL"); + } +}; diff --git a/.history/database/migrations/2026_06_18_223156_add_bendahara_columns_to_iuran_table_20260618223155.php b/.history/database/migrations/2026_06_18_223156_add_bendahara_columns_to_iuran_table_20260618223155.php new file mode 100644 index 0000000..1cdf017 --- /dev/null +++ b/.history/database/migrations/2026_06_18_223156_add_bendahara_columns_to_iuran_table_20260618223155.php @@ -0,0 +1,28 @@ +unsignedBigInteger('dibuat_oleh')->nullable()->after('id'); + $table->text('catatan_rt')->nullable()->after('dibuat_oleh'); + $table->unsignedBigInteger('rekap_id')->nullable()->after('catatan_rt'); + }); + + // Perluas enum status iuran jadi 5 nilai + DB::statement("ALTER TABLE iuran MODIFY COLUMN status ENUM('diajukan','ditolak','aktif','menunggu','lunas') NOT NULL DEFAULT 'diajukan'"); + } + + public function down(): void + { + Schema::table('iuran', function (Blueprint $table) { + $table->dropColumn(['dibuat_oleh', 'catatan_rt', 'rekap_id']); + }); + + DB::statement("ALTER TABLE iuran MODIFY COLUMN status ENUM('belum','menunggu','lunas') NOT NULL DEFAULT 'belum'"); + } +}; diff --git a/.history/database/migrations/2026_06_18_224252_create_rekap_iuran_table_20260618224251.php b/.history/database/migrations/2026_06_18_224252_create_rekap_iuran_table_20260618224251.php new file mode 100644 index 0000000..16f0c0e --- /dev/null +++ b/.history/database/migrations/2026_06_18_224252_create_rekap_iuran_table_20260618224251.php @@ -0,0 +1,27 @@ +id(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('rekap_iuran'); + } +}; diff --git a/.history/database/migrations/2026_06_18_224252_create_rekap_iuran_table_20260618224306.php b/.history/database/migrations/2026_06_18_224252_create_rekap_iuran_table_20260618224306.php new file mode 100644 index 0000000..9fc6d67 --- /dev/null +++ b/.history/database/migrations/2026_06_18_224252_create_rekap_iuran_table_20260618224306.php @@ -0,0 +1,26 @@ +id(); + $table->unsignedBigInteger('bendahara_id'); + $table->unsignedBigInteger('rt_id'); + $table->string('periode'); // contoh: "Januari 2025" + $table->enum('status', ['diajukan', 'ditolak', 'disetujui'])->default('diajukan'); + $table->text('catatan_rt')->nullable(); + $table->timestamps(); + }); + } + + public function down(): void + { + Schema::dropIfExists('rekap_iuran'); + } +}; diff --git a/.history/database/migrations/2026_06_18_224445_create_kas_bendahara_table_20260618224444.php b/.history/database/migrations/2026_06_18_224445_create_kas_bendahara_table_20260618224444.php new file mode 100644 index 0000000..763de48 --- /dev/null +++ b/.history/database/migrations/2026_06_18_224445_create_kas_bendahara_table_20260618224444.php @@ -0,0 +1,27 @@ +id(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('kas_bendahara'); + } +}; diff --git a/.history/database/migrations/2026_06_18_224445_create_kas_bendahara_table_20260618224454.php b/.history/database/migrations/2026_06_18_224445_create_kas_bendahara_table_20260618224454.php new file mode 100644 index 0000000..a880e03 --- /dev/null +++ b/.history/database/migrations/2026_06_18_224445_create_kas_bendahara_table_20260618224454.php @@ -0,0 +1,27 @@ +id(); + $table->unsignedBigInteger('bendahara_id'); + $table->unsignedBigInteger('rt_id'); + $table->enum('jenis', ['masuk', 'keluar']); + $table->bigInteger('jumlah'); + $table->string('keterangan'); + $table->unsignedBigInteger('iuran_id')->nullable(); // otomatis dari pembayaran + $table->timestamps(); + }); + } + + public function down(): void + { + Schema::dropIfExists('kas_bendahara'); + } +}; diff --git a/.history/database/migrations/2026_06_19_104835_add_wajib_ganti_password_to_users_table_20260619104834.php b/.history/database/migrations/2026_06_19_104835_add_wajib_ganti_password_to_users_table_20260619104834.php new file mode 100644 index 0000000..5773e07 --- /dev/null +++ b/.history/database/migrations/2026_06_19_104835_add_wajib_ganti_password_to_users_table_20260619104834.php @@ -0,0 +1,28 @@ +boolean('wajib_ganti_password')->default(false)->after('status_akun'); + }); + } + + public function down(): void + { + Schema::table('users', function (Blueprint $table) { + $table->dropColumn('wajib_ganti_password'); + }); + } +}; diff --git a/.history/database/migrations/2026_06_19_193624_add_tagihan_columns_to_kas_bendahara_table_20260619193623.php b/.history/database/migrations/2026_06_19_193624_add_tagihan_columns_to_kas_bendahara_table_20260619193623.php new file mode 100644 index 0000000..e78d3d9 --- /dev/null +++ b/.history/database/migrations/2026_06_19_193624_add_tagihan_columns_to_kas_bendahara_table_20260619193623.php @@ -0,0 +1,28 @@ +unsignedBigInteger('penghuni_id')->nullable()->after('rt_id'); + $table->enum('status', ['manual', 'menunggu_bayar', 'menunggu_konfirmasi', 'lunas'])->default('manual')->after('keterangan'); + $table->string('metode')->nullable()->after('status'); + $table->string('bukti_pembayaran')->nullable()->after('metode'); + }); + } + + public function down(): void + { + Schema::table('kas_bendahara', function (Blueprint $table) { + $table->dropColumn(['penghuni_id', 'status', 'metode', 'bukti_pembayaran']); + }); + } +}; diff --git a/.history/resources/views/admin/dashboard.blade_20260510224500.php b/.history/resources/views/admin/dashboard.blade_20260622103728.php similarity index 68% rename from .history/resources/views/admin/dashboard.blade_20260510224500.php rename to .history/resources/views/admin/dashboard.blade_20260622103728.php index 69b3261..98d65e2 100644 --- a/.history/resources/views/admin/dashboard.blade_20260510224500.php +++ b/.history/resources/views/admin/dashboard.blade_20260622103728.php @@ -9,11 +9,20 @@
+ {{-- PAGE HEADER + CLOCK --}} +
+ + + + + {{-- TABEL KAS TERPISAH --}} +
+
+
+
+
+
Tagihan Kas
+

{{ $kas->count() }} tagihan kas

+
+
+
+
+ + + + + + + + + + + @forelse($kas as $k) + + + + + + + @empty + + @endforelse + +
KeteranganJumlahStatusAksi
+
+
+
+
{{ $k->keterangan }}
+
{{ $k->created_at->format('d M Y') }}
+
+
+
Rp {{ number_format($k->jumlah,0,',','.') }}
+ @if($k->status == 'lunas') +
Lunas
+ @elseif($k->status == 'menunggu_konfirmasi') + ⏳ Menunggu Konfirmasi + @else + ⚠ Belum Bayar + @endif +
+ @if($k->status == 'menunggu_bayar') + + @else + - + @endif +
Belum ada tagihan kas.
+
+
+ +{{-- ── MODAL DETAIL ── --}} +@foreach($iuran->where('status','lunas') as $i) + +@endforeach + +{{-- ── MODAL BAYAR KAS ── --}} +@foreach($kas->where('status', 'menunggu_bayar') as $k) + +@endforeach + + +@endsection diff --git a/.history/resources/views/user/iuran/index.blade_20260620141440.php b/.history/resources/views/user/iuran/index.blade_20260620141440.php new file mode 100644 index 0000000..1346776 --- /dev/null +++ b/.history/resources/views/user/iuran/index.blade_20260620141440.php @@ -0,0 +1,497 @@ +@extends('layouts.app') + +@section('content') + + +
+ + {{-- HEADER --}} +
+
+

💰 Data Iuran Saya

+

Kelola pembayaran iuran bulanan Anda

+
+ Tahun {{ date('Y') }} +
+ + {{-- STATS --}} + @php + $lunas = $iuran->where('status','lunas')->count(); + $belum = $iuran->filter(fn($x) => $x->status != 'lunas' && !$x->bukti_pembayaran)->count(); + $total = $iuran->where('status','lunas')->sum('jumlah'); + $pct = $iuran->count() > 0 ? round($lunas / $iuran->count() * 100) : 0; + @endphp +
+
+
+
{{ $lunas }}
+
Bulan Lunas
+
+
+
+
+
+
+
{{ $belum }}
+
Belum Bayar
+
+
+
+
Rp {{ number_format($total,0,',','.') }}
+
Total Dibayar
+
+
+ + {{-- MAIN GRID --}} +
+ + {{-- QRIS --}} +
+
+
Bayar via QRIS
+

Scan dengan e-wallet apapun

+
+
+
+ QRIS +
+
+ Scan menggunakan GoPay, OVO, Dana, atau e-wallet lainnya +
+
+ +
+ + {{-- TABLE --}} +
+
+
+
+
+
Riwayat Iuran
+

{{ $iuran->count() }} tagihan tahun berjalan

+
+
+
+ + + +
+
+ +
+ + + + + + + + + + + + + @forelse($iuran as $i) + + + + + {{-- TAMBAH INI --}} + + + {{-- JADI --}} + + + + + + @empty + + + + @endforelse + +
BulanJumlahJenisKeteranganStatusAksi
+
+
+
+
{{ $i->bulan }}
+
{{ $i->tahun ?? date('Y') }}
+
+
+
+
Rp {{ number_format($i->jumlah,0,',','.') }}
+
Bulanan
+
+ {{ $i->jenis_iuran ?? '-' }} + + {{ $i->keterangan ?? '-' }} + + @if($i->status == 'lunas') +
+
Lunas +
+ @elseif($i->status == 'rt') + ⏳ Menunggu Admin + @elseif($i->bukti_pembayaran) + ⏳ Menunggu Bendahara + @else + ⚠ Belum Bayar + @endif +
+ @if($i->status == 'lunas') + + @elseif($i->bukti_pembayaran) + {{-- Sudah upload bukti, sedang diproses — tidak ada aksi --}} + Sedang diproses + @else + + Bayar + + @endif +
+
+
💳
+
Belum Ada Data Iuran
+

Data iuran Anda akan muncul di sini

+
+
+
+
+ +
+
+ + + + + + + + {{-- TABEL KAS TERPISAH --}} +
+
+
+
+
+
Tagihan Kas
+

{{ $kas->count() }} tagihan kas

+
+
+
+
+ + + + + + + + + + + @forelse($kas as $k) + + + + + + + @empty + + @endforelse + +
KeteranganJumlahStatusAksi
+
+
+
+
{{ $k->keterangan }}
+
{{ $k->created_at->format('d M Y') }}
+
+
+
Rp {{ number_format($k->jumlah,0,',','.') }}
+ @if($k->status == 'lunas') +
Lunas
+ @elseif($k->status == 'menunggu_konfirmasi') + ⏳ Menunggu Konfirmasi + @else + ⚠ Belum Bayar + @endif +
+ @if($k->status == 'menunggu_bayar') + + @else + - + @endif +
Belum ada tagihan kas.
+
+
+ +{{-- ── MODAL DETAIL ── --}} +@foreach($iuran->where('status','lunas') as $i) + +@endforeach + +{{-- ── MODAL BAYAR KAS ── --}} +@foreach($kas->where('status', 'menunggu_bayar') as $k) + +@endforeach + + +@endsection diff --git a/.history/resources/views/user/iuran/index.blade_20260620141441.php b/.history/resources/views/user/iuran/index.blade_20260620141441.php new file mode 100644 index 0000000..baec511 --- /dev/null +++ b/.history/resources/views/user/iuran/index.blade_20260620141441.php @@ -0,0 +1,497 @@ +@extends('layouts.app') + +@section('content') + + +
+ + {{-- HEADER --}} +
+
+

💰 Data Iuran Saya

+

Kelola pembayaran iuran bulanan Anda

+
+ Tahun {{ date('Y') }} +
+ + {{-- STATS --}} + @php + $lunas = $iuran->where('status','lunas')->count(); + $belum = $iuran->filter(fn($x) => $x->status != 'lunas' && !$x->bukti_pembayaran)->count(); + $total = $iuran->where('status','lunas')->sum('jumlah'); + $pct = $iuran->count() > 0 ? round($lunas / $iuran->count() * 100) : 0; + @endphp +
+
+
+
{{ $lunas }}
+
Bulan Lunas
+
+
+
+
+
+
+
{{ $belum }}
+
Belum Bayar
+
+
+
+
Rp {{ number_format($total,0,',','.') }}
+
Total Dibayar
+
+
+ + {{-- MAIN GRID --}} +
+ + {{-- QRIS --}} +
+
+
Bayar via QRIS
+

Scan dengan e-wallet apapun

+
+
+
+ QRIS +
+
+ Scan menggunakan GoPay, OVO, Dana, atau e-wallet lainnya +
+
+ +
+ + {{-- TABLE --}} +
+
+
+
+
+
Riwayat Iuran
+

{{ $iuran->count() }} tagihan tahun berjalan

+
+
+
+ + + +
+
+ +
+ + + + + + + + + + + + + @forelse($iuran as $i) + + + + + {{-- TAMBAH INI --}} + + + {{-- JADI --}} + + + + + + @empty + + + + @endforelse + +
BulanJumlahJenisKeteranganStatusAksi
+
+
+
+
{{ $i->bulan }}
+
{{ $i->tahun ?? date('Y') }}
+
+
+
+
Rp {{ number_format($i->jumlah,0,',','.') }}
+
Bulanan
+
+ {{ $i->jenis_iuran ?? '-' }} + + {{ $i->keterangan ?? '-' }} + + @if($i->status == 'lunas') +
+
Lunas +
+ @elseif($i->status == 'rt') + ⏳ Menunggu Admin + @elseif($i->bukti_pembayaran) + ⏳ Menunggu Bendahara + @else + ⚠ Belum Bayar + @endif +
+ @if($i->status == 'lunas') + + @elseif($i->bukti_pembayaran) + {{-- Sudah upload bukti, sedang diproses — tidak ada aksi --}} + Sedang diproses + @else + + Bayar + + @endif +
+
+
💳
+
Belum Ada Data Iuran
+

Data iuran Anda akan muncul di sini

+
+
+
+
+ +
+
+ + + + + + + + {{-- TABEL KAS TERPISAH --}} +
+
+
+
+
+
Tagihan Kas
+

{{ $kas->count() }} tagihan kas

+
+
+
+
+ + + + + + + + + + + @forelse($kas as $k) + + + + + + + @empty + + @endforelse + +
KeteranganJumlahStatusAksi
+
+
+
+
{{ $k->keterangan }}
+
{{ $k->created_at->format('d M Y') }}
+
+
+
Rp {{ number_format($k->jumlah,0,',','.') }}
+ @if($k->status == 'lunas') +
Lunas
+ @elseif($k->status == 'menunggu_konfirmasi') + ⏳ Menunggu Konfirmasi + @else + ⚠ Belum Bayar + @endif +
+ @if($k->status == 'menunggu_bayar') + + @else + - + @endif +
Belum ada tagihan kas.
+
+
+ +{{-- ── MODAL DETAIL ── --}} +@foreach($iuran->where('status','lunas') as $i) + +@endforeach + +{{-- ── MODAL BAYAR KAS ── --}} +@foreach($kas->where('status', 'menunggu_bayar') as $k) + +@endforeach + + +@endsection diff --git a/.history/resources/views/user/iuran/index.blade_20260622094706.php b/.history/resources/views/user/iuran/index.blade_20260622094706.php new file mode 100644 index 0000000..e383510 --- /dev/null +++ b/.history/resources/views/user/iuran/index.blade_20260622094706.php @@ -0,0 +1,502 @@ +@extends('layouts.app') + +@section('content') + + +
+ + {{-- HEADER --}} +
+
+

💰 Data Iuran Saya

+

Kelola pembayaran iuran bulanan Anda

+
+ Tahun {{ date('Y') }} +
+ + {{-- STATS --}} + @php + $lunas = $iuran->where('status','lunas')->count(); + $belum = $iuran->filter(fn($x) => $x->status != 'lunas' && !$x->bukti_pembayaran)->count(); + $total = $iuran->where('status','lunas')->sum('jumlah'); + $pct = $iuran->count() > 0 ? round($lunas / $iuran->count() * 100) : 0; + @endphp +
+
+
+
{{ $lunas }}
+
Bulan Lunas
+
+
+
+
+
+
+
{{ $belum }}
+
Belum Bayar
+
+
+
+
Rp {{ number_format($total,0,',','.') }}
+
Total Dibayar
+
+
+
+
Rp {{ number_format($totalBelumBayar,0,',','.') }}
+
Total Belum Bayar
+
+
+ + {{-- MAIN GRID --}} +
+ + {{-- QRIS --}} +
+
+
Bayar via QRIS
+

Scan dengan e-wallet apapun

+
+
+
+ QRIS +
+
+ Scan menggunakan GoPay, OVO, Dana, atau e-wallet lainnya +
+
+ +
+ + {{-- TABLE --}} +
+
+
+
+
+
Riwayat Iuran
+

{{ $iuran->count() }} tagihan tahun berjalan

+
+
+
+ + + +
+
+ +
+ + + + + + + + + + + + + @forelse($iuran as $i) + + + + + {{-- TAMBAH INI --}} + + + {{-- JADI --}} + + + + + + @empty + + + + @endforelse + +
BulanJumlahJenisKeteranganStatusAksi
+
+
+
+
{{ $i->bulan }}
+
{{ $i->tahun ?? date('Y') }}
+
+
+
+
Rp {{ number_format($i->jumlah,0,',','.') }}
+
Bulanan
+
+ {{ $i->jenis_iuran ?? '-' }} + + {{ $i->keterangan ?? '-' }} + + @if($i->status == 'lunas') +
+
Lunas +
+ @elseif($i->status == 'rt') + ⏳ Menunggu Admin + @elseif($i->bukti_pembayaran) + ⏳ Menunggu Bendahara + @else + ⚠ Belum Bayar + @endif +
+ @if($i->status == 'lunas') + + @elseif($i->bukti_pembayaran) + {{-- Sudah upload bukti, sedang diproses — tidak ada aksi --}} + Sedang diproses + @else + + Bayar + + @endif +
+
+
💳
+
Belum Ada Data Iuran
+

Data iuran Anda akan muncul di sini

+
+
+
+
+ +
+
+ + + + + + + + {{-- TABEL KAS TERPISAH --}} +
+
+
+
+
+
Tagihan Kas
+

{{ $kas->count() }} tagihan kas

+
+
+
+
+ + + + + + + + + + + @forelse($kas as $k) + + + + + + + @empty + + @endforelse + +
KeteranganJumlahStatusAksi
+
+
+
+
{{ $k->keterangan }}
+
{{ $k->created_at->format('d M Y') }}
+
+
+
Rp {{ number_format($k->jumlah,0,',','.') }}
+ @if($k->status == 'lunas') +
Lunas
+ @elseif($k->status == 'menunggu_konfirmasi') + ⏳ Menunggu Konfirmasi + @else + ⚠ Belum Bayar + @endif +
+ @if($k->status == 'menunggu_bayar') + + @else + - + @endif +
Belum ada tagihan kas.
+
+
+ +{{-- ── MODAL DETAIL ── --}} +@foreach($iuran->where('status','lunas') as $i) + +@endforeach + +{{-- ── MODAL BAYAR KAS ── --}} +@foreach($kas->where('status', 'menunggu_bayar') as $k) + +@endforeach + + +@endsection diff --git a/.history/resources/views/user/iuran/index.blade_20260627170632.php b/.history/resources/views/user/iuran/index.blade_20260627170632.php new file mode 100644 index 0000000..65464bf --- /dev/null +++ b/.history/resources/views/user/iuran/index.blade_20260627170632.php @@ -0,0 +1,588 @@ +@extends('layouts.app') + +@section('content') + + +
+ + {{-- HEADER --}} +
+
+

💰 Data Iuran Saya

+

Kelola pembayaran iuran bulanan Anda

+
+ Tahun {{ date('Y') }} +
+ + {{-- STATS --}} + @php + $lunas = $iuran->where('status','lunas')->count(); + $belum = $iuran->filter(fn($x) => $x->status != 'lunas' && !$x->bukti_pembayaran)->count(); + $total = $iuran->where('status','lunas')->sum('jumlah'); + $pct = $iuran->count() > 0 ? round($lunas / $iuran->count() * 100) : 0; + @endphp +
+
+
+
{{ $lunas }}
+
Bulan Lunas
+
+
+
+
+
{{ $belum }}
+
Belum Bayar
+
+
+
+
Rp {{ number_format($total,0,',','.') }}
+
Total Dibayar
+
+
+
+
Rp {{ number_format($totalBelumBayar,0,',','.') }}
+
Total Belum Bayar
+
+
+ + {{-- MAIN GRID --}} +
+ + {{-- QRIS --}} +
+
+
Bayar via QRIS
+

Scan dengan e-wallet apapun

+
+
+
+ QRIS +
+
+ Scan menggunakan GoPay, OVO, Dana, atau e-wallet lainnya +
+
+ +
+ + {{-- TABLE + MOBILE CARDS --}} +
+
+
+
+
+
Riwayat Iuran
+

{{ $iuran->count() }} tagihan tahun berjalan

+
+
+
+ + + +
+
+ + {{-- Desktop table --}} +
+ + + + + + + + + + + + + @forelse($iuran as $i) + + + + + + + + + @empty + + @endforelse + +
BulanJumlahJenisKeteranganStatusAksi
+
+
+
+
{{ $i->bulan }}
+
{{ $i->tahun ?? date('Y') }}
+
+
+
+
Rp {{ number_format($i->jumlah,0,',','.') }}
+
Bulanan
+
{{ $i->jenis_iuran ?? '-' }}{{ $i->keterangan ?? '-' }} + @if($i->status == 'lunas') +
Lunas
+ @elseif($i->status == 'rt') + ⏳ Menunggu Admin + @elseif($i->bukti_pembayaran) + ⏳ Menunggu Bendahara + @else + ⚠ Belum Bayar + @endif +
+ @if($i->status == 'lunas') + + @elseif($i->bukti_pembayaran) + Sedang diproses + @else + Bayar + @endif +
+
+
💳
+
Belum Ada Data Iuran
+

Data iuran Anda akan muncul di sini

+
+
+
+ + {{-- Mobile cards --}} +
+ @forelse($iuran as $i) +
+
+
+
{{ $i->bulan }}
+
{{ $i->tahun ?? date('Y') }}
+
+
Rp {{ number_format($i->jumlah,0,',','.') }}
+
+
+ {{ $i->jenis_iuran ?? '-' }} + @if($i->status == 'lunas') +
Lunas
+ @elseif($i->status == 'rt') + ⏳ Menunggu Admin + @elseif($i->bukti_pembayaran) + ⏳ Menunggu + @else + ⚠ Belum Bayar + @endif +
+ @if($i->keterangan) +
{{ $i->keterangan }}
+ @endif +
+ @if($i->status == 'lunas') + + @elseif($i->bukti_pembayaran) + Sedang diproses + @else + Bayar + @endif +
+
+ @empty +
+
💳
+
Belum Ada Data Iuran
+

Data iuran Anda akan muncul di sini

+
+ @endforelse +
+ +
+
+ + {{-- KAS SECTION --}} +
+
+
+
+
+
+
Tagihan Kas
+

{{ $kas->count() }} tagihan kas

+
+
+
+ + {{-- Desktop --}} +
+ + + + + + + + + + + @forelse($kas as $k) + + + + + + + @empty + + @endforelse + +
KeteranganJumlahStatusAksi
+
+
+
+
{{ $k->keterangan }}
+
{{ $k->created_at->format('d M Y') }}
+
+
+
Rp {{ number_format($k->jumlah,0,',','.') }}
+ @if($k->status == 'lunas') +
Lunas
+ @elseif($k->status == 'menunggu_konfirmasi') + ⏳ Menunggu Konfirmasi + @else + ⚠ Belum Bayar + @endif +
+ @if($k->status == 'menunggu_bayar') + + @else + - + @endif +
Belum ada tagihan kas.
+
+ + {{-- Mobile kas cards --}} +
+ @forelse($kas as $k) +
+
+
+
{{ $k->keterangan }}
+
{{ $k->created_at->format('d M Y') }}
+
+
Rp {{ number_format($k->jumlah,0,',','.') }}
+
+
+ @if($k->status == 'lunas') +
Lunas
+ @elseif($k->status == 'menunggu_konfirmasi') + ⏳ Menunggu Konfirmasi + @else + ⚠ Belum Bayar + @endif +
+
+ @if($k->status == 'menunggu_bayar') + + @else + - + @endif +
+
+ @empty +
Belum ada tagihan kas.
+ @endforelse +
+ +
+
+ +
+ +{{-- MODAL DETAIL --}} +@foreach($iuran->where('status','lunas') as $i) + +@endforeach + +{{-- MODAL BAYAR KAS --}} +@foreach($kas->where('status','menunggu_bayar') as $k) + +@endforeach + + +@endsection diff --git a/.history/resources/views/user/iuran/index.blade_20260627170650.php b/.history/resources/views/user/iuran/index.blade_20260627170650.php new file mode 100644 index 0000000..65464bf --- /dev/null +++ b/.history/resources/views/user/iuran/index.blade_20260627170650.php @@ -0,0 +1,588 @@ +@extends('layouts.app') + +@section('content') + + +
+ + {{-- HEADER --}} +
+
+

💰 Data Iuran Saya

+

Kelola pembayaran iuran bulanan Anda

+
+ Tahun {{ date('Y') }} +
+ + {{-- STATS --}} + @php + $lunas = $iuran->where('status','lunas')->count(); + $belum = $iuran->filter(fn($x) => $x->status != 'lunas' && !$x->bukti_pembayaran)->count(); + $total = $iuran->where('status','lunas')->sum('jumlah'); + $pct = $iuran->count() > 0 ? round($lunas / $iuran->count() * 100) : 0; + @endphp +
+
+
+
{{ $lunas }}
+
Bulan Lunas
+
+
+
+
+
{{ $belum }}
+
Belum Bayar
+
+
+
+
Rp {{ number_format($total,0,',','.') }}
+
Total Dibayar
+
+
+
+
Rp {{ number_format($totalBelumBayar,0,',','.') }}
+
Total Belum Bayar
+
+
+ + {{-- MAIN GRID --}} +
+ + {{-- QRIS --}} +
+
+
Bayar via QRIS
+

Scan dengan e-wallet apapun

+
+
+
+ QRIS +
+
+ Scan menggunakan GoPay, OVO, Dana, atau e-wallet lainnya +
+
+ +
+ + {{-- TABLE + MOBILE CARDS --}} +
+
+
+
+
+
Riwayat Iuran
+

{{ $iuran->count() }} tagihan tahun berjalan

+
+
+
+ + + +
+
+ + {{-- Desktop table --}} +
+ + + + + + + + + + + + + @forelse($iuran as $i) + + + + + + + + + @empty + + @endforelse + +
BulanJumlahJenisKeteranganStatusAksi
+
+
+
+
{{ $i->bulan }}
+
{{ $i->tahun ?? date('Y') }}
+
+
+
+
Rp {{ number_format($i->jumlah,0,',','.') }}
+
Bulanan
+
{{ $i->jenis_iuran ?? '-' }}{{ $i->keterangan ?? '-' }} + @if($i->status == 'lunas') +
Lunas
+ @elseif($i->status == 'rt') + ⏳ Menunggu Admin + @elseif($i->bukti_pembayaran) + ⏳ Menunggu Bendahara + @else + ⚠ Belum Bayar + @endif +
+ @if($i->status == 'lunas') + + @elseif($i->bukti_pembayaran) + Sedang diproses + @else + Bayar + @endif +
+
+
💳
+
Belum Ada Data Iuran
+

Data iuran Anda akan muncul di sini

+
+
+
+ + {{-- Mobile cards --}} +
+ @forelse($iuran as $i) +
+
+
+
{{ $i->bulan }}
+
{{ $i->tahun ?? date('Y') }}
+
+
Rp {{ number_format($i->jumlah,0,',','.') }}
+
+
+ {{ $i->jenis_iuran ?? '-' }} + @if($i->status == 'lunas') +
Lunas
+ @elseif($i->status == 'rt') + ⏳ Menunggu Admin + @elseif($i->bukti_pembayaran) + ⏳ Menunggu + @else + ⚠ Belum Bayar + @endif +
+ @if($i->keterangan) +
{{ $i->keterangan }}
+ @endif +
+ @if($i->status == 'lunas') + + @elseif($i->bukti_pembayaran) + Sedang diproses + @else + Bayar + @endif +
+
+ @empty +
+
💳
+
Belum Ada Data Iuran
+

Data iuran Anda akan muncul di sini

+
+ @endforelse +
+ +
+
+ + {{-- KAS SECTION --}} +
+
+
+
+
+
+
Tagihan Kas
+

{{ $kas->count() }} tagihan kas

+
+
+
+ + {{-- Desktop --}} +
+ + + + + + + + + + + @forelse($kas as $k) + + + + + + + @empty + + @endforelse + +
KeteranganJumlahStatusAksi
+
+
+
+
{{ $k->keterangan }}
+
{{ $k->created_at->format('d M Y') }}
+
+
+
Rp {{ number_format($k->jumlah,0,',','.') }}
+ @if($k->status == 'lunas') +
Lunas
+ @elseif($k->status == 'menunggu_konfirmasi') + ⏳ Menunggu Konfirmasi + @else + ⚠ Belum Bayar + @endif +
+ @if($k->status == 'menunggu_bayar') + + @else + - + @endif +
Belum ada tagihan kas.
+
+ + {{-- Mobile kas cards --}} +
+ @forelse($kas as $k) +
+
+
+
{{ $k->keterangan }}
+
{{ $k->created_at->format('d M Y') }}
+
+
Rp {{ number_format($k->jumlah,0,',','.') }}
+
+
+ @if($k->status == 'lunas') +
Lunas
+ @elseif($k->status == 'menunggu_konfirmasi') + ⏳ Menunggu Konfirmasi + @else + ⚠ Belum Bayar + @endif +
+
+ @if($k->status == 'menunggu_bayar') + + @else + - + @endif +
+
+ @empty +
Belum ada tagihan kas.
+ @endforelse +
+ +
+
+ +
+ +{{-- MODAL DETAIL --}} +@foreach($iuran->where('status','lunas') as $i) + +@endforeach + +{{-- MODAL BAYAR KAS --}} +@foreach($kas->where('status','menunggu_bayar') as $k) + +@endforeach + + +@endsection diff --git a/.history/resources/views/user/iuran/upload.blade_20260505210628.php b/.history/resources/views/user/iuran/upload.blade_20260505210628.php new file mode 100644 index 0000000..fa9af07 --- /dev/null +++ b/.history/resources/views/user/iuran/upload.blade_20260505210628.php @@ -0,0 +1,634 @@ +@extends('layouts.app') + +@section('content') + + + +
+
+ + {{-- BREADCRUMB --}} + + +
+
+
+ + {{-- JUDUL --}} +
+
+ +
+
+

Upload Bukti Pembayaran

+

Lampirkan foto atau scan bukti transfer iuran Anda

+
+
+ + {{-- INFO IURAN --}} +
+
+

Bulan

+

{{ $iuran->bulan }}

+
+
+
+

Jumlah Tagihan

+

Rp {{ number_format($iuran->jumlah, 0, ',', '.') }}

+
+
+
+

Status

+
+ + Menunggu Konfirmasi +
+
+
+ + {{-- FORM --}} +
+ @csrf + + {{-- ERROR --}} + @if ($errors->any()) +
+ + {{ $errors->first() }} +
+ @endif + + {{-- GRID UPLOAD --}} +
+ + {{-- PREVIEW --}} +
+

Pratinjau Gambar

+
+
+ +

Gambar akan muncul di sini

+
+ Preview bukti pembayaran +
+
+ + {{-- UPLOAD ZONE --}} +
+

Pilih File

+
+ +
+ +
+

Klik atau Seret File

+

Pilih foto bukti transfer dari
galeri atau kamera Anda

+
+ JPG + PNG + WEBP + HEIC +
+
+
+ + nama-file.jpg +
+
+ +
+ + {{-- TIPS --}} +
+ +

+ Tips: Pastikan foto bukti transfer terlihat jelas, + nominal dan nama tujuan transfer terbaca, serta tidak terpotong. + Ukuran file maksimal 2 MB. +

+
+ + {{-- ACTION --}} +
+ + + Kembali + + +
+ +
+ +
+
+ +
+
+ + + +@endsection diff --git a/.history/resources/views/user/iuran/upload.blade_20260615180656.php b/.history/resources/views/user/iuran/upload.blade_20260615180656.php new file mode 100644 index 0000000..e21f47f --- /dev/null +++ b/.history/resources/views/user/iuran/upload.blade_20260615180656.php @@ -0,0 +1,650 @@ +@extends('layouts.app') + +@section('content') + + + +
+
+ + {{-- BREADCRUMB --}} + + +
+
+
+ + {{-- JUDUL --}} +
+
+ +
+
+

Upload Bukti Pembayaran

+

Lampirkan foto atau scan bukti transfer iuran Anda

+
+
+ + {{-- INFO IURAN --}} +
+
+

Bulan

+

{{ $iuran->bulan }} {{ $iuran->tahun }}

+
+
+
+

Jumlah Tagihan

+

Rp {{ number_format($iuran->jumlah, 0, ',', '.') }}

+
+
+
+

Jenis Iuran

+

{{ $iuran->jenis_iuran ?? '-' }}

+
+
+
+

Status

+
+ + Menunggu Konfirmasi RT +
+
+
+ +{{-- KETERANGAN --}} +@if($iuran->keterangan) +
+ +
+

Keterangan dari RT

+

{{ $iuran->keterangan }}

+
+
+@endif + + {{-- FORM --}} +
+ @csrf + + {{-- ERROR --}} + @if ($errors->any()) +
+ + {{ $errors->first() }} +
+ @endif + + {{-- GRID UPLOAD --}} +
+ + {{-- PREVIEW --}} +
+

Pratinjau Gambar

+
+
+ +

Gambar akan muncul di sini

+
+ Preview bukti pembayaran +
+
+ + {{-- UPLOAD ZONE --}} +
+

Pilih File

+
+ +
+ +
+

Klik atau Seret File

+

Pilih foto bukti transfer dari
galeri atau kamera Anda

+
+ JPG + PNG + WEBP + HEIC +
+
+
+ + nama-file.jpg +
+
+ +
+ + {{-- TIPS --}} +
+ +

+ Tips: Pastikan foto bukti transfer terlihat jelas, + nominal dan nama tujuan transfer terbaca, serta tidak terpotong. + Ukuran file maksimal 2 MB. +

+
+ + {{-- ACTION --}} +
+ + + Kembali + + +
+ +
+ +
+
+ +
+
+ + + +@endsection diff --git a/.history/resources/views/user/iuran/upload.blade_20260615180708.php b/.history/resources/views/user/iuran/upload.blade_20260615180708.php new file mode 100644 index 0000000..fe4fe83 --- /dev/null +++ b/.history/resources/views/user/iuran/upload.blade_20260615180708.php @@ -0,0 +1,650 @@ +@extends('layouts.app') + +@section('content') + + + +
+
+ + {{-- BREADCRUMB --}} + + +
+
+
+ + {{-- JUDUL --}} +
+
+ +
+
+

Upload Bukti Pembayaran

+

Lampirkan foto atau scan bukti transfer iuran Anda

+
+
+ + {{-- INFO IURAN --}} +
+
+

Bulan

+

{{ $iuran->bulan }} {{ $iuran->tahun }}

+
+
+
+

Jumlah Tagihan

+

Rp {{ number_format($iuran->jumlah, 0, ',', '.') }}

+
+
+
+

Jenis Iuran

+

{{ $iuran->jenis_iuran ?? '-' }}

+
+
+
+

Status

+
+ + Menunggu Konfirmasi RT +
+
+
+ + {{-- KETERANGAN --}} + @if($iuran->keterangan) +
+ +
+

Keterangan dari RT

+

{{ $iuran->keterangan }}

+
+
+ @endif + + {{-- FORM --}} +
+ @csrf + + {{-- ERROR --}} + @if ($errors->any()) +
+ + {{ $errors->first() }} +
+ @endif + + {{-- GRID UPLOAD --}} +
+ + {{-- PREVIEW --}} +
+

Pratinjau Gambar

+
+
+ +

Gambar akan muncul di sini

+
+ Preview bukti pembayaran +
+
+ + {{-- UPLOAD ZONE --}} +
+

Pilih File

+
+ +
+ +
+

Klik atau Seret File

+

Pilih foto bukti transfer dari
galeri atau kamera Anda

+
+ JPG + PNG + WEBP + HEIC +
+
+
+ + nama-file.jpg +
+
+ +
+ + {{-- TIPS --}} +
+ +

+ Tips: Pastikan foto bukti transfer terlihat jelas, + nominal dan nama tujuan transfer terbaca, serta tidak terpotong. + Ukuran file maksimal 2 MB. +

+
+ + {{-- ACTION --}} +
+ + + Kembali + + +
+ +
+ +
+
+ +
+
+ + + +@endsection diff --git a/.history/resources/views/user/kas/upload.blade_20260619213231.php b/.history/resources/views/user/kas/upload.blade_20260619213231.php new file mode 100644 index 0000000..e69de29 diff --git a/.history/resources/views/user/kas/upload.blade_20260619213238.php b/.history/resources/views/user/kas/upload.blade_20260619213238.php new file mode 100644 index 0000000..bcfe385 --- /dev/null +++ b/.history/resources/views/user/kas/upload.blade_20260619213238.php @@ -0,0 +1,16 @@ +@extends('layouts.app') + +@section('content') +
+

Upload Bukti Bayar Kas

+

{{ $kas->keterangan }} — Rp {{ number_format($kas->jumlah, 0, ',', '.') }}

+ +
+ @csrf +
+ +
+ +
+
+@endsection diff --git a/.history/resources/views/user/kas/upload.blade_20260620085228.php b/.history/resources/views/user/kas/upload.blade_20260620085228.php new file mode 100644 index 0000000..b7db574 --- /dev/null +++ b/.history/resources/views/user/kas/upload.blade_20260620085228.php @@ -0,0 +1,198 @@ +@extends('layouts.app') + +@section('content') + + +
+
+ +
+
+

Upload Bukti Bayar Kas

+

Lampirkan bukti transfer untuk konfirmasi bendahara

+
+ +
+ +
+
+
+
Tagihan Kas
+
{{ $kas->keterangan }}
+
Rp {{ number_format($kas->jumlah, 0, ',', '.') }}
+
+
+ +
+ @csrf + + +
+
+
Klik atau seret gambar ke sini
+
JPG atau PNG, maksimal 2MB
+
+ +
+ +
+ Preview +
+ + +
+ + + Kembali ke Riwayat Iuran + + +
+
+
+ + +@endsection diff --git a/.history/resources/views/user/layanan/status.blade_20260505213925.php b/.history/resources/views/user/layanan/status.blade_20260505213925.php new file mode 100644 index 0000000..dd55df6 --- /dev/null +++ b/.history/resources/views/user/layanan/status.blade_20260505213925.php @@ -0,0 +1,657 @@ +@extends('layouts.app') + +@section('content') + + + +
+ + {{-- HEADER SECTION --}} +
+
+
+
+ +
+
+

Status Pengaduan Saya

+

Pantau perkembangan laporan yang telah Anda kirimkan

+
+
+ {{ count($layanan) }} + Total Laporan +
+
+
+ + {{-- CARD WRAPPER --}} +
+ + @if(count($layanan) === 0) +
+
+

Belum ada pengaduan yang diajukan

+
+ @else + +
+ + + + + + + + + + + @foreach($layanan as $item) + + + + + + + @endforeach + +
NoTanggal PengaduanStatusAksi
+ {{ $loop->iteration }} + +
+ + {{ \Carbon\Carbon::parse($item->tanggal_pengaduan)->translatedFormat('d M Y') }} + {{ \Carbon\Carbon::parse($item->tanggal_pengaduan)->format('H:i') }} +
+
+ @if($item->status == 'diajukan') + + Diajukan + + @elseif($item->status == 'diproses') + + Diproses + + @else + + Selesai + + @endif + + +
+
+ + @endif +
+
+ +{{-- MODALS --}} +@foreach($layanan as $item) + +@endforeach + +@endsection + + diff --git a/.history/resources/views/user/layanan/status.blade_20260625013734.php b/.history/resources/views/user/layanan/status.blade_20260625013734.php new file mode 100644 index 0000000..3e32a9f --- /dev/null +++ b/.history/resources/views/user/layanan/status.blade_20260625013734.php @@ -0,0 +1,269 @@ +@extends('layouts.app') + +@section('content') + + + +
+ +
+
+
+
+
+

Status Pengaduan Saya

+

Pantau perkembangan laporan yang telah Anda kirimkan

+
+
+ {{ count($layanan) }} + Total Laporan +
+
+
+ +
+ @if(count($layanan) === 0) +
+
+

Belum ada pengaduan yang diajukan

+
+ @else +
+ + + + + + + + + + + + @foreach($layanan as $item) + + + + + + + + @endforeach + +
NoTanggal PengaduanKategoriStatusAksi
{{ $loop->iteration }} +
+ + {{ \Carbon\Carbon::parse($item->tanggal_pengaduan)->translatedFormat('d M Y') }} + {{ \Carbon\Carbon::parse($item->tanggal_pengaduan)->format('H:i') }} +
+
{{ ucfirst($item->kategori_masalah) }} + @if($item->status == 'diajukan') + Diajukan + @elseif($item->status == 'diproses') + Diproses + @else + Selesai + @endif + + +
+
+ @endif +
+
+ +{{-- MODALS --}} +@foreach($layanan as $item) + +@endforeach + +@endsection + + diff --git a/.history/resources/views/user/rumah.blade_20260511001052.php b/.history/resources/views/user/rumah.blade_20260511001052.php deleted file mode 100644 index f64a048..0000000 --- a/.history/resources/views/user/rumah.blade_20260511001052.php +++ /dev/null @@ -1,1373 +0,0 @@ -@extends('layouts.app') - -@section('content') -
- - {{-- ===== HERO ===== --}} -
-
-
-
-
-
-
-
- -
-
- {{--

Selamat Datang, {{ auth()->user()->name }} 👋

-

Kelola hunian Anda dengan mudah di Green View

--}} -
-
-
- {{--
- {{ $rumahList->count() ?? 0 }} - Total Kavling -
-
-
- {{ $rumahList->where('status', 'Kosong')->count() ?? 0 }} - Tersedia -
-
-
- {{ $rumahList->where('status', 'Terisi')->count() ?? 0 }} - Terisi -
--}} -
-
- -
- - {{-- ===== PROFILE CARD ===== --}} -
-
-
-
-
- Avatar -
-
-
{{ auth()->user()->name }}
-

{{ auth()->user()->email }}

- -
- User Aktif -
- -
- -
-

Status Hunian

- - @if($penghuni) - - @if($penghuni->status_huni == 'Tetap') - - Sudah Punya Rumah - - - @else - - Kontrak - @if($penghuni->tanggal_keluar) - sampai {{ \Carbon\Carbon::parse($penghuni->tanggal_keluar)->format('d M Y') }} - @endif - - @endif - - @else - - - Belum Punya - - - @endif -
- -
- - @if($penghuni) -
-
Status Kontrak
- {{ $penghuni->status_huni ?? '-' }} -
- @endif - - - Edit Profil - -
-
-
- - {{-- ===== KONTEN UTAMA ===== --}} -
- -
- {{-- ===================== --}} - {{-- FORM DATA PENGHUNI --}} - {{-- ===================== --}} - @if(!$penghuni) -
- -
-
- -
-
-
Form Data Penghuni
-

Lengkapi data sebelum memilih rumah

-
-
- - {{-- ✅ Flash success message --}} - @if(session('success')) -
- {{ session('success') }} -
- @endif - -
- @csrf - -
- - - - - - - - - - - -
- - -
- -
- @endif - - @if($rumah) - {{-- ===== RUMAH SAYA ===== --}} -
-
-
- -
-
-
Rumah Saya
-

Detail hunian terdaftar Anda

-
-
- -
-
- Foto Rumah -
- Blok {{ $penghuni->rumah->blok }} -
-
- -
-
-
-
-
Blok
-
{{ $penghuni->rumah->blok }}
-
-
-
-
-
-
No. Rumah
-
{{ $penghuni->rumah->no_rumah }}
-
-
-
-
-
-
Status
-
- {{ $penghuni->rumah->status }} -
-
-
-
-
-
-
RT
-
{{ $rtUser->name ?? '-' }}
-
-
-
-
-
- - @else - {{-- ===== EMPTY STATE ===== --}} -
-
-
- -
-
Belum Memiliki Rumah
-

Pilih kavling di bawah untuk memulai

-
-
- - {{-- ===== KAVLING GRID ===== --}} -
-
-
- -
-
-
Pilih Kavling
-

Klik kavling hijau untuk memilih -

-
-
- Tersedia - Terisi -
-
- -
- @foreach($rumahList ?? [] as $index => $r) - - @endforeach -
-
- @endif - -
-
-
- - {{-- ===== MODAL AMBIL KAVLING ===== --}} - - -@endsection - - @section('scripts') - -@endsection - - @push('styles') - - @endpush diff --git a/.history/resources/views/user/rumah.blade_20260511001108.php b/.history/resources/views/user/rumah.blade_20260511001108.php deleted file mode 100644 index 6a9d402..0000000 --- a/.history/resources/views/user/rumah.blade_20260511001108.php +++ /dev/null @@ -1,1373 +0,0 @@ -@extends('layouts.app') - -@section('content') -
- - {{-- ===== HERO ===== --}} -
-
-
-
-
-
-
- {{--
- -
--}} -
-

Selamat Datang, {{ auth()->user()->name }} 👋

-

Kelola hunian Anda dengan mudah di Green View

-
-
-
- {{--
- {{ $rumahList->count() ?? 0 }} - Total Kavling -
-
-
- {{ $rumahList->where('status', 'Kosong')->count() ?? 0 }} - Tersedia -
-
-
- {{ $rumahList->where('status', 'Terisi')->count() ?? 0 }} - Terisi -
--}} -
-
- -
- - {{-- ===== PROFILE CARD ===== --}} -
-
-
-
-
- Avatar -
-
-
{{ auth()->user()->name }}
-

{{ auth()->user()->email }}

- -
- User Aktif -
- -
- -
-

Status Hunian

- - @if($penghuni) - - @if($penghuni->status_huni == 'Tetap') - - Sudah Punya Rumah - - - @else - - Kontrak - @if($penghuni->tanggal_keluar) - sampai {{ \Carbon\Carbon::parse($penghuni->tanggal_keluar)->format('d M Y') }} - @endif - - @endif - - @else - - - Belum Punya - - - @endif -
- -
- - @if($penghuni) -
-
Status Kontrak
- {{ $penghuni->status_huni ?? '-' }} -
- @endif - - - Edit Profil - -
-
-
- - {{-- ===== KONTEN UTAMA ===== --}} -
- -
- {{-- ===================== --}} - {{-- FORM DATA PENGHUNI --}} - {{-- ===================== --}} - @if(!$penghuni) -
- -
-
- -
-
-
Form Data Penghuni
-

Lengkapi data sebelum memilih rumah

-
-
- - {{-- ✅ Flash success message --}} - @if(session('success')) -
- {{ session('success') }} -
- @endif - -
- @csrf - -
- - - - - - - - - - - -
- - -
- -
- @endif - - @if($rumah) - {{-- ===== RUMAH SAYA ===== --}} -
-
-
- -
-
-
Rumah Saya
-

Detail hunian terdaftar Anda

-
-
- -
-
- Foto Rumah -
- Blok {{ $penghuni->rumah->blok }} -
-
- -
-
-
-
-
Blok
-
{{ $penghuni->rumah->blok }}
-
-
-
-
-
-
No. Rumah
-
{{ $penghuni->rumah->no_rumah }}
-
-
-
-
-
-
Status
-
- {{ $penghuni->rumah->status }} -
-
-
-
-
-
-
RT
-
{{ $rtUser->name ?? '-' }}
-
-
-
-
-
- - @else - {{-- ===== EMPTY STATE ===== --}} -
-
-
- -
-
Belum Memiliki Rumah
-

Pilih kavling di bawah untuk memulai

-
-
- - {{-- ===== KAVLING GRID ===== --}} -
-
-
- -
-
-
Pilih Kavling
-

Klik kavling hijau untuk memilih -

-
-
- Tersedia - Terisi -
-
- -
- @foreach($rumahList ?? [] as $index => $r) - - @endforeach -
-
- @endif - -
-
-
- - {{-- ===== MODAL AMBIL KAVLING ===== --}} - - -@endsection - - @section('scripts') - -@endsection - - @push('styles') - - @endpush diff --git a/.history/resources/views/user/rumah.blade_20260511001118.php b/.history/resources/views/user/rumah.blade_20260511001118.php deleted file mode 100644 index 4320619..0000000 --- a/.history/resources/views/user/rumah.blade_20260511001118.php +++ /dev/null @@ -1,1373 +0,0 @@ -@extends('layouts.app') - -@section('content') -
- - {{-- ===== HERO ===== --}} -
-
-
-
-
-
-
- {{--
- -
--}} -
- {{--

Selamat Datang, {{ auth()->user()->name }} 👋

--}} -

Kelola hunian Anda dengan mudah di Green View

-
-
-
- {{--
- {{ $rumahList->count() ?? 0 }} - Total Kavling -
-
-
- {{ $rumahList->where('status', 'Kosong')->count() ?? 0 }} - Tersedia -
-
-
- {{ $rumahList->where('status', 'Terisi')->count() ?? 0 }} - Terisi -
--}} -
-
- -
- - {{-- ===== PROFILE CARD ===== --}} -
-
-
-
-
- Avatar -
-
-
{{ auth()->user()->name }}
-

{{ auth()->user()->email }}

- -
- User Aktif -
- -
- -
-

Status Hunian

- - @if($penghuni) - - @if($penghuni->status_huni == 'Tetap') - - Sudah Punya Rumah - - - @else - - Kontrak - @if($penghuni->tanggal_keluar) - sampai {{ \Carbon\Carbon::parse($penghuni->tanggal_keluar)->format('d M Y') }} - @endif - - @endif - - @else - - - Belum Punya - - - @endif -
- -
- - @if($penghuni) -
-
Status Kontrak
- {{ $penghuni->status_huni ?? '-' }} -
- @endif - - - Edit Profil - -
-
-
- - {{-- ===== KONTEN UTAMA ===== --}} -
- -
- {{-- ===================== --}} - {{-- FORM DATA PENGHUNI --}} - {{-- ===================== --}} - @if(!$penghuni) -
- -
-
- -
-
-
Form Data Penghuni
-

Lengkapi data sebelum memilih rumah

-
-
- - {{-- ✅ Flash success message --}} - @if(session('success')) -
- {{ session('success') }} -
- @endif - -
- @csrf - -
- - - - - - - - - - - -
- - -
- -
- @endif - - @if($rumah) - {{-- ===== RUMAH SAYA ===== --}} -
-
-
- -
-
-
Rumah Saya
-

Detail hunian terdaftar Anda

-
-
- -
-
- Foto Rumah -
- Blok {{ $penghuni->rumah->blok }} -
-
- -
-
-
-
-
Blok
-
{{ $penghuni->rumah->blok }}
-
-
-
-
-
-
No. Rumah
-
{{ $penghuni->rumah->no_rumah }}
-
-
-
-
-
-
Status
-
- {{ $penghuni->rumah->status }} -
-
-
-
-
-
-
RT
-
{{ $rtUser->name ?? '-' }}
-
-
-
-
-
- - @else - {{-- ===== EMPTY STATE ===== --}} -
-
-
- -
-
Belum Memiliki Rumah
-

Pilih kavling di bawah untuk memulai

-
-
- - {{-- ===== KAVLING GRID ===== --}} -
-
-
- -
-
-
Pilih Kavling
-

Klik kavling hijau untuk memilih -

-
-
- Tersedia - Terisi -
-
- -
- @foreach($rumahList ?? [] as $index => $r) - - @endforeach -
-
- @endif - -
-
-
- - {{-- ===== MODAL AMBIL KAVLING ===== --}} - - -@endsection - - @section('scripts') - -@endsection - - @push('styles') - - @endpush diff --git a/.history/resources/views/user/rumah.blade_20260511001137.php b/.history/resources/views/user/rumah.blade_20260511001137.php deleted file mode 100644 index 02bee21..0000000 --- a/.history/resources/views/user/rumah.blade_20260511001137.php +++ /dev/null @@ -1,1358 +0,0 @@ -@extends('layouts.app') - -@section('content') -
- - {{-- ===== HERO ===== --}} -
-
-
-
-
-
-
- {{--
- -
--}} -
- {{--

Selamat Datang, {{ auth()->user()->name }} 👋

--}} -

Kelola hunian Anda dengan mudah di Green View

-
-
- -
- -
- - {{-- ===== PROFILE CARD ===== --}} -
-
-
-
-
- Avatar -
-
-
{{ auth()->user()->name }}
-

{{ auth()->user()->email }}

- -
- User Aktif -
- -
- -
-

Status Hunian

- - @if($penghuni) - - @if($penghuni->status_huni == 'Tetap') - - Sudah Punya Rumah - - - @else - - Kontrak - @if($penghuni->tanggal_keluar) - sampai {{ \Carbon\Carbon::parse($penghuni->tanggal_keluar)->format('d M Y') }} - @endif - - @endif - - @else - - - Belum Punya - - - @endif -
- -
- - @if($penghuni) -
-
Status Kontrak
- {{ $penghuni->status_huni ?? '-' }} -
- @endif - - - Edit Profil - -
-
-
- - {{-- ===== KONTEN UTAMA ===== --}} -
- -
- {{-- ===================== --}} - {{-- FORM DATA PENGHUNI --}} - {{-- ===================== --}} - @if(!$penghuni) -
- -
-
- -
-
-
Form Data Penghuni
-

Lengkapi data sebelum memilih rumah

-
-
- - {{-- ✅ Flash success message --}} - @if(session('success')) -
- {{ session('success') }} -
- @endif - -
- @csrf - -
- - - - - - - - - - - -
- - -
- -
- @endif - - @if($rumah) - {{-- ===== RUMAH SAYA ===== --}} -
-
-
- -
-
-
Rumah Saya
-

Detail hunian terdaftar Anda

-
-
- -
-
- Foto Rumah -
- Blok {{ $penghuni->rumah->blok }} -
-
- -
-
-
-
-
Blok
-
{{ $penghuni->rumah->blok }}
-
-
-
-
-
-
No. Rumah
-
{{ $penghuni->rumah->no_rumah }}
-
-
-
-
-
-
Status
-
- {{ $penghuni->rumah->status }} -
-
-
-
-
-
-
RT
-
{{ $rtUser->name ?? '-' }}
-
-
-
-
-
- - @else - {{-- ===== EMPTY STATE ===== --}} -
-
-
- -
-
Belum Memiliki Rumah
-

Pilih kavling di bawah untuk memulai

-
-
- - {{-- ===== KAVLING GRID ===== --}} -
-
-
- -
-
-
Pilih Kavling
-

Klik kavling hijau untuk memilih -

-
-
- Tersedia - Terisi -
-
- -
- @foreach($rumahList ?? [] as $index => $r) - - @endforeach -
-
- @endif - -
-
-
- - {{-- ===== MODAL AMBIL KAVLING ===== --}} - - -@endsection - - @section('scripts') - -@endsection - - @push('styles') - - @endpush diff --git a/.history/resources/views/user/rumah.blade_20260511001201.php b/.history/resources/views/user/rumah.blade_20260511001201.php deleted file mode 100644 index e82c958..0000000 --- a/.history/resources/views/user/rumah.blade_20260511001201.php +++ /dev/null @@ -1,1296 +0,0 @@ -@extends('layouts.app') - -@section('content') -
- - {{-- ===== HERO ===== --}} -
-
-
-
-
-
-
- {{--
- -
--}} -
- {{--

Selamat Datang, {{ auth()->user()->name }} 👋

--}} -

Kelola hunian Anda dengan mudah di Green View

-
-
- -
- -
- - - - {{-- ===== KONTEN UTAMA ===== --}} -
- -
- {{-- ===================== --}} - {{-- FORM DATA PENGHUNI --}} - {{-- ===================== --}} - @if(!$penghuni) -
- -
-
- -
-
-
Form Data Penghuni
-

Lengkapi data sebelum memilih rumah

-
-
- - {{-- ✅ Flash success message --}} - @if(session('success')) -
- {{ session('success') }} -
- @endif - -
- @csrf - -
- - - - - - - - - - - -
- - -
- -
- @endif - - @if($rumah) - {{-- ===== RUMAH SAYA ===== --}} -
-
-
- -
-
-
Rumah Saya
-

Detail hunian terdaftar Anda

-
-
- -
-
- Foto Rumah -
- Blok {{ $penghuni->rumah->blok }} -
-
- -
-
-
-
-
Blok
-
{{ $penghuni->rumah->blok }}
-
-
-
-
-
-
No. Rumah
-
{{ $penghuni->rumah->no_rumah }}
-
-
-
-
-
-
Status
-
- {{ $penghuni->rumah->status }} -
-
-
-
-
-
-
RT
-
{{ $rtUser->name ?? '-' }}
-
-
-
-
-
- - @else - {{-- ===== EMPTY STATE ===== --}} -
-
-
- -
-
Belum Memiliki Rumah
-

Pilih kavling di bawah untuk memulai

-
-
- - {{-- ===== KAVLING GRID ===== --}} -
-
-
- -
-
-
Pilih Kavling
-

Klik kavling hijau untuk memilih -

-
-
- Tersedia - Terisi -
-
- -
- @foreach($rumahList ?? [] as $index => $r) - - @endforeach -
-
- @endif - -
-
-
- - {{-- ===== MODAL AMBIL KAVLING ===== --}} - - -@endsection - - @section('scripts') - -@endsection - - @push('styles') - - @endpush diff --git a/.history/resources/views/user/rumah.blade_20260511001216.php b/.history/resources/views/user/rumah.blade_20260511001216.php deleted file mode 100644 index 0add4f5..0000000 --- a/.history/resources/views/user/rumah.blade_20260511001216.php +++ /dev/null @@ -1,1119 +0,0 @@ -@extends('layouts.app') - -@section('content') -
- - {{-- ===== HERO ===== --}} -
-
-
-
-
-
-
- {{--
- -
--}} -
- {{--

Selamat Datang, {{ auth()->user()->name }} 👋

--}} -

Kelola hunian Anda dengan mudah di Green View

-
-
- -
- - - - {{-- ===== MODAL AMBIL KAVLING ===== --}} - - -@endsection - - @section('scripts') - -@endsection - - @push('styles') - - @endpush diff --git a/.history/resources/views/user/rumah.blade_20260506115605.php b/.history/resources/views/user/rumah.blade_20260521212139.php similarity index 98% rename from .history/resources/views/user/rumah.blade_20260506115605.php rename to .history/resources/views/user/rumah.blade_20260521212139.php index e0f87eb..3d783d6 100644 --- a/.history/resources/views/user/rumah.blade_20260506115605.php +++ b/.history/resources/views/user/rumah.blade_20260521212139.php @@ -64,19 +64,19 @@ @if($penghuni) - @if($penghuni->status_huni == 'Tetap') - - Sudah Punya Rumah - - - @else - - Kontrak - @if($penghuni->tanggal_keluar) - sampai {{ \Carbon\Carbon::parse($penghuni->tanggal_keluar)->format('d M Y') }} - @endif - - @endif + {{-- BARU --}} +@if($penghuni->status_huni == 'Tetap') + + Sudah Punya Rumah + +@elseif($penghuni->status_huni == 'Kontrak') + + Kontrak + @if($penghuni->tanggal_keluar) + sampai {{ \Carbon\Carbon::parse($penghuni->tanggal_keluar)->format('d M Y') }} + @endif + +@endif @else diff --git a/.history/resources/views/user/rumah.blade_20260511001231.php b/.history/resources/views/user/rumah.blade_20260521212151.php similarity index 98% rename from .history/resources/views/user/rumah.blade_20260511001231.php rename to .history/resources/views/user/rumah.blade_20260521212151.php index e0f87eb..06c5940 100644 --- a/.history/resources/views/user/rumah.blade_20260511001231.php +++ b/.history/resources/views/user/rumah.blade_20260521212151.php @@ -64,19 +64,19 @@ @if($penghuni) - @if($penghuni->status_huni == 'Tetap') - - Sudah Punya Rumah - - - @else - - Kontrak - @if($penghuni->tanggal_keluar) - sampai {{ \Carbon\Carbon::parse($penghuni->tanggal_keluar)->format('d M Y') }} - @endif - - @endif + {{-- BARU --}} + @if($penghuni->status_huni == 'Tetap') + + Sudah Punya Rumah + + @elseif($penghuni->status_huni == 'Kontrak') + + Kontrak + @if($penghuni->tanggal_keluar) + sampai {{ \Carbon\Carbon::parse($penghuni->tanggal_keluar)->format('d M Y') }} + @endif + + @endif @else diff --git a/.history/resources/views/user/rumah.blade_20260511001037.php b/.history/resources/views/user/rumah.blade_20260521212225.php similarity index 97% rename from .history/resources/views/user/rumah.blade_20260511001037.php rename to .history/resources/views/user/rumah.blade_20260521212225.php index 2206f75..1065770 100644 --- a/.history/resources/views/user/rumah.blade_20260511001037.php +++ b/.history/resources/views/user/rumah.blade_20260521212225.php @@ -20,7 +20,7 @@
- {{--
+
{{ $rumahList->count() ?? 0 }} Total Kavling
@@ -33,7 +33,7 @@
{{ $rumahList->where('status', 'Terisi')->count() ?? 0 }} Terisi -
--}} +
@@ -64,19 +64,19 @@ @if($penghuni) - @if($penghuni->status_huni == 'Tetap') - - Sudah Punya Rumah - - - @else - - Kontrak - @if($penghuni->tanggal_keluar) - sampai {{ \Carbon\Carbon::parse($penghuni->tanggal_keluar)->format('d M Y') }} - @endif - - @endif + {{-- BARU --}} + @if($penghuni->status_huni == 'Tetap') + + Sudah Punya Rumah + + @elseif($penghuni->status_huni == 'Kontrak') + + Kontrak + @if($penghuni->tanggal_keluar) + sampai {{ \Carbon\Carbon::parse($penghuni->tanggal_keluar)->format('d M Y') }} + @endif + + @endif @else @@ -89,12 +89,17 @@
- @if($penghuni) -
-
Status Kontrak
- {{ $penghuni->status_huni ?? '-' }} -
- @endif +{{-- BARU --}} +@if($penghuni) +
+
Status Kontrak
+ @if($penghuni->status_huni == 'Tetap') + Tetap + @else + Kontrak + @endif +
+@endif Edit Profil diff --git a/.history/resources/views/user/rumah.blade_20260511001102.php b/.history/resources/views/user/rumah.blade_20260521212229.php similarity index 84% rename from .history/resources/views/user/rumah.blade_20260511001102.php rename to .history/resources/views/user/rumah.blade_20260521212229.php index 2206f75..6070e76 100644 --- a/.history/resources/views/user/rumah.blade_20260511001102.php +++ b/.history/resources/views/user/rumah.blade_20260521212229.php @@ -20,7 +20,7 @@
- {{--
+
{{ $rumahList->count() ?? 0 }} Total Kavling
@@ -33,7 +33,7 @@
{{ $rumahList->where('status', 'Terisi')->count() ?? 0 }} Terisi -
--}} +
@@ -62,37 +62,42 @@

Status Hunian

- @if($penghuni) + @if($penghuni) - @if($penghuni->status_huni == 'Tetap') - - Sudah Punya Rumah - - - @else - - Kontrak - @if($penghuni->tanggal_keluar) - sampai {{ \Carbon\Carbon::parse($penghuni->tanggal_keluar)->format('d M Y') }} - @endif - - @endif - - @else - - - Belum Punya + {{-- BARU --}} + @if($penghuni->status_huni == 'Tetap') + + Sudah Punya Rumah + + @elseif($penghuni->status_huni == 'Kontrak') + + Kontrak + @if($penghuni->tanggal_keluar) + sampai {{ \Carbon\Carbon::parse($penghuni->tanggal_keluar)->format('d M Y') }} + @endif - @endif + + @else + + + Belum Punya + + + @endif

+ {{-- BARU --}} @if($penghuni)
Status Kontrak
- {{ $penghuni->status_huni ?? '-' }} + @if($penghuni->status_huni == 'Tetap') + Tetap + @else + Kontrak + @endif
@endif @@ -107,8 +112,8 @@
- {{-- ===================== --}} - {{-- FORM DATA PENGHUNI --}} + {{-- ===================== --}} + {{-- FORM DATA PENGHUNI --}} {{-- ===================== --}} @if(!$penghuni)
@@ -134,26 +139,23 @@ @csrf
- + - - - - - +