From 56be7efdaf5c50100d6c5c1ae997b30938254917 Mon Sep 17 00:00:00 2001 From: Ilham Wara Nugroho Date: Tue, 21 Jul 2026 15:18:09 +0700 Subject: [PATCH] update --- Controllers/HomeController.cs | 31 +- Controllers/LokasiController.cs | 208 +----- Controllers/MapController.cs | 61 +- Database/ApplicationDbContext.cs | 1 + Helpers/Custom.cs | 109 +++ .../20260721071042_LokasiFauna.Designer.cs | 362 ++++++++++ Migrations/20260721071042_LokasiFauna.cs | 47 ++ .../ApplicationDbContextModelSnapshot.cs | 126 +++- Models/Entity/Master/Lokasi.cs | 9 + Models/Entity/Master/LokasiFauna.cs | 23 + Models/Entity/Master/LokasiTumbuhan.cs | 10 + Views/Fauna/Index.cshtml | 84 +-- Views/Flora/Index.cshtml | 3 +- Views/Home/Index.cshtml | 101 ++- Views/Lokasi/Detail.cshtml | 143 +--- Views/Lokasi/Index.cshtml | 7 +- Views/Map/Index.cshtml | 64 +- Views/Shared/_Layout.cshtml | 18 +- Views/Shared/_Pagination.cshtml | 127 ++-- bin/Debug/net9.0/kehati.dll | Bin 427520 -> 450560 bytes bin/Debug/net9.0/kehati.pdb | Bin 123352 -> 126128 bytes .../kehati.staticwebassets.endpoints.json | 2 +- .../kehati.staticwebassets.runtime.json | 2 +- .../compressed/7h6jxd9k8n-47ih3oe4t7.gz | Bin 0 -> 43048 bytes .../compressed/wkd5h07ok4-cf9mtx7t7r.gz | Bin 0 -> 97712 bytes .../compressed/zoo8rffbr6-i65bx55hda.gz | Bin 0 -> 3515 bytes obj/Debug/net9.0/kehati.AssemblyInfo.cs | 2 +- .../net9.0/kehati.AssemblyInfoInputs.cache | 2 +- .../kehati.csproj.CoreCompileInputs.cache | 2 +- .../net9.0/kehati.csproj.FileListAbsolute.txt | 3 + obj/Debug/net9.0/kehati.dll | Bin 427520 -> 450560 bytes obj/Debug/net9.0/kehati.pdb | Bin 123352 -> 126128 bytes obj/Debug/net9.0/rbcswa.dswa.cache.json | 2 +- obj/Debug/net9.0/ref/kehati.dll | Bin 60928 -> 65536 bytes obj/Debug/net9.0/refint/kehati.dll | Bin 60928 -> 65536 bytes obj/Debug/net9.0/rjimswa.dswa.cache.json | 2 +- obj/Debug/net9.0/rjsmcshtml.dswa.cache.json | 2 +- obj/Debug/net9.0/rjsmrazor.dswa.cache.json | 2 +- obj/Debug/net9.0/rpswa.dswa.cache.json | 2 +- .../staticwebassets.build.endpoints.json | 2 +- obj/Debug/net9.0/staticwebassets.build.json | 2 +- .../net9.0/staticwebassets.build.json.cache | 2 +- .../net9.0/staticwebassets.development.json | 2 +- wwwroot/css/leaflet.css | 664 ++++++++++++++++++ wwwroot/images/marker-icon-2x.png | Bin 0 -> 2464 bytes wwwroot/images/marker-icon.png | Bin 0 -> 1466 bytes wwwroot/images/marker-shadow.png | Bin 0 -> 618 bytes wwwroot/js/leaflet.js | 9 + wwwroot/js/lucide.js | 15 + 49 files changed, 1638 insertions(+), 615 deletions(-) create mode 100644 Helpers/Custom.cs create mode 100644 Migrations/20260721071042_LokasiFauna.Designer.cs create mode 100644 Migrations/20260721071042_LokasiFauna.cs create mode 100644 Models/Entity/Master/LokasiFauna.cs create mode 100644 obj/Debug/net9.0/compressed/7h6jxd9k8n-47ih3oe4t7.gz create mode 100644 obj/Debug/net9.0/compressed/wkd5h07ok4-cf9mtx7t7r.gz create mode 100644 obj/Debug/net9.0/compressed/zoo8rffbr6-i65bx55hda.gz create mode 100644 wwwroot/css/leaflet.css create mode 100644 wwwroot/images/marker-icon-2x.png create mode 100644 wwwroot/images/marker-icon.png create mode 100644 wwwroot/images/marker-shadow.png create mode 100644 wwwroot/js/leaflet.js create mode 100644 wwwroot/js/lucide.js diff --git a/Controllers/HomeController.cs b/Controllers/HomeController.cs index 48b076a..415a3d7 100644 --- a/Controllers/HomeController.cs +++ b/Controllers/HomeController.cs @@ -22,6 +22,8 @@ public class HomeController : Controller { //memanggil data lokasi dari master DB Lokasi ViewBag.lokasiHome = await db.Lokasi + .Include(x => x.LokasiFauna) + .Include(x => x.LokasiTumbuhan) .OrderByDescending(l => l.MsLokasiId) .Take(3) .ToListAsync(); @@ -34,19 +36,24 @@ public class HomeController : Controller .OrderByDescending(l => l.MsFaunaId) .Take(4) .ToListAsync(); - - var model = new HomeViewModel - { - Statistik = new StatistikHomeModel - { - TotalLocations = 10, - TotalFlora = 50, - TotalFauna = 30, - TotalSpecies = 80 - }, - }; - return View(model); + ViewBag.TotalLokasi = await db.Lokasi.CountAsync(); + ViewBag.TotalTumbuhan = await db.Tumbuhan.CountAsync(); + ViewBag.TotalFauna = await db.Fauna.CountAsync(); + ViewBag.Total = (ViewBag.TotalTumbuhan+ViewBag.TotalFauna); + + // var model = new HomeViewModel + // { + // Statistik = new StatistikHomeModel + // { + // TotalLocations = 10, + // TotalFlora = 50, + // TotalFauna = 30, + // TotalSpecies = 80 + // }, + // }; + + return View(); } public IActionResult Privacy() diff --git a/Controllers/LokasiController.cs b/Controllers/LokasiController.cs index 851309c..5390ee2 100644 --- a/Controllers/LokasiController.cs +++ b/Controllers/LokasiController.cs @@ -2,6 +2,7 @@ using System.Diagnostics; using Microsoft.AspNetCore.Mvc; using kehati.Models.View; using kehati.Database; +using kehati.Helpers; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; @@ -17,208 +18,21 @@ namespace kehati.Controllers public async Task Index(int page = 1) { ViewBag.lokasiHome = await Pagination.PaginateAsync( - db.Lokasi.OrderByDescending(l => l.MsLokasiId), + db.Lokasi + .Include(x => x.LokasiFauna) + .Include(x => x.LokasiTumbuhan) + .OrderByDescending(l => l.MsLokasiId), page,12); return View(); } - public IActionResult Detail(string slug) + public async Task Detail(string slug) { - ViewBag.Slug = slug; - var lokasi = new LokasiModel - { - Slug = "tebet-eco-park", - Name = "Tebet Eco Park", - Region = "Jakarta Selatan", - Area = "15.3 Ha", - FloraCount = 45, - FaunaCount = 20, - Total = 100, - Description = "Taman kota modern yang mengintegrasikan ekologi dan ruang publik. Rumah bagi puluhan jenis tanaman lokal serta berbagai burung dan serangga penyerbuk.", - Image = "loc-tebet.jpg" - }; - var model = new HomeViewModel - { - - Location = lokasi, - - FeaturedSpesies = new List - { - new() - { - Slug = "pohon-trembesi", - Type = "flora", - CommonName = "Pohon Trembesi", - ScientificName = "Samanea saman", - Description = - "Pohon peneduh raksasa dengan tajuk lebar menyerupai payung. Sangat efektif menyerap karbon dioksida sehingga banyak ditanam di ruang publik Jakarta.", - Habitat = "Tumbuh baik di dataran rendah tropis, tanah subur, sinar matahari penuh.", - ConservationStatus = "Aman", - Image = "sp-trembesi.jpg", - LocationSlugs = new List - { - "tebet-eco-park", - "hutan-kota-gbk", - "taman-menteng" - } - }, - new() - { - Slug= "pohon-beringin", - Type= "flora", - CommonName= "Pohon Beringin", - ScientificName= "Ficus benjamina", - Description= - "Pohon rindang dengan akar udara khas yang menjuntai. Simbol keteduhan dan sering dijumpai di taman kota serta ruang publik Jakarta.", - Habitat= "Iklim tropis, tanah lembab, tahan terhadap polusi udara perkotaan.", - ConservationStatus= "Aman", - Image= "sp-beringin.jpg", - LocationSlugs = new List - {"hutan-kota-srengseng", "taman-menteng", "hutan-kota-gbk"} - }, - new() - { - Slug= "mangrove-rhizophora", - Type= "flora", - CommonName= "Bakau Merah", - ScientificName= "Rhizophora mucronata", - Description= - "Tumbuhan bakau dengan akar tunjang khas. Berfungsi sebagai benteng alami pesisir Jakarta terhadap abrasi dan intrusi air laut.", - Habitat= "Kawasan pesisir berlumpur, muara sungai, air payau.", - ConservationStatus= "Dilindungi", - Image= "sp-mangrove.jpg", - LocationSlugs = new List - {"muara-angke", "mangrove-pik"} - }, - new() - { - Slug= "bunga-kamboja", - Type= "flora", - CommonName= "Kamboja Putih", - ScientificName= "Plumeria alba", - Description= - "Pohon hias berbunga harum dengan kelopak putih dan kuning di tengah. Populer di pekarangan dan taman kota.", - Habitat= "Daerah tropis kering, tanah berdrainase baik.", - ConservationStatus= "Aman", - Image= "sp-kamboja.jpg", - LocationSlugs = new List - {"tebet-eco-park", "taman-menteng"} - }, - new() - { - Slug= "anggrek-bulan", - Type= "flora", - CommonName= "Anggrek Bulan", - ScientificName= "Phalaenopsis amabilis", - Description= - "Bunga nasional Indonesia (Puspa Pesona). Berkelopak lebar putih murni, tumbuh menempel pada batang pohon.", - Habitat= "Epifit pada pohon di hutan tropis lembab.", - ConservationStatus= "Rentan", - Image= "sp-anggrek.jpg", - LocationSlugs = new List - {"hutan-kota-srengseng", "tebet-eco-park"} - }, - new() - { - Slug= "bambu-kuning", - Type= "flora", - CommonName= "Bambu Kuning", - ScientificName= "Bambusa vulgaris", - Description= - "Rumpun bambu berbatang kuning cerah yang tumbuh cepat. Berperan penting menyerap air tanah dan mencegah erosi.", - Habitat= "Tanah lembab di tepi sungai, taman, dan hutan kota.", - ConservationStatus= "Aman", - Image= "sp-bambu.jpg", - LocationSlugs = new List - {"tebet-eco-park", "hutan-kota-srengseng"} - }, - new() - { - Slug= "burung-kutilang", - Type= "fauna", - CommonName= "Burung Kutilang", - ScientificName= "Pycnonotus aurigaster", - Description= - "Burung pengicau kecil dengan tunggir kuning cerah. Salah satu burung liar paling umum di taman-taman Jakarta.", - Habitat= "Taman kota, pekarangan, hutan sekunder.", - ConservationStatus= "Aman", - Image= "sp-kutilang.jpg", - LocationSlugs = new List - {"tebet-eco-park", "taman-menteng", "hutan-kota-gbk"} - }, - new() - { - Slug= "burung-madu-sriganti", - Type= "fauna", - CommonName= "Burung Madu Sriganti", - ScientificName= "Cinnyris jugularis", - Description= - "Burung kecil berwarna cerah, jantan berdada hitam berkilau. Penghisap nektar bunga di taman dan hutan kota.", - Habitat= "Taman berbunga, semak berbunga, pinggir hutan.", - ConservationStatus= "Dilindungi", - Image= "sp-madu-sriganti.jpg", - LocationSlugs = new List - {"tebet-eco-park", "hutan-kota-srengseng", "mangrove-pik"} - }, - new() - { - Slug= "kupu-kupu-raja", - Type= "fauna", - CommonName= "Kupu-kupu Raja", - ScientificName= "Papilio memnon", - Description= - "Kupu-kupu besar berwarna hitam kebiruan dengan sayap lebar. Penyerbuk penting bagi berbagai tanaman berbunga.", - Habitat= "Taman berbunga, hutan sekunder, pinggir sungai.", - ConservationStatus= "Aman", - Image= "sp-kupu-kupu.jpg", - LocationSlugs = new List - {"tebet-eco-park", "hutan-kota-srengseng"} - }, - new() - { - Slug= "biawak-air", - Type= "fauna", - CommonName= "Biawak Air", - ScientificName= "Varanus salvator", - Description= - "Reptil besar semi-akuatik dengan lidah bercabang. Predator alami yang membantu mengendalikan populasi tikus di ekosistem kota.", - Habitat= "Rawa, sungai, hutan mangrove.", - ConservationStatus= "Dilindungi", - Image= "sp-biawak.jpg", - LocationSlugs = new List - {"muara-angke", "mangrove-pik"} - }, - new() - { - Slug= "monyet-ekor-panjang", - Type= "fauna", - CommonName= "Monyet Ekor Panjang", - ScientificName= "Macaca fascicularis", - Description= - "Primata berbulu abu-abu kecoklatan dengan ekor panjang. Hidup berkelompok di kawasan hutan yang tersisa.", - Habitat= "Hutan mangrove, hutan sekunder, tepi sungai.", - ConservationStatus= "Rentan", - Image= "sp-monyet.jpg", - LocationSlugs = new List - {"muara-angke", "mangrove-pik"} - }, - new() - { - Slug= "elang-bondol", - Type= "fauna", - CommonName= "Elang Bondol", - ScientificName= "Haliastur indus", - Description= - "Elang berkepala putih dengan tubuh coklat kemerahan. Maskot Provinsi DKI Jakarta dan simbol kekayaan hayati pesisir.", - Habitat= "Pesisir, mangrove, muara sungai.", - ConservationStatus= "Dilindungi", - Image= "sp-elang-bondol.jpg", - LocationSlugs = new List - {"muara-angke", "mangrove-pik"} - } - } - }; - return View(model); + var decode = Custom.DecodeInt(slug); + ViewBag.data = await db.Lokasi.FirstOrDefaultAsync(x => x.MsLokasiId == decode); + ViewBag.lokasiTumbuhan = await db.LokasiTumbuhan.Include(x => x.Tumbuhan).Where(x => x.MsLokasiId == decode).ToListAsync(); + ViewBag.lokasiFauna = await db.LokasiFauna.Include(x => x.Fauna).Where(x => x.MsLokasiId == decode).ToListAsync(); + return View(); } } } \ No newline at end of file diff --git a/Controllers/MapController.cs b/Controllers/MapController.cs index f93dc93..c3b5d14 100644 --- a/Controllers/MapController.cs +++ b/Controllers/MapController.cs @@ -1,56 +1,27 @@ using Microsoft.AspNetCore.Mvc; +using kehati.Database; using kehati.Models.View; +using Microsoft.EntityFrameworkCore; namespace kehati.Controllers { public class MapController : Controller { - public IActionResult Index() - { - var model = new HomeViewModel - { - FeaturedLocations = new List - { - new() - { - Slug = "tebet-eco-park", - Name = "Tebet Eco Park", - Region = "Jakarta Selatan", - Area = "15.3 Ha", - Latitude = "-6.236993826064424", - Longitude = "106.85290802883573", - FloraCount = 45, - FaunaCount = 20, - Image = "loc-tebet.jpg" - }, - new() - { - Slug = "hutan-kota-srengseng", - Name = "Hutan Kota Srengseng", - Image = "loc-srengseng.jpg", - Region = "Jakarta Barat", - Area = "15.3 Ha", - Latitude = "", - Longitude = "", - FloraCount = 45, - FaunaCount = 20 - }, + private readonly ApplicationDbContext db; - new() - { - Slug = "mangrove-angke", - Name = "Hutan Mangrove Angke", - Region = "Jakarta Barat", - Area = "15.3 Ha", - Latitude = "", - Longitude = "", - FloraCount = 45, - FaunaCount = 20, - Image = "loc-mangrove-pik.jpg" - } - } - }; - return View(model); + public MapController(ApplicationDbContext context) + { + db = context; + } + public async Task Index() + { + ViewBag.lokasiHome = await db.Lokasi + .Where(x => x.Lat != null) + .Include(x => x.LokasiFauna) + .Include(x => x.LokasiTumbuhan) + .OrderByDescending(l => l.MsLokasiId) + .ToListAsync(); + return View(); } public IActionResult Detail(string slug) diff --git a/Database/ApplicationDbContext.cs b/Database/ApplicationDbContext.cs index 2af7c75..7290504 100644 --- a/Database/ApplicationDbContext.cs +++ b/Database/ApplicationDbContext.cs @@ -20,6 +20,7 @@ namespace kehati.Database public DbSet Group { get; set; } public DbSet Habitat { get; set; } public DbSet LokasiTumbuhan { get; set; } + public DbSet LokasiFauna { get; set; } public DbSet Menu { get; set; } public DbSet Tumbuhan { get; set; } public DbSet Fauna { get; set; } diff --git a/Helpers/Custom.cs b/Helpers/Custom.cs new file mode 100644 index 0000000..4a2b8b0 --- /dev/null +++ b/Helpers/Custom.cs @@ -0,0 +1,109 @@ +namespace kehati.Helpers; +using System.Security.Cryptography; +using System.Text; +using kehati.Models.Common; +using Microsoft.EntityFrameworkCore; +public static class Custom +{ + // Ganti dengan secret Anda sendiri + private const string Secret = "kehatiDINASLHDKI-2026"; + + private static byte[] GetKey() + { + return MD5.HashData(Encoding.UTF8.GetBytes(Secret)); + } + + private static byte[] GetIV() + { + byte[] sha = SHA1.HashData(Encoding.UTF8.GetBytes(Secret)); + return sha.Take(16).ToArray(); + } + + public static string Encode(int value) + { + return Encode(value.ToString()); + } + + public static string Encode(string value) + { + string random = RandomString(4); + + string text = random + value; + + using var aes = Aes.Create(); + + aes.Key = GetKey(); + aes.IV = GetIV(); + aes.Mode = CipherMode.CBC; + aes.Padding = PaddingMode.PKCS7; + + using var encryptor = aes.CreateEncryptor(); + + byte[] bytes = Encoding.UTF8.GetBytes(text); + + byte[] encrypted = encryptor.TransformFinalBlock(bytes, 0, bytes.Length); + + string hex = Convert.ToHexString(encrypted).ToLower(); + + return FormatUuid(hex); + } + + public static string Decode(string value) + { + value = value.Replace("-", ""); + + byte[] encrypted = Convert.FromHexString(value); + + using var aes = Aes.Create(); + + aes.Key = GetKey(); + aes.IV = GetIV(); + aes.Mode = CipherMode.CBC; + aes.Padding = PaddingMode.PKCS7; + + using var decryptor = aes.CreateDecryptor(); + + byte[] plain = decryptor.TransformFinalBlock( + encrypted, + 0, + encrypted.Length); + + string result = Encoding.UTF8.GetString(plain); + + // Hilangkan random 4 karakter + return result.Substring(4); + } + + public static int DecodeInt(string value) + { + return int.Parse(Decode(value)); + } + + private static string RandomString(int length) + { + const string chars = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + + Span bytes = stackalloc byte[length]; + + RandomNumberGenerator.Fill(bytes); + + var sb = new StringBuilder(length); + + foreach (byte b in bytes) + sb.Append(chars[b % chars.Length]); + + return sb.ToString(); + } + + private static string FormatUuid(string hex) + { + return + $"{hex[..8]}-" + + $"{hex.Substring(8, 4)}-" + + $"{hex.Substring(12, 4)}-" + + $"{hex.Substring(16, 4)}-" + + $"{hex.Substring(20)}"; + } + +} \ No newline at end of file diff --git a/Migrations/20260721071042_LokasiFauna.Designer.cs b/Migrations/20260721071042_LokasiFauna.Designer.cs new file mode 100644 index 0000000..dbab062 --- /dev/null +++ b/Migrations/20260721071042_LokasiFauna.Designer.cs @@ -0,0 +1,362 @@ +// +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using kehati.Database; + +#nullable disable + +namespace kehati.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20260721071042_LokasiFauna")] + partial class LokasiFauna + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.1") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("kehati.Models.Entity.Master.Famili", b => + { + b.Property("MsFamiliId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("MsFamiliId")); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name"); + + b.HasKey("MsFamiliId"); + + b.ToTable("ms_famili"); + }); + + modelBuilder.Entity("kehati.Models.Entity.Master.Fauna", b => + { + b.Property("MsFaunaId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("MsFaunaId")); + + b.Property("Image") + .HasColumnType("text") + .HasColumnName("image"); + + b.Property("MsFamiliId") + .HasColumnType("text") + .HasColumnName("ms_famili_id"); + + b.Property("MsHabitusId") + .HasColumnType("text") + .HasColumnName("ms_habitus_id"); + + b.Property("NamaIlmiah") + .HasColumnType("text") + .HasColumnName("nama_ilmiah"); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("Slug") + .HasColumnType("text") + .HasColumnName("slug"); + + b.Property("Status") + .HasColumnType("text") + .HasColumnName("status"); + + b.HasKey("MsFaunaId"); + + b.ToTable("ms_fauna"); + }); + + modelBuilder.Entity("kehati.Models.Entity.Master.Group", b => + { + b.Property("MsGroupId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("MsGroupId")); + + b.Property("Alias") + .HasColumnType("text") + .HasColumnName("alias"); + + b.Property("CreatedBy") + .HasColumnType("integer") + .HasColumnName("created_by"); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("Status") + .HasColumnType("text") + .HasColumnName("status"); + + b.Property("UpdatedBy") + .HasColumnType("integer") + .HasColumnName("updated_by"); + + b.HasKey("MsGroupId"); + + b.ToTable("ms_group"); + }); + + modelBuilder.Entity("kehati.Models.Entity.Master.Habitat", b => + { + b.Property("MsHabitusId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("MsHabitusId")); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name"); + + b.HasKey("MsHabitusId"); + + b.ToTable("ms_habitus"); + }); + + modelBuilder.Entity("kehati.Models.Entity.Master.Lokasi", b => + { + b.Property("MsLokasiId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("MsLokasiId")); + + b.Property("Area") + .HasColumnType("text") + .HasColumnName("area"); + + b.Property("Image") + .HasColumnType("text") + .HasColumnName("image"); + + b.Property("Kode") + .HasColumnType("integer") + .HasColumnName("kode"); + + b.Property("Lat") + .HasColumnType("text") + .HasColumnName("lat"); + + b.Property("Long") + .HasColumnType("text") + .HasColumnName("long"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("Region") + .HasColumnType("text") + .HasColumnName("region"); + + b.Property("Slug") + .HasColumnType("text") + .HasColumnName("slug"); + + b.Property("Status") + .HasColumnType("text") + .HasColumnName("status"); + + b.HasKey("MsLokasiId"); + + b.ToTable("ms_lokasi"); + }); + + modelBuilder.Entity("kehati.Models.Entity.Master.LokasiTumbuhan", b => + { + b.Property("MsLokasiTumbuhanId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("MsLokasiTumbuhanId")); + + b.Property("MsLokasiId") + .HasColumnType("integer") + .HasColumnName("ms_lokasi_id"); + + b.Property("MsTumbuhanId") + .HasColumnType("integer") + .HasColumnName("ms_tumbuhan_id"); + + b.HasKey("MsLokasiTumbuhanId"); + + b.HasIndex("MsLokasiId"); + + b.HasIndex("MsTumbuhanId"); + + b.ToTable("ms_lokasi_tumbuhan"); + }); + + modelBuilder.Entity("kehati.Models.Entity.Master.Menu", b => + { + b.Property("MsMenuId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("MsMenuId")); + + b.Property("MenuIcon") + .HasColumnType("text") + .HasColumnName("menu_icon"); + + b.Property("MenuType") + .HasColumnType("text") + .HasColumnName("menu_type"); + + b.Property("Module") + .HasColumnType("text") + .HasColumnName("module"); + + b.Property("Ordering") + .HasColumnType("text") + .HasColumnName("ordering"); + + b.Property("ParentId") + .HasColumnType("integer") + .HasColumnName("parent_id"); + + b.Property("Status") + .HasColumnType("text") + .HasColumnName("status"); + + b.Property("Title") + .HasColumnType("text") + .HasColumnName("title"); + + b.Property("Url") + .HasColumnType("text") + .HasColumnName("url"); + + b.HasKey("MsMenuId"); + + b.ToTable("ms_menu"); + }); + + modelBuilder.Entity("kehati.Models.Entity.Master.Tumbuhan", b => + { + b.Property("MsTumbuhanId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("MsTumbuhanId")); + + b.Property("Cites") + .HasColumnType("text") + .HasColumnName("cites"); + + b.Property("Image") + .HasColumnType("text") + .HasColumnName("image"); + + b.Property("Iucn") + .HasColumnType("text") + .HasColumnName("iucn"); + + b.Property("MsFamiliId") + .HasColumnType("integer") + .HasColumnName("ms_famili_id"); + + b.Property("MsHabitatId") + .HasColumnType("integer") + .HasColumnName("ms_habitus_id"); + + b.Property("NamaIlmiah") + .HasColumnType("text") + .HasColumnName("name_ilmiah"); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("Slug") + .HasColumnType("text") + .HasColumnName("slug"); + + b.Property("StatusPerlindungan") + .HasColumnType("text") + .HasColumnName("status_perlindungan"); + + b.Property("TanamanKhasJakarta") + .HasColumnType("boolean") + .HasColumnName("tanaman_khas_jakarta"); + + b.HasKey("MsTumbuhanId"); + + b.ToTable("ms_tumbuhan"); + }); + + modelBuilder.Entity("kehati.Models.Entity.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Email") + .IsRequired() + .HasColumnType("text"); + + b.Property("MsGroupId") + .HasColumnType("integer") + .HasColumnName("ms_group_id"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Password") + .IsRequired() + .HasColumnType("text"); + + b.Property("Username") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("users"); + }); + + modelBuilder.Entity("kehati.Models.Entity.Master.LokasiTumbuhan", b => + { + b.HasOne("kehati.Models.Entity.Master.Lokasi", "Lokasi") + .WithMany() + .HasForeignKey("MsLokasiId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("kehati.Models.Entity.Master.Tumbuhan", "Tumbuhan") + .WithMany() + .HasForeignKey("MsTumbuhanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Lokasi"); + + b.Navigation("Tumbuhan"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Migrations/20260721071042_LokasiFauna.cs b/Migrations/20260721071042_LokasiFauna.cs new file mode 100644 index 0000000..7271a85 --- /dev/null +++ b/Migrations/20260721071042_LokasiFauna.cs @@ -0,0 +1,47 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace kehati.Migrations +{ + /// + public partial class LokasiFauna : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "ms_lokasi_fauna", + columns: table => new + { + MsLokasiFaunaId = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + ms_lokasi_id = table.Column(type: "integer", nullable: false), + ms_fauna_id = table.Column(type: "integer", nullable: false), + created_at = table.Column(type: "timestamp with time zone", nullable: false), + updated_at = table.Column(type: "timestamp with time zone", nullable: true), + }, + constraints: table => + { + table.PrimaryKey("PK_MsLokasiFaunaId", x => x.MsLokasiFaunaId); + table.ForeignKey( + name: "FK_LokasiId", + column: x => x.ms_lokasi_id, + principalTable: "ms_lokasi", + principalColumn: "MsLokasiId"); + table.ForeignKey( + name: "FK_FaunaId", + column: x => x.ms_fauna_id, + principalTable: "ms_fauna", + principalColumn: "MsFaunaId"); + }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + + } + } +} diff --git a/Migrations/ApplicationDbContextModelSnapshot.cs b/Migrations/ApplicationDbContextModelSnapshot.cs index c7d6a57..16afb98 100644 --- a/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/Migrations/ApplicationDbContextModelSnapshot.cs @@ -30,14 +30,55 @@ namespace kehati.Migrations NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("MsFamiliId")); b.Property("Name") - .IsRequired() - .HasColumnType("text"); + .HasColumnType("text") + .HasColumnName("name"); b.HasKey("MsFamiliId"); b.ToTable("ms_famili"); }); + modelBuilder.Entity("kehati.Models.Entity.Master.Fauna", b => + { + b.Property("MsFaunaId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("MsFaunaId")); + + b.Property("Image") + .HasColumnType("text") + .HasColumnName("image"); + + b.Property("MsFamiliId") + .HasColumnType("text") + .HasColumnName("ms_famili_id"); + + b.Property("MsHabitusId") + .HasColumnType("text") + .HasColumnName("ms_habitus_id"); + + b.Property("NamaIlmiah") + .HasColumnType("text") + .HasColumnName("nama_ilmiah"); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("Slug") + .HasColumnType("text") + .HasColumnName("slug"); + + b.Property("Status") + .HasColumnType("text") + .HasColumnName("status"); + + b.HasKey("MsFaunaId"); + + b.ToTable("ms_fauna"); + }); + modelBuilder.Entity("kehati.Models.Entity.Master.Group", b => { b.Property("MsGroupId") @@ -47,22 +88,24 @@ namespace kehati.Migrations NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("MsGroupId")); b.Property("Alias") - .IsRequired() - .HasColumnType("text"); + .HasColumnType("text") + .HasColumnName("alias"); - b.Property("CreatedBy") - .HasColumnType("integer"); + b.Property("CreatedBy") + .HasColumnType("integer") + .HasColumnName("created_by"); b.Property("Name") - .IsRequired() - .HasColumnType("text"); + .HasColumnType("text") + .HasColumnName("name"); b.Property("Status") - .IsRequired() - .HasColumnType("text"); + .HasColumnType("text") + .HasColumnName("status"); - b.Property("UpdatedBy") - .HasColumnType("integer"); + b.Property("UpdatedBy") + .HasColumnType("integer") + .HasColumnName("updated_by"); b.HasKey("MsGroupId"); @@ -78,8 +121,8 @@ namespace kehati.Migrations NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("MsHabitusId")); b.Property("Name") - .IsRequired() - .HasColumnType("text"); + .HasColumnType("text") + .HasColumnName("name"); b.HasKey("MsHabitusId"); @@ -106,6 +149,14 @@ namespace kehati.Migrations .HasColumnType("integer") .HasColumnName("kode"); + b.Property("Lat") + .HasColumnType("text") + .HasColumnName("lat"); + + b.Property("Long") + .HasColumnType("text") + .HasColumnName("long"); + b.Property("Name") .IsRequired() .HasColumnType("text") @@ -146,6 +197,10 @@ namespace kehati.Migrations b.HasKey("MsLokasiTumbuhanId"); + b.HasIndex("MsLokasiId"); + + b.HasIndex("MsTumbuhanId"); + b.ToTable("ms_lokasi_tumbuhan"); }); @@ -158,38 +213,36 @@ namespace kehati.Migrations NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("MsMenuId")); b.Property("MenuIcon") - .IsRequired() .HasColumnType("text") .HasColumnName("menu_icon"); b.Property("MenuType") - .IsRequired() .HasColumnType("text") .HasColumnName("menu_type"); b.Property("Module") - .IsRequired() - .HasColumnType("text"); + .HasColumnType("text") + .HasColumnName("module"); b.Property("Ordering") - .IsRequired() - .HasColumnType("text"); + .HasColumnType("text") + .HasColumnName("ordering"); - b.Property("ParentId") + b.Property("ParentId") .HasColumnType("integer") .HasColumnName("parent_id"); b.Property("Status") - .IsRequired() - .HasColumnType("text"); + .HasColumnType("text") + .HasColumnName("status"); b.Property("Title") - .IsRequired() - .HasColumnType("text"); + .HasColumnType("text") + .HasColumnName("title"); b.Property("Url") - .IsRequired() - .HasColumnType("text"); + .HasColumnType("text") + .HasColumnName("url"); b.HasKey("MsMenuId"); @@ -281,6 +334,25 @@ namespace kehati.Migrations b.ToTable("users"); }); + + modelBuilder.Entity("kehati.Models.Entity.Master.LokasiTumbuhan", b => + { + b.HasOne("kehati.Models.Entity.Master.Lokasi", "Lokasi") + .WithMany() + .HasForeignKey("MsLokasiId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("kehati.Models.Entity.Master.Tumbuhan", "Tumbuhan") + .WithMany() + .HasForeignKey("MsTumbuhanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Lokasi"); + + b.Navigation("Tumbuhan"); + }); #pragma warning restore 612, 618 } } diff --git a/Models/Entity/Master/Lokasi.cs b/Models/Entity/Master/Lokasi.cs index 2b63015..b0f6987 100644 --- a/Models/Entity/Master/Lokasi.cs +++ b/Models/Entity/Master/Lokasi.cs @@ -21,4 +21,13 @@ public class Lokasi public string? Region { get; set; } = ""; [Column("area")] public string? Area { get; set; } = ""; + [Column("lat")] + public string? Lat { get; set; } = ""; + [Column("long")] + public string? Long { get; set; } = ""; + + public ICollection LokasiTumbuhan { get; set; } = new List(); + + public ICollection LokasiFauna { get; set; } = new List(); + } \ No newline at end of file diff --git a/Models/Entity/Master/LokasiFauna.cs b/Models/Entity/Master/LokasiFauna.cs new file mode 100644 index 0000000..755c937 --- /dev/null +++ b/Models/Entity/Master/LokasiFauna.cs @@ -0,0 +1,23 @@ +namespace kehati.Models.Entity.Master; +using System.ComponentModel.DataAnnotations.Schema; +using System.ComponentModel.DataAnnotations; +[Table("ms_lokasi_fauna")] +public class LokasiFauna +{ + [Key] + public int MsLokasiFaunaId { get; set; } + [Column("ms_fauna_id")] + public int MsFaunaId { get; set; } + [Column("ms_lokasi_id")] + public int MsLokasiId { get; set; } + + //contoh untuk one to many + // public ICollection Tumbuhan { get; set; } = new List(); + + //ini one to one + [ForeignKey(nameof(MsFaunaId))] + public Fauna Fauna { get; set; } = null!; + [ForeignKey(nameof(MsLokasiId))] + public Lokasi Lokasi { get; set; } = null!; + +} \ No newline at end of file diff --git a/Models/Entity/Master/LokasiTumbuhan.cs b/Models/Entity/Master/LokasiTumbuhan.cs index 6f2f8c1..36ed376 100644 --- a/Models/Entity/Master/LokasiTumbuhan.cs +++ b/Models/Entity/Master/LokasiTumbuhan.cs @@ -10,4 +10,14 @@ public class LokasiTumbuhan public int MsTumbuhanId { get; set; } [Column("ms_lokasi_id")] public int MsLokasiId { get; set; } + + //contoh untuk one to many + // public ICollection Tumbuhan { get; set; } = new List(); + + //ini one to one + [ForeignKey(nameof(MsTumbuhanId))] + public Tumbuhan Tumbuhan { get; set; } = null!; + [ForeignKey(nameof(MsLokasiId))] + public Lokasi Lokasi { get; set; } = null!; + } \ No newline at end of file diff --git a/Views/Fauna/Index.cshtml b/Views/Fauna/Index.cshtml index 64808c7..a2b06cc 100644 --- a/Views/Fauna/Index.cshtml +++ b/Views/Fauna/Index.cshtml @@ -1,3 +1,4 @@ +@using kehati.Helpers @using kehati.Models.View @using kehati.Models.Entity.Master @using kehati.Models.Common @@ -20,7 +21,7 @@ Katalog

- Flora & Fauna Jakarta + Fauna Jakarta

Telusuri spesies yang terdokumentasi di kawasan konservasi Jakarta. @@ -43,13 +44,13 @@ + + + + + + +