release version 2.2

This commit is contained in:
abeemanew
2026-02-11 03:27:31 +07:00
parent 2fd0d4ab89
commit c614ac51b0
103 changed files with 79260 additions and 1 deletions

927
basic-form.html Normal file
View File

@@ -0,0 +1,927 @@
<!--
* © 2025-2026 Skoci Admin
* Designed and Developed by Abimanyu
* Contact : abimanyuag12@gmail.com
* All Rights Reserved
-->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="view-transition" content="same-origin">
<title>Skoci Admin | Basic Form</title>
<link rel="icon" type="image/x-icon" href="static/images/favicon.ico">
<!-- Bootstrap 5 -->
<link rel="stylesheet" href="static/vendor/bootstrap/bootstrap.min.css">
<link rel="stylesheet" href="static/css/style.css">
<link rel="stylesheet" href="static/vendor/bootstrap-icons/bootstrap-icons.css">
<!-- Icons -->
<link rel="stylesheet" href="static/vendor/tabler-icons/tabler-icons.css">
<link rel="stylesheet" href="static/vendor/micons/micons.css">
<link rel="stylesheet" href="static/vendor/mdi/materialdesignicons.min.css">
<link rel="stylesheet" href="static/vendor/remixicon/remixicon.css">
<link rel="stylesheet" href="static/vendor/coreui-icons/free.css">
<link rel="stylesheet" href="static/vendor/coreui-icons/brand.css">
<link rel="stylesheet" href="static/vendor/coreui-icons/flag.css">
<script src="static/vendor/jquery/jquery.min.js"></script>
</head>
<body>
<div id="bz-preloader">
<div class="bz-spinner"></div>
</div>
<!-- topbar-right -->
<div class="topbar-right">
<a href="index.html" class="text-decoration-none">
<div class="d-flex align-items-center gap-2">
<img src="static/images/logo.png" alt="logo-icon">
<div class="d-flex flex-column">
<h5 class="mb-0 fw-bold text-light text-uppercase">
Skoci
</h5>
</div>
</div>
</a>
<button id="toggleSidebarRight" class="btn btn-sm toggle-btn">
<i class="ri-arrow-left-s-line chevron"></i>
</button>
</div>
<!-- sidebar-right -->
<div class="sidebar-right">
<ul class="nav flex-column">
<li class="sidebar-title">
<span>Overview</span>
</li>
<li class="nav-item">
<a href="index.html" class="nav-link" data-tooltip="Dashboard">
<i class="ri-apps-line"></i>
<span class="text-wrapper">
<span class="text-inner">Dashboard</span>
</span>
</a>
</li>
<li class="sidebar-title">
<span>Menu</span>
</li>
<li class="nav-item">
<a href="basic-form.html" class="nav-link active" data-tooltip="Form">
<i class="ri-layout-5-line"></i>
<span class="text-wrapper">
<span class="text-inner">Forms</span>
</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link d-flex align-items-center"
data-bs-toggle="collapse"
href="#menuTables"
role="button"
aria-expanded="false"
aria-controls="menuTables">
<i class="ri-table-line"></i>
<span class="text-inner">Tables</span>
<i class="bi bi-chevron-right ms-auto"></i>
</a>
<div class="collapse" id="menuTables">
<ul class="nav flex-column">
<li class="nav-item">
<a href="table1.html" class="nav-link">
DataTables
</a>
</li>
<li class="nav-item">
<a href="table2.html" class="nav-link">
Bootstrap-Table
</a>
</li>
</ul>
</div>
</li>
<li class="nav-item">
<a class="nav-link d-flex align-items-center"
data-bs-toggle="collapse"
href="#menuPages"
role="button"
aria-expanded="false"
aria-controls="menuPages">
<i class="cil-notes"></i>
<span class="text-inner">Pages</span>
<i class="bi bi-chevron-right ms-auto"></i>
</a>
<div class="collapse" id="menuPages">
<ul class="nav flex-column">
<li class="nav-item">
<a href="login.html" class="nav-link">
Login
</a>
</li>
<li class="nav-item">
<a href="404.html" class="nav-link">
404 Page
</a>
</li>
<li class="nav-item">
<a href="403.html" class="nav-link">
403 Page
</a>
</li>
<li class="nav-item">
<a href="blank-page.html" class="nav-link">
Blank Page
</a>
</li>
</ul>
</div>
</li>
<li class="sidebar-title">
<span>UI Elements</span>
</li>
<li class="nav-item">
<a href="alert.html" class="nav-link" data-tooltip="Alert">
<i class="cil-bell"></i>
<span class="text-wrapper">
<span class="text-inner">Alerts</span>
</span>
</a>
</li>
</ul>
</div>
<!-- topbar-main -->
<div class="topbar-main">
<div class="d-flex align-items-center gap-3" style="height: 79px;">
<img class="d-lg-none" src="static/images/logo.png" alt="logo-icon">
<button id="mobileToogle" class="btn btn-topbar d-lg-none d-flex align-items-center justify-content-center">
<i class="ti ti-align-left"></i>
</button>
<div class="vr d-lg-none"></div>
<h5 class="fw-bold mb-0 text-uppercase fs-6 d-flex align-items-center">
Forms
</h5>
</div>
<div class="d-flex align-items-center gap-3">
<div class="position-relative search-form">
<input type="text" class="form-control" placeholder="Search for results...">
<i class="icon-search search-icon position-absolute top-50 end-0 translate-middle-y me-2"></i>
</div>
<div class="vr d-none d-lg-block"></div>
<!-- Cart -->
<button class="btn position-relative p-0 btn-topbar" type="button" data-bs-toggle="offcanvas" data-bs-target="#cartOffcanvas" aria-controls="messagesSidebar">
<i class="cil-cart"></i>
<span class="position-absolute translate-middle badge rounded-pill bg-danger d-flex align-items-center justify-content-center">
4
</span>
</button>
<!-- Notifikasi -->
<button class="btn position-relative p-0 btn-topbar border-0" type="button" data-bs-toggle="offcanvas" data-bs-target="#notificationOffcanvas" aria-controls="notificationOffcanvas">
<i class="cil-bell"></i>
<span class="position-absolute translate-middle badge rounded-pill bg-danger d-flex align-items-center justify-content-center">
2
</span>
</button>
<div class="vr"></div>
<!-- User Profile -->
<button
class="btn btn-link text-secondary text-decoration-none d-flex align-items-center gap-3 p-0"
type="button"
data-bs-toggle="offcanvas"
data-bs-target="#profileOffcanvas"
aria-controls="profileOffcanvas"
>
<img src="static/images/profile.png" alt="Profile Avatar" class="image-profile rounded-circle border border-2">
<div class="d-lg-flex align-items-center gap-1 d-none">
<div class="d-flex flex-column align-items-start lh-sm">
<div class="fw-bold" style="font-size: 1rem;">Admin</div>
<div class="text-muted small opacity-75">Superuser</div>
</div>
<!-- <i class="ti ti-chevron-down align-middle"></i> -->
</div>
</button>
</div>
</div>
<!-- topbar-secondary -->
<div class="topbar-secondary d-flex align-items-center justify-content-between">
<div class="d-flex align-items-center">
<a href="javascript:history.back()" class="btn-back d-none d-lg-block">
<i class="ri-arrow-left-double-line"></i>
</a>
<div class="vr mx-3 d-none d-lg-block"></div>
<h5 class="fw-medium mb-0 text-light">Basic Form</h5>
</div>
<nav>
<ul class="nav nav-pills d-none d-lg-flex overflow-auto flex-nowrap align-items-center">
<li class="nav-item"><a href="basic-form.html" class="nav-link active">Basic Form</a></li>
<li class="nav-item"><a href="advanced-form.html" class="nav-link">Advanced Form</a></li>
<div class="vr me-4 align-self-center bg-light" style="height: 18px; opacity: 0.4;"></div>
<li class="nav-item"><a href="#" class="nav-link" data-bs-toggle="modal" data-bs-target="#confirmModal"><i class="bi bi-info-circle"></i> Information</a></li>
</ul>
<div class="dropdown d-lg-none">
<button class="btn text-light border-0 p-2" type="button" data-bs-toggle="dropdown" aria-expanded="false">
<i class="ri-menu-line fs-5"></i>
</button>
<ul class="dropdown-menu dropdown-menu-end shadow-sm bz-dropdown-menu">
<li>
<a class="dropdown-item active" href="basic-form.html">Basic Form</a>
</li>
<li>
<a class="dropdown-item" href="advanced-form.html">Advanced Form</a>
</li>
<li class="px-2"><hr class="dropdown-divider my-2 opacity-25 border-light"></li>
<li>
<a class="dropdown-item" href="#" data-bs-toggle="modal" data-bs-target="#confirmModal">
<i class="bi bi-info-circle"></i> Information
</a>
</li>
</ul>
</div>
</nav>
</div>
<!-- main-content -->
<div class="main-content">
<div class="container-fluid py-4">
<div class="row mt-2">
<div class="col-12">
<ul class="nav nav-tabs tab-style-1 d-sm-flex d-block" role="tablist">
<li class="nav-item" role="presentation">
<a class="nav-link active" data-bs-toggle="tab" data-bs-target="#tabs-1" aria-current="page" href="#tabs-1" aria-selected="true" role="tab">Tab Input 1</a>
</li>
<li class="nav-item" role="presentation">
<a class="nav-link" data-bs-toggle="tab" data-bs-target="#tabs-2" href="#tabs-2" aria-selected="tabs-2" tabindex="-1" role="tab">Tab Input 2</a>
</li>
</ul>
<div class="tab-content">
<div class="tab-pane fade show active" id="tabs-1" role="tabpanel">
<div class="card shadow-lg border-0">
<form method="POST" enctype="multipart/form-data">
<div class="card-body p-5">
<div class="d-flex justify-content-between align-items-center border-bottom pb-2 mb-4">
<h6 class="mb-0">
Input 1
</h6>
<div class="dropdown">
<button class="btn btn-bz-size bz-btn-outline-primary dropdown-toggle" type="button" id="excelDropdown" data-bs-toggle="dropdown" aria-expanded="false">
Bulk Import
</button>
<div class="dropdown-menu" aria-labelledby="excelDropdown">
<a class="dropdown-item" href="#" target="_blank">Download Template</a>
<a class="dropdown-item" href="#" data-bs-toggle="modal" data-bs-target="#uploadModal">Import Data</a>
</div>
</div>
</div>
<div class="row g-4">
<div class="col-12 col-md-6">
<label for="id_general_input" class="form-label">
Input Label
</label>
<input type="text"
name="general_input"
value="DELL-5430-KYBD"
placeholder="Enter information..."
class="form-control is-invalid"
autocomplete="off"
required
aria-describedby="id_input_help id_input_error"
id="id_general_input">
<div id="id_input_help" class="form-text ms-1 text-muted">
This field is required. Please provide a unique value.
</div>
<div id="id_input_error" class="form-text text-danger ms-1">
An entry with this value already exists in the system.
</div>
</div>
<div class="col-12 col-md-6">
<div class="mb-3">
<label for="id_generic_text" class="form-label">
Input Label
</label>
<input type="text"
name="generic_text"
value="Internal Keyboard US-English"
placeholder="Enter value here..."
class="form-control"
autocomplete="off"
id="id_generic_text"
aria-describedby="generic_text_help">
<div id="generic_text_help" class="form-text ms-1">
Optional. Provide the necessary information for this field.
</div>
</div>
</div>
<div class="col-12 col-md-6">
<div class="mb-3">
<label for="id_general_select" class="form-label">
Select Option
</label>
<select name="general_select" class="form-select" autocomplete="off" id="id_general_select" aria-describedby="select_help">
<option value="" disabled selected>-- Select an option --</option>
<option value="electronics">Electronics</option>
<option value="accessories">Accessories</option>
<option value="office-supplies">Office Supplies</option>
<option value="other">Other</option>
</select>
<div id="select_help" class="form-text ms-1">
Please select one option from the list.
</div>
</div>
</div>
<div class="col-12 col-md-6">
<label for="id_generic_input" class="form-label">
Input Value
</label>
<input type="number"
name="generic_numeric_field"
value="1"
class="form-control numeric-input"
autocomplete="off"
id="id_generic_input"
aria-describedby="generic_help_text">
<div id="generic_help_text" class="form-text ms-1">
Enter a numeric value if applicable.
</div>
</div>
<div class="col-12 col-md-6">
<label for="id_is_active" class="form-label">
Option Status
</label>
<div class="form-check mt-1">
<input type="checkbox"
name="is_active"
class="form-check-input"
id="id_is_active"
checked="">
<label class="form-check-label" for="id_is_active">
Enable this feature
</label>
</div>
<div id="status_help" class="form-text ms-1">
Toggle to set the current availability of this record.
</div>
</div>
<div class="col-12 col-md-6">
<label for="id_general_textarea" class="form-label">
Additional Information
</label>
<textarea
class="form-control"
name="general_notes"
id="id_general_textarea"
rows="4"
placeholder="Provide additional details or notes here..."
aria-describedby="textarea_help"
></textarea>
<div id="textarea_help" class="form-text ms-1">
You may include any relevant notes or details in this section.
</div>
</div>
</div>
<hr class="my-5">
<div class="d-flex justify-content-end">
<button onclick="history.back()" class="btn bz-btn-outline-primary btn-bz-size me-2">Cancel</button>
<button class="btn bz-btn-primary btn-bz-size" type="submit">Submit</button>
</div>
</div>
</form>
</div>
</div>
<div class="tab-pane fade" id="tabs-2" role="tabpanel">
<div class="card shadow-lg border-0">
<form method="GET">
<div class="card-body p-5">
<div class="d-flex justify-content-between align-items-center border-bottom pb-2 mb-4">
<h6 class="mb-0">
Input 2
</h6>
</div>
<div class="row g-4">
<div class="col-12 col-md-6">
<label for="id_image" class="form-label">
Media Upload
</label>
<div>
<img id="imagePreview" src="static/images/placeholder.jpg" alt="Preview" class="mb-3 w-50 rounded border">
</div>
<input type="file"
name="media_file"
class="form-control"
accept="image/*"
autocomplete="off"
id="id_image"
aria-describedby="media_help">
<div id="media_help" class="form-text ms-1">
Accepted formats: JPG, PNG, or WEBP. (Maximum file size: 5MB).
</div>
</div>
</div>
<hr class="my-5">
<div class="d-flex justify-content-end">
<button onclick="history.back()" class="btn bz-btn-outline-primary btn-bz-size me-2">Cancel</button>
<button class="btn bz-btn-primary btn-bz-size" type="submit">Submit</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- offcanvas -->
<div class="offcanvas offcanvas-end" tabindex="-1" id="cartOffcanvas" aria-labelledby="cartOffcanvas">
<div class="offcanvas-header border-bottom">
<div class="d-flex align-items-center w-100">
<div class="flex-grow-1">
<p class="offcanvas-title mb-0 fw-bold" id="cartOffcanvasLabel">
Carts
</p>
<div class="fsmall mb-0">You have 4 item in your cart</div>
</div>
<div class="d-flex align-items-center">
<button type="button" class="btn-close btn-close-white small" data-bs-dismiss="offcanvas" aria-label="Close"></button>
</div>
</div>
</div>
<div class="offcanvas-body p-0">
<div id="cartContainer">
<div class="list-group list-group-flush">
<a href="#" class="list-group-item list-group-item-action border-bottom py-2 px-3">
<div class="d-flex align-items-start">
<div class="me-3">
<div class="rounded-circle bg-primary bg-opacity-10 text-primary d-flex align-items-center justify-content-center"
style="width: 36px; height: 36px;">
<i class="bi bi-cart"></i>
</div>
</div>
<div class="flex-grow-1">
<div class="d-flex justify-content-between align-items-start">
<div>
<div class="fw-bold text-dark mb-1">DELL-5430-KYBD</div>
<div class="text-muted small mb-2">Internal Keyboard US-English</div>
</div>
<small class="text-muted text-nowrap ms-3 d-flex align-items-center">
<i class="ri-time-line me-1"></i>2 minutes ago
</small>
</div>
<div class="text-muted small">Qty: 2 unit(s)</div>
</div>
</div>
</a>
<a href="#" class="list-group-item list-group-item-action border-bottom py-2 px-3">
<div class="d-flex align-items-start">
<div class="me-3">
<div class="rounded-circle bg-primary bg-opacity-10 text-primary d-flex align-items-center justify-content-center"
style="width: 36px; height: 36px;">
<i class="bi bi-cart"></i>
</div>
</div>
<div class="flex-grow-1">
<div class="d-flex justify-content-between align-items-start">
<div>
<div class="fw-bold text-dark mb-1">BATT-54WH-RY</div>
<div class="text-muted small mb-2">Battery 4-Cell 54Wh Long Life</div>
</div>
<small class="text-muted text-nowrap ms-3 d-flex align-items-center">
<i class="ri-time-line me-1"></i>15 minutes ago
</small>
</div>
<div class="text-muted small">Qty: 1 unit(s)</div>
</div>
</div>
</a>
<a href="#" class="list-group-item list-group-item-action border-bottom py-2 px-3">
<div class="d-flex align-items-start">
<div class="me-3">
<div class="rounded-circle bg-primary bg-opacity-10 text-primary d-flex align-items-center justify-content-center"
style="width: 36px; height: 36px;">
<i class="bi bi-cart"></i>
</div>
</div>
<div class="flex-grow-1">
<div class="d-flex justify-content-between align-items-start">
<div>
<div class="fw-bold text-dark mb-1">SSD-NVME-512</div>
<div class="text-muted small mb-2">512GB NVMe M.2 2280 Gen4</div>
</div>
<small class="text-muted text-nowrap ms-3 d-flex align-items-center">
<i class="ri-time-line me-1"></i>1 hours ago
</small>
</div>
<div class="text-muted small">Qty: 5 unit(s)</div>
</div>
</div>
</a>
<a href="#" class="list-group-item list-group-item-action border-bottom py-2 px-3">
<div class="d-flex align-items-start">
<div class="me-3">
<div class="rounded-circle bg-primary bg-opacity-10 text-primary d-flex align-items-center justify-content-center"
style="width: 36px; height: 36px;">
<i class="bi bi-cart"></i>
</div>
</div>
<div class="flex-grow-1">
<div class="d-flex justify-content-between align-items-start">
<div>
<p class="fw-bold text-dark mb-1">MEM-DDR4-16G</p>
<div class="text-muted small mb-2">16GB DDR4 3200MHz SODIMM</div>
</div>
<small class="text-muted text-nowrap ms-3 d-flex align-items-center">
<i class="ri-time-line me-1"></i>2 hours ago
</small>
</div>
<div class="text-muted small">Qty: 3 unit(s)</div>
</div>
</div>
</a>
</div>
</div>
</div>
</div>
<div class="offcanvas offcanvas-end" tabindex="-1" id="notificationOffcanvas" aria-labelledby="notificationOffcanvasLabel">
<div class="offcanvas-header border-bottom">
<div class="d-flex align-items-center w-100">
<div class="flex-grow-1">
<p class="offcanvas-title mb-0 fw-bold" id="notificationOffcanvasLabel">
Notifications
</p>
<div class="fsmall mb-0">You have 2 new notifications</div>
</div>
<div class="d-flex align-items-center">
<button type="button" class="btn-close btn-close-white small" data-bs-dismiss="offcanvas" aria-label="Close"></button>
</div>
</div>
</div>
<div class="offcanvas-body p-0">
<div id="notificationContainer">
<div class="sticky-top bg-light">
<div class="d-flex justify-content-between align-items-center px-2 border">
<div class="d-flex align-items-center ps-2">
<div class="form-check d-flex align-items-center m-0 p-0">
<input class="form-check-input m-0" type="checkbox" id="selectAll">
<label class="form-check-label ms-3" for="selectAll">Select All</label>
</div>
</div>
<div class="d-flex align-items-center">
<div class="btn-group" role="group">
<button type="button" onclick="handleBulkAction('mark_read')" id="btnBulkRead" class="btn btn-sm btn-link text-secondary text-decoration-none">
<i class="ri-mail-open-line"></i><span> Mark Read</span>
</button>
<div class="vr mx-2 align-self-center" style="height: 16px; opacity: 0.2;"></div>
<button type="button" onclick="handleBulkAction('delete')" id="btnBulkDelete" class="btn btn-sm btn-link text-danger text-decoration-none">
<i class="ri-delete-bin-line"></i><span> Delete</span>
</button>
</div>
</div>
</div>
</div>
<div class="list-group list-group-flush">
<!-- Item 1 -->
<div class="list-group-item p-0 border-bottom bg-offcanvas-body text-dark fw-semibold">
<div class="d-flex align-items-start py-2 px-3">
<div class="pe-3 pt-1">
<input class="form-check-input notif-checkbox" type="checkbox">
</div>
<a href="#" class="text-decoration-none text-dark d-flex justify-content-between align-items-start flex-grow-1 gap-3">
<div>
<p class="mb-0 small">
Your Order Has Been Shipped
</p>
<span class="text-muted small">
Order #DO-123456 has shipped to your delivery address
</span>
</div>
<div class="text-muted small text-nowrap d-flex align-items-center pt-1">
<i class="ri-time-line me-1"></i>
2 hours ago
</div>
</a>
</div>
</div>
<!-- Item 2 -->
<div class="list-group-item p-0 border-bottom bg-offcanvas-body text-dark fw-semibold">
<div class="d-flex align-items-start py-2 px-3">
<!-- Checkbox -->
<div class="pe-3 pt-1">
<input class="form-check-input notif-checkbox" type="checkbox">
</div>
<!-- Content -->
<a href="#" class="text-decoration-none text-dark d-flex justify-content-between align-items-start flex-grow-1 gap-3">
<!-- Left -->
<div>
<p class="mb-0 small">
Payment Received
</p>
<span class="text-muted small">
Invoice #INV-202401 has been paid successfully
</span>
</div>
<!-- Time -->
<div class="text-muted small text-nowrap d-flex align-items-center pt-1">
<i class="ri-time-line me-1"></i>
5 hours ago
</div>
</a>
</div>
</div>
<!-- Item 3 -->
<div class="list-group-item p-0 border-bottom text-dark fw-normal">
<div class="d-flex align-items-start py-2 px-3">
<!-- Checkbox -->
<div class="pe-3 pt-1">
<input class="form-check-input notif-checkbox" type="checkbox">
</div>
<!-- Content -->
<a href="#" class="text-decoration-none text-dark d-flex justify-content-between align-items-start flex-grow-1 gap-3">
<!-- Left -->
<div>
<p class="mb-0 small">
New Login Detected
</p>
<span class="text-muted small">
Jakarta, ID • Chrome on Ubuntu
</span>
</div>
<!-- Time -->
<div class="text-muted small text-nowrap d-flex align-items-center pt-1">
<i class="ri-time-line me-1"></i>
Yesterday
</div>
</a>
</div>
</div>
<!-- Item 4 -->
<div class="list-group-item p-0 border-bottom text-dark fw-normal">
<div class="d-flex align-items-start py-2 px-3">
<!-- Checkbox -->
<div class="pe-3 pt-1">
<input class="form-check-input notif-checkbox" type="checkbox">
</div>
<!-- Content -->
<a href="#" class="text-decoration-none text-dark d-flex justify-content-between align-items-start flex-grow-1 gap-3">
<!-- Left -->
<div>
<p class="mb-0 small">
Stock Opname in Progress
</p>
<span class="text-muted small">
Reference: #SO-12-2025 (Warehouse B)
</span>
</div>
<!-- Time -->
<div class="text-muted small text-nowrap d-flex align-items-center pt-1">
<i class="ri-time-line me-1"></i>
4 days ago
</div>
</a>
</div>
</div>
<!-- Item 5 -->
<div class="list-group-item p-0 border-bottom text-dark fw-normal">
<div class="d-flex align-items-start py-2 px-3">
<!-- Checkbox -->
<div class="pe-3 pt-1">
<input class="form-check-input notif-checkbox" type="checkbox">
</div>
<!-- Content -->
<a href="#" class="text-decoration-none text-dark d-flex justify-content-between align-items-start flex-grow-1 gap-3">
<!-- Left -->
<div>
<p class="mb-0 small">
System Test Completed
</p>
<span class="text-muted small">
Reference: #TEST-DEBUG-LOG
</span>
</div>
<!-- Time -->
<div class="text-muted small text-nowrap d-flex align-items-center pt-1">
<i class="ri-time-line me-1"></i>
6 days ago
</div>
</a>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="offcanvas offcanvas-end" tabindex="-1" id="profileOffcanvas" aria-labelledby="profileOffcanvasLabel">
<div class="offcanvas-header border-bottom">
<div class="d-flex align-items-center w-100">
<div class="flex-grow-1">
<p class="offcanvas-title mb-0 fw-bold" id="profileOffcanvasLabel">
Your Account
</p>
<div class="fsmall mb-0">Last sign-in: 02/01/2025-2026 17:36</div>
</div>
<button type="button" class="btn-close btn-close-white small" data-bs-dismiss="offcanvas" aria-label="Close"></button>
</div>
</div>
<div class="offcanvas-body p-0">
<div class="p-4 text-center text-account-dropdown">
<div class="position-relative d-inline-block mx-auto">
<div class="profile-img-container">
<img src="static/images/profile.png" class="img img-thumbnail rounded-circle w-25" alt="Profile Avatar">
</div>
</div>
<div class="fw-bold mt-3 mb-2 opacity-75" style="font-size: 1rem;">Admin</div>
<div class="text-muted fsmall opacity-75">Superuser</div>
<div class="text-muted fsmall opacity-75">admin@mail.com</div>
<div class="mt-3 text-center">
<button type="button" class="btn btn-danger btn-bz-size" onclick="location.href='login.html'">
<i class="ri-logout-box-r-line"></i> Sign Out
</button>
</div>
</div>
</div>
<!-- Copyright -->
<div class="offcanvas-footer p-4 bg-light">
<div class="text-center text-muted fsmall">
<p class="fw-semibold text-dark mb-2">
&copy; 2025-2026&ensp;Skoci Admin<br>All rights reserved.
</p>
<p class="mb-2">
<a href="https://github.com/abeemanew/skoci-admin" target="_blank" class="text-decoration-none text-muted">
<i class="bi bi-github me-1"></i> GitHub Repository
</a>
</p>
<p class="mb-0 d-inline-flex align-items-center">
Built with
<img src="static/images/favicon.ico" alt="Icon" width="18" height="18" class="mx-1">
<span class="fw-semibold text-dark me-1"> Skoci Admin</span> • v2.2
</p>
</div>
</div>
</div>
<!-- modal -->
<div class="modal fade" id="confirmModal" tabindex="-1" aria-labelledby="confirmModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="confirmModalLabel">
Information
</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="mt-3">
<p class="px-3">This is where you can provide detailed information, announcements, or a user guide for your application.</p>
<hr class="my-4">
<div class="d-flex justify-content-end mb-4">
<button type="button" class="btn bz-btn-outline-primary btn-bz-size me-2" data-bs-dismiss="modal">Cancel</button>
<button type="button" class="btn bz-btn-primary btn-bz-size" name="action">Submit</button>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
// Preview Image Browse
$(document).ready(function() {
$('#id_image').change(async function(e) {
const file = this.files[0];
// 1. Tampilkan nama file
// $('#fileName').text(`${file.name} (${formatFileSize(file.size)})`);
$('#fileName').text(file.name);
try {
// 2. Kompres gambar hingga di bawah 1MB
const compressedImage = await compressToMax1MB(file);
// 3. Lakukan crop 4:3 setelah kompresi
const img = new Image();
img.onload = function() {
const croppedUrl = cropTo4_3Ratio(img);
$('#imagePreview').attr('src', croppedUrl).show();
$('#fileInfo').text(`Ukuran akhir: ${formatFileSize(getDataSize(croppedUrl))}`);
};
img.src = compressedImage;
} catch (error) {
alert('Gagal memproses gambar: ' + error.message);
}
});
// Fungsi kompresi dengan target maksimal 1MB
async function compressToMax1MB(file) {
let quality = 0.9; // Mulai dengan kualitas 90%
let result;
// Kompresi bertahap hingga ukuran di bawah 1MB
do {
result = await compressImage(file, quality);
quality -= 0.1; // Turunkan kualitas 10% setiap iterasi
if (quality < 0.1) {
throw new Error('Gambar terlalu besar untuk dikompresi ke bawah 1MB');
}
} while (result.dataSize > 1024 * 1024); // 1MB
return result.url;
}
// Fungsi kompresi gambar
function compressImage(file, quality) {
return new Promise((resolve) => {
const reader = new FileReader();
reader.onload = function(e) {
const img = new Image();
img.onload = function() {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// Hitung ukuran baru dengan menjaga aspect ratio
const maxDimension = 2000; // Batas maksimum dimensi
let width = img.width;
let height = img.height;
if (width > height && width > maxDimension) {
height = (maxDimension / width) * height;
width = maxDimension;
} else if (height > maxDimension) {
width = (maxDimension / height) * width;
height = maxDimension;
}
canvas.width = width;
canvas.height = height;
// Gambar ulang dengan ukuran baru
ctx.drawImage(img, 0, 0, width, height);
// Konversi ke JPEG
const imageUrl = canvas.toDataURL('image/jpeg', quality);
resolve({
url: imageUrl,
dataSize: getDataSize(imageUrl)
});
};
img.src = e.target.result;
};
reader.readAsDataURL(file);
});
}
// Fungsi crop dengan rasio 4:3
function cropTo4_3Ratio(img) {
const targetRatio = 4/3;
let cropWidth, cropHeight;
// Hitung area crop
if (img.width/img.height > targetRatio) {
cropHeight = img.height;
cropWidth = cropHeight * targetRatio;
} else {
cropWidth = img.width;
cropHeight = cropWidth / targetRatio;
}
// Hitung posisi crop (center)
const x = (img.width - cropWidth)/2;
const y = (img.height - cropHeight)/2;
// Buat canvas untuk hasil crop
const canvas = document.createElement('canvas');
canvas.width = cropWidth;
canvas.height = cropHeight;
const ctx = canvas.getContext('2d');
ctx.drawImage(img, x, y, cropWidth, cropHeight, 0, 0, cropWidth, cropHeight);
return canvas.toDataURL('image/jpeg', 0.8);
}
// Helper functions
function getDataSize(dataUrl) {
return Math.round((dataUrl.length - 'data:image/jpeg;base64,'.length) * 3/4);
}
function formatFileSize(bytes) {
if (bytes < 1024) return bytes + ' bytes';
else if (bytes < 1048576) return (bytes/1024).toFixed(1) + ' KB';
else return (bytes/1048576).toFixed(1) + ' MB';
}
});
</script>
<script src="static/js/main.js"></script>
<script src="static/vendor/bootstrap/bootstrap.bundle.min.js"></script>
</body>
</html>