آکادمی بنو/آموزش Bootstrap

ساخت یک پنل مدیریت Responsive با Bootstrap

بهنام نوبخت · ۱۴۰۵/۷/۱۲

تا اینجا تقریباً تمام ابزارهای اصلی Bootstrap را به‌صورت جداگانه و همچنین در قالب صفحات واقعی بررسی کرده‌ایم. اکنون زمان آن رسیده است که همه این مفاهیم را در یک پروژه کاربردی‌تر ترکیب کنیم: ساخت یک پنل مدیریت Responsive. پنل مدیریت یکی از رایج‌ترین رابط‌های کاربری در پروژه‌های واقعی است و معمولاً شامل Sidebar، Navbar، Dashboard، کارت‌های آماری، جدول اطلاعات، فرم‌ها، اعلان‌ها و بخش‌های مختلف مدیریتی است. در این مقاله یک ساختار واقعی برای پنل مدیریت ایجاد می‌کنیم و یاد می‌گیریم چگونه با استفاده از Grid، Flexbox، Navbar، Offcanvas، Card، Table، Badge، Button، Dropdown، Alert، Modal و Utilities یک داشبورد مدیریتی طراحی کنیم که در دسکتاپ Sidebar داشته باشد و در موبایل همان Sidebar به یک منوی Offcanvas تبدیل شود. همچنین درباره ساختار فایل‌ها، Responsive Design، RTL، Accessibility، جدول‌های مدیریتی، فرم‌های مدیریت اطلاعات، حذف رکوردها، وضعیت کاربران و نکات مهم برای تبدیل این قالب به یک پروژه واقعی با Backend صحبت خواهیم کرد.

1. پنل مدیریت چیست؟

پنل مدیریت یا Admin Dashboard محیطی است که مدیر یا کاربر دارای دسترسی از طریق آن بخش‌های مختلف یک سیستم را مدیریت می‌کند.

برای مثال یک فروشگاه آنلاین ممکن است پنل مدیریتی زیر را داشته باشد:

Admin Panel
 ├── Dashboard
 ├── Products
 ├── Orders
 ├── Users
 ├── Reports
 ├── Settings
 └── Logout

در یک سیستم بزرگ‌تر:

Dashboard
Users
Companies
Advertisements
Categories
Payments
Tickets
Notifications
Reports
Settings

Bootstrap برای ساخت ظاهر این بخش‌ها بسیار مناسب است.

2. ساختار کلی پنل مدیریت

یک پنل مدیریت معمولاً از چهار بخش اصلی تشکیل می‌شود:

Admin Panel
│
├── Sidebar
│
├── Header
│
├── Main Content
│
└── Footer

در دسکتاپ:

+---------+--------------------------------+
|         | Header                         |
| Sidebar |--------------------------------|
|         | Main Content                   |
|         |                                |
|         |                                |
+---------+--------------------------------+

در موبایل:

+--------------------------------+
| Header                    Menu |
|--------------------------------|
|                                |
| Main Content                   |
|                                |
|                                |
+--------------------------------+

بنابراین Sidebar در موبایل باید به شکل دیگری نمایش داده شود.

3. ساختار پیشنهادی پروژه

برای یک پروژه ساده می‌توانیم ساختار زیر را داشته باشیم:

admin-panel/
│
├── index.html
├── users.html
├── products.html
├── orders.html
├── settings.html
│
└── assets/
    ├── css/
    │   └── admin.css
    │
    ├── js/
    │   └── admin.js
    │
    └── images/

در پروژه واقعی که از Backend استفاده می‌کند، ساختار بسته به تکنولوژی تغییر خواهد کرد.

مثلاً در یک پروژه ASP.NET Core:

Backend
    ↓
API
    ↓
Admin Frontend
    ↓
Bootstrap UI

Bootstrap فقط بخش رابط کاربری را مدیریت می‌کند.

4. ساخت Layout اصلی

برای شروع یک Container کلی ایجاد نمی‌کنیم؛ زیرا Sidebar و Main Content باید فضای صفحه را کنترل کنند.

ساختار کلی:

<div class="d-flex">

    <aside>
        Sidebar
    </aside>

    <div class="flex-grow-1">
        Header
        Main
    </div>

</div>

کلاس:

d-flex

باعث می‌شود دو بخش در یک Flex container قرار بگیرند.

کلاس:

flex-grow-1

باعث می‌شود بخش اصلی فضای باقی‌مانده را بگیرد.

5. ساخت Sidebar

ابتدا Sidebar دسکتاپ را طراحی می‌کنیم:

<aside class="bg-dark text-white p-3"
       style="width: 260px; min-height: 100vh;">

    <div class="mb-4">

        <h1 class="h4 mb-0">
            AdminPanel
        </h1>

        <small class="text-white-50">
            مدیریت سیستم
        </small>

    </div>

    <nav>

        <ul class="nav nav-pills flex-column gap-1">

            <li class="nav-item">

                <a href="index.html"
                   class="nav-link active">
                    داشبورد
                </a>

            </li>

            <li class="nav-item">

                <a href="users.html"
                   class="nav-link text-white">
                    کاربران
                </a>

            </li>

            <li class="nav-item">

                <a href="products.html"
                   class="nav-link text-white">
                    محصولات
                </a>

            </li>

            <li class="nav-item">

                <a href="orders.html"
                   class="nav-link text-white">
                    سفارش‌ها
                </a>

            </li>

            <li class="nav-item">

                <a href="settings.html"
                   class="nav-link text-white">
                    تنظیمات
                </a>

            </li>

        </ul>

    </nav>

</aside>

در اینجا از:

  • nav

  • nav-pills

  • flex-column

  • gap-1

  • bg-dark

  • text-white

استفاده کرده‌ایم.

6. مشکل Sidebar در موبایل

اگر همین Sidebar را در موبایل نمایش دهیم، فضای زیادی از صفحه را اشغال می‌کند.

بنابراین بهتر است:

  • دسکتاپ: Sidebar ثابت

  • موبایل: Offcanvas

داشته باشیم.

این همان الگویی است که در مقاله‌های قبلی برای Filter استفاده کردیم.

7. ساخت Mobile Sidebar با Offcanvas

<div
    class="offcanvas offcanvas-start"
    tabindex="-1"
    id="mobileSidebar">

    <div class="offcanvas-header">

        <h2 class="offcanvas-title h5">
            AdminPanel
        </h2>

        <button
            type="button"
            class="btn-close"
            data-bs-dismiss="offcanvas">
        </button>

    </div>

    <div class="offcanvas-body">

        <nav>

            <ul class="nav nav-pills flex-column gap-2">

                <li class="nav-item">

                    <a href="index.html"
                       class="nav-link active">
                        داشبورد
                    </a>

                </li>

                <li class="nav-item">

                    <a href="users.html"
                       class="nav-link">
                        کاربران
                    </a>

                </li>

                <li class="nav-item">

                    <a href="products.html"
                       class="nav-link">
                        محصولات
                    </a>

                </li>

                <li class="nav-item">

                    <a href="orders.html"
                       class="nav-link">
                        سفارش‌ها
                    </a>

                </li>

            </ul>

        </nav>

    </div>

</div>

8. دکمه باز کردن Sidebar

در Navbar موبایل:

<button
    class="btn btn-outline-secondary d-lg-none"
    type="button"
    data-bs-toggle="offcanvas"
    data-bs-target="#mobileSidebar">

    منو

</button>

کلاس:

d-lg-none

باعث می‌شود این Button در نمایشگرهای بزرگ مخفی شود.

9. ساخت Header پنل

Header معمولاً شامل عنوان صفحه، Notification و User Menu است.

<header class="bg-white border-bottom">

    <div class="container-fluid py-3">

        <div class="d-flex align-items-center gap-3">

            <button
                class="btn btn-outline-secondary d-lg-none"
                type="button"
                data-bs-toggle="offcanvas"
                data-bs-target="#mobileSidebar">

                منو

            </button>

            <div class="flex-grow-1">

                <h2 class="h5 mb-0">
                    داشبورد
                </h2>

            </div>

            <button class="btn btn-light position-relative">

                اعلان‌ها

                <span
                    class="position-absolute top-0 start-100 translate-middle badge rounded-pill text-bg-danger">

                    3

                </span>

            </button>

            <div class="dropdown">

                <button
                    class="btn btn-outline-secondary dropdown-toggle"
                    data-bs-toggle="dropdown">

                    مدیر سیستم

                </button>

                <ul class="dropdown-menu dropdown-menu-end">

                    <li>
                        <a class="dropdown-item"
                           href="profile.html">
                            پروفایل
                        </a>
                    </li>

                    <li>
                        <a class="dropdown-item"
                           href="settings.html">
                            تنظیمات
                        </a>
                    </li>

                    <li>
                        <hr class="dropdown-divider">
                    </li>

                    <li>
                        <a class="dropdown-item"
                           href="login.html">
                            خروج
                        </a>
                    </li>

                </ul>

            </div>

        </div>

    </div>

</header>

10. ساخت Dashboard

Dashboard معمولاً اولین صفحه پنل مدیریت است.

یکی از بخش‌های مهم آن کارت‌های آماری است.

<div class="row g-4">

    <div class="col-12 col-sm-6 col-xl-3">

        <div class="card h-100">

            <div class="card-body">

                <p class="text-secondary mb-2">
                    کاربران
                </p>

                <div class="d-flex justify-content-between">

                    <strong class="fs-3">
                        12,540
                    </strong>

                    <span class="badge text-bg-primary">
                        +12%
                    </span>

                </div>

            </div>

        </div>

    </div>

    <div class="col-12 col-sm-6 col-xl-3">

        <div class="card h-100">

            <div class="card-body">

                <p class="text-secondary mb-2">
                    سفارش‌ها
                </p>

                <div class="d-flex justify-content-between">

                    <strong class="fs-3">
                        1,240
                    </strong>

                    <span class="badge text-bg-success">
                        +8%
                    </span>

                </div>

            </div>

        </div>

    </div>

    <div class="col-12 col-sm-6 col-xl-3">

        <div class="card h-100">

            <div class="card-body">

                <p class="text-secondary mb-2">
                    فروش
                </p>

                <div class="d-flex justify-content-between">

                    <strong class="fs-3">
                        850M
                    </strong>

                    <span class="badge text-bg-success">
                        +18%
                    </span>

                </div>

            </div>

        </div>

    </div>

    <div class="col-12 col-sm-6 col-xl-3">

        <div class="card h-100">

            <div class="card-body">

                <p class="text-secondary mb-2">
                    تیکت‌ها
                </p>

                <div class="d-flex justify-content-between">

                    <strong class="fs-3">
                        24
                    </strong>

                    <span class="badge text-bg-warning">
                        جدید
                    </span>

                </div>

            </div>

        </div>

    </div>

</div>

11. طراحی جدول کاربران

یکی از مهم‌ترین قسمت‌های پنل مدیریت، جدول اطلاعات است.

<div class="card mt-4">

    <div class="card-header bg-white">

        <div class="d-flex justify-content-between align-items-center">

            <h2 class="h5 mb-0">
                کاربران اخیر
            </h2>

            <a href="users.html"
               class="btn btn-primary btn-sm">

                مشاهده همه

            </a>

        </div>

    </div>

    <div class="table-responsive">

        <table class="table table-hover align-middle mb-0">

            <thead>

                <tr>

                    <th scope="col">
                        نام
                    </th>

                    <th scope="col">
                        ایمیل
                    </th>

                    <th scope="col">
                        وضعیت
                    </th>

                    <th scope="col">
                        عملیات
                    </th>

                </tr>

            </thead>

            <tbody>

                <tr>

                    <td>
                        علی احمدی
                    </td>

                    <td>
                        ali@example.com
                    </td>

                    <td>
                        <span class="badge text-bg-success">
                            فعال
                        </span>
                    </td>

                    <td>

                        <a
                            href="users.html"
                            class="btn btn-sm btn-outline-primary">

                            مشاهده

                        </a>

                    </td>

                </tr>

                <tr>

                    <td>
                        سارا محمدی
                    </td>

                    <td>
                        sara@example.com
                    </td>

                    <td>
                        <span class="badge text-bg-warning">
                            در انتظار
                        </span>
                    </td>

                    <td>

                        <a
                            href="users.html"
                            class="btn btn-sm btn-outline-primary">

                            مشاهده

                        </a>

                    </td>

                </tr>

            </tbody>

        </table>

    </div>

</div>

12. چرا table-responsive مهم است؟

جدول‌های مدیریتی معمولاً ستون‌های زیادی دارند.

در موبایل ممکن است جدول از صفحه خارج شود.

با:

<div class="table-responsive">

جدول در صورت نیاز به‌صورت افقی Scroll می‌شود.

این روش بسیار بهتر از کوچک کردن بیش از حد جدول است.

13. جدول کامل مدیریت کاربران

اکنون یک صفحه کاربران می‌سازیم.

<div class="card">

    <div class="card-header bg-white">

        <div class="row align-items-center g-3">

            <div class="col">

                <h1 class="h5 mb-0">
                    مدیریت کاربران
                </h1>

            </div>

            <div class="col-auto">

                <button class="btn btn-primary">
                    کاربر جدید
                </button>

            </div>

        </div>

    </div>

    <div class="card-body">

        <div class="row g-3 mb-4">

            <div class="col-md-6">

                <input
                    type="search"
                    class="form-control"
                    placeholder="جستجوی کاربر">

            </div>

            <div class="col-md-3">

                <select class="form-select">

                    <option>
                        همه وضعیت‌ها
                    </option>

                    <option>
                        فعال
                    </option>

                    <option>
                        غیرفعال
                    </option>

                </select>

            </div>

            <div class="col-md-3">

                <button class="btn btn-outline-primary w-100">
                    جستجو
                </button>

            </div>

        </div>

        <div class="table-responsive">

            <table class="table table-hover align-middle">

                <thead>

                    <tr>

                        <th scope="col">
                            #
                        </th>

                        <th scope="col">
                            نام
                        </th>

                        <th scope="col">
                            ایمیل
                        </th>

                        <th scope="col">
                            وضعیت
                        </th>

                        <th scope="col">
                            تاریخ ثبت‌نام
                        </th>

                        <th scope="col">
                            عملیات
                        </th>

                    </tr>

                </thead>

                <tbody>

                    <tr>

                        <td>
                            1
                        </td>

                        <td>
                            علی احمدی
                        </td>

                        <td>
                            ali@example.com
                        </td>

                        <td>

                            <span class="badge text-bg-success">
                                فعال
                            </span>

                        </td>

                        <td>
                            1405/06/20
                        </td>

                        <td>

                            <div class="dropdown">

                                <button
                                    class="btn btn-sm btn-outline-secondary dropdown-toggle"
                                    data-bs-toggle="dropdown">

                                    عملیات

                                </button>

                                <ul class="dropdown-menu">

                                    <li>
                                        <a
                                            class="dropdown-item"
                                            href="#">
                                            مشاهده
                                        </a>
                                    </li>

                                    <li>
                                        <a
                                            class="dropdown-item"
                                            href="#">
                                            ویرایش
                                        </a>
                                    </li>

                                    <li>
                                        <button
                                            class="dropdown-item text-danger">
                                            حذف
                                        </button>
                                    </li>

                                </ul>

                            </div>

                        </td>

                    </tr>

                    <tr>

                        <td>
                            2
                        </td>

                        <td>
                            سارا محمدی
                        </td>

                        <td>
                            sara@example.com
                        </td>

                        <td>

                            <span class="badge text-bg-warning">
                                در انتظار
                            </span>

                        </td>

                        <td>
                            1405/06/18
                        </td>

                        <td>

                            <div class="dropdown">

                                <button
                                    class="btn btn-sm btn-outline-secondary dropdown-toggle"
                                    data-bs-toggle="dropdown">

                                    عملیات

                                </button>

                                <ul class="dropdown-menu">

                                    <li>
                                        <a class="dropdown-item" href="#">
                                            مشاهده
                                        </a>
                                    </li>

                                    <li>
                                        <a class="dropdown-item" href="#">
                                            ویرایش
                                        </a>
                                    </li>

                                    <li>
                                        <button class="dropdown-item text-danger">
                                            حذف
                                        </button>
                                    </li>

                                </ul>

                            </div>

                        </td>

                    </tr>

                </tbody>

            </table>

        </div>

    </div>

</div>

14. Modal برای حذف کاربر

برای عملیات حساس مانند حذف بهتر است مستقیماً عملیات را انجام ندهیم.

ابتدا از کاربر تأیید می‌گیریم.

Button:

<button
    class="dropdown-item text-danger"
    data-bs-toggle="modal"
    data-bs-target="#deleteModal">

    حذف

</button>

Modal:

<div
    class="modal fade"
    id="deleteModal"
    tabindex="-1"
    aria-labelledby="deleteModalLabel"
    aria-hidden="true">

    <div class="modal-dialog modal-dialog-centered">

        <div class="modal-content">

            <div class="modal-header">

                <h2
                    class="modal-title h5"
                    id="deleteModalLabel">

                    حذف کاربر

                </h2>

                <button
                    type="button"
                    class="btn-close"
                    data-bs-dismiss="modal">
                </button>

            </div>

            <div class="modal-body">

                آیا از حذف این کاربر اطمینان دارید؟

            </div>

            <div class="modal-footer">

                <button
                    type="button"
                    class="btn btn-secondary"
                    data-bs-dismiss="modal">

                    انصراف

                </button>

                <button
                    type="button"
                    class="btn btn-danger">

                    حذف کاربر

                </button>

            </div>

        </div>

    </div>

</div>

در پروژه واقعی Button حذف باید به API متصل شود.

15. فرم افزودن کاربر

یک پنل مدیریت معمولاً نیاز به فرم ایجاد و ویرایش اطلاعات دارد.

<div class="card">

    <div class="card-header bg-white">

        <h1 class="h5 mb-0">
            افزودن کاربر
        </h1>

    </div>

    <div class="card-body">

        <form>

            <div class="row g-3">

                <div class="col-md-6">

                    <label
                        for="firstName"
                        class="form-label">

                        نام

                    </label>

                    <input
                        type="text"
                        class="form-control"
                        id="firstName"
                        required>

                </div>

                <div class="col-md-6">

                    <label
                        for="lastName"
                        class="form-label">

                        نام خانوادگی

                    </label>

                    <input
                        type="text"
                        class="form-control"
                        id="lastName"
                        required>

                </div>

                <div class="col-md-6">

                    <label
                        for="email"
                        class="form-label">

                        ایمیل

                    </label>

                    <input
                        type="email"
                        class="form-control"
                        id="email"
                        required>

                </div>

                <div class="col-md-6">

                    <label
                        for="role"
                        class="form-label">

                        نقش

                    </label>

                    <select
                        id="role"
                        class="form-select">

                        <option>
                            کاربر
                        </option>

                        <option>
                            مدیر
                        </option>

                        <option>
                            اپراتور
                        </option>

                    </select>

                </div>

                <div class="col-12">

                    <div class="form-check">

                        <input
                            class="form-check-input"
                            type="checkbox"
                            id="active">

                        <label
                            class="form-check-label"
                            for="active">

                            کاربر فعال باشد

                        </label>

                    </div>

                </div>

                <div class="col-12">

                    <button
                        type="submit"
                        class="btn btn-primary">

                        ذخیره

                    </button>

                    <button
                        type="reset"
                        class="btn btn-outline-secondary">

                        پاک کردن

                    </button>

                </div>

            </div>

        </form>

    </div>

</div>

16. طراحی وضعیت‌های مختلف

در پنل مدیریت، وضعیت‌ها اهمیت زیادی دارند.

می‌توانیم از Badge استفاده کنیم:

<span class="badge text-bg-success">
    فعال
</span>

یا:

<span class="badge text-bg-danger">
    مسدود
</span>

یا:

<span class="badge text-bg-warning">
    در انتظار
</span>

یا:

<span class="badge text-bg-secondary">
    غیرفعال
</span>

بهتر است وضعیت‌های یک سیستم معنای مشخص و ثابتی داشته باشند.

17. ساخت Alert در Dashboard

برای نمایش پیام سیستم:

<div
    class="alert alert-success alert-dismissible fade show"
    role="alert">

    اطلاعات با موفقیت ذخیره شد.

    <button
        type="button"
        class="btn-close"
        data-bs-dismiss="alert">
    </button>

</div>

برای خطا:

<div
    class="alert alert-danger"
    role="alert">

    در ذخیره اطلاعات مشکلی ایجاد شد.

</div>

18. ساخت Progress در Dashboard

Progress می‌تواند برای نمایش وضعیت پردازش یا تکمیل اطلاعات استفاده شود.

<div class="card">

    <div class="card-body">

        <h2 class="h5">
            تکمیل اطلاعات شرکت
        </h2>

        <div class="progress my-3"
             role="progressbar"
             aria-label="تکمیل اطلاعات"
             aria-valuenow="75"
             aria-valuemin="0"
             aria-valuemax="100">

            <div
                class="progress-bar"
                style="width: 75%">

                75%

            </div>

        </div>

    </div>

</div>

19. ساخت Dashboard با Grid

اکنون می‌توانیم کارت‌ها و محتوای اصلی را کنار هم قرار دهیم.

<div class="row g-4">

    <div class="col-12 col-xl-8">

        <div class="card">

            <div class="card-body">

                <h2 class="h5">
                    فعالیت‌های اخیر
                </h2>

                <!-- Activity List -->

            </div>

        </div>

    </div>

    <div class="col-12 col-xl-4">

        <div class="card">

            <div class="card-body">

                <h2 class="h5">
                    وضعیت سیستم
                </h2>

                <!-- System Status -->

            </div>

        </div>

    </div>

</div>

در نمایشگرهای کوچک:

Activity
System Status

و در نمایشگرهای بزرگ:

+----------------------+----------+
| Activity             | Status   |
|                      |          |
+----------------------+----------+

20. ساخت Layout کامل پنل

اکنون اجزای اصلی را کنار هم قرار می‌دهیم.

<div class="d-flex">

    <aside class="d-none d-lg-block">
        Sidebar
    </aside>

    <div class="flex-grow-1">

        <header>
            Header
        </header>

        <main class="p-3 p-md-4">

            Dashboard Content

        </main>

    </div>

</div>

نکته مهم این است که:

d-none d-lg-block

باعث می‌شود Sidebar تا اندازه lg مخفی باشد و از lg به بعد نمایش داده شود.

21. نسخه کامل صفحه Dashboard

نمونه زیر یک قالب قابل اجرا برای شروع پنل است:

<!DOCTYPE html>
<html lang="fa" dir="rtl">

<head>

    <meta charset="UTF-8">

    <meta
        name="viewport"
        content="width=device-width, initial-scale=1">

    <title>
        داشبورد مدیریت
    </title>

    <meta
        name="description"
        content="پنل مدیریت سیستم">

    <link
        href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.rtl.min.css"
        rel="stylesheet">

</head>

<body class="bg-light">

<div class="d-flex">

    <aside
        class="bg-dark text-white p-3 d-none d-lg-block"
        style="width: 260px; min-height: 100vh;">

        <div class="mb-4">

            <h1 class="h4 mb-0">
                AdminPanel
            </h1>

            <small class="text-white-50">
                مدیریت سیستم
            </small>

        </div>

        <nav>

            <ul class="nav nav-pills flex-column gap-1">

                <li class="nav-item">

                    <a
                        href="#"
                        class="nav-link active">

                        داشبورد

                    </a>

                </li>

                <li class="nav-item">

                    <a
                        href="#"
                        class="nav-link text-white">

                        کاربران

                    </a>

                </li>

                <li class="nav-item">

                    <a
                        href="#"
                        class="nav-link text-white">

                        محصولات

                    </a>

                </li>

                <li class="nav-item">

                    <a
                        href="#"
                        class="nav-link text-white">

                        سفارش‌ها

                    </a>

                </li>

                <li class="nav-item">

                    <a
                        href="#"
                        class="nav-link text-white">

                        تنظیمات

                    </a>

                </li>

            </ul>

        </nav>

    </aside>

    <div class="flex-grow-1">

        <header class="bg-white border-bottom">

            <div class="container-fluid py-3">

                <div class="d-flex align-items-center gap-3">

                    <button
                        class="btn btn-outline-secondary d-lg-none"
                        type="button"
                        data-bs-toggle="offcanvas"
                        data-bs-target="#mobileSidebar">

                        منو

                    </button>

                    <div class="flex-grow-1">

                        <h2 class="h5 mb-0">
                            داشبورد
                        </h2>

                    </div>

                    <button
                        class="btn btn-light position-relative">

                        اعلان‌ها

                        <span
                            class="position-absolute top-0 start-100 translate-middle badge rounded-pill text-bg-danger">

                            3

                        </span>

                    </button>

                    <div class="dropdown">

                        <button
                            class="btn btn-outline-secondary dropdown-toggle"
                            data-bs-toggle="dropdown">

                            مدیر سیستم

                        </button>

                        <ul class="dropdown-menu dropdown-menu-end">

                            <li>
                                <a class="dropdown-item" href="#">
                                    پروفایل
                                </a>
                            </li>

                            <li>
                                <a class="dropdown-item" href="#">
                                    تنظیمات
                                </a>
                            </li>

                            <li>
                                <hr class="dropdown-divider">
                            </li>

                            <li>
                                <a class="dropdown-item" href="#">
                                    خروج
                                </a>
                            </li>

                        </ul>

                    </div>

                </div>

            </div>

        </header>

        <main class="container-fluid p-3 p-md-4">

            <div class="mb-4">

                <h1 class="h3 fw-bold">
                    داشبورد
                </h1>

                <p class="text-secondary mb-0">
                    نمای کلی وضعیت سیستم
                </p>

            </div>

            <div class="row g-4">

                <div class="col-12 col-sm-6 col-xl-3">

                    <div class="card h-100">

                        <div class="card-body">

                            <p class="text-secondary">
                                کاربران
                            </p>

                            <strong class="fs-3">
                                12,540
                            </strong>

                            <div class="mt-2">

                                <span class="badge text-bg-success">
                                    +12%
                                </span>

                            </div>

                        </div>

                    </div>

                </div>

                <div class="col-12 col-sm-6 col-xl-3">

                    <div class="card h-100">

                        <div class="card-body">

                            <p class="text-secondary">
                                سفارش‌ها
                            </p>

                            <strong class="fs-3">
                                1,240
                            </strong>

                            <div class="mt-2">

                                <span class="badge text-bg-success">
                                    +8%
                                </span>

                            </div>

                        </div>

                    </div>

                </div>

                <div class="col-12 col-sm-6 col-xl-3">

                    <div class="card h-100">

                        <div class="card-body">

                            <p class="text-secondary">
                                فروش
                            </p>

                            <strong class="fs-3">
                                850M
                            </strong>

                            <div class="mt-2">

                                <span class="badge text-bg-primary">
                                    این ماه
                                </span>

                            </div>

                        </div>

                    </div>

                </div>

                <div class="col-12 col-sm-6 col-xl-3">

                    <div class="card h-100">

                        <div class="card-body">

                            <p class="text-secondary">
                                تیکت‌ها
                            </p>

                            <strong class="fs-3">
                                24
                            </strong>

                            <div class="mt-2">

                                <span class="badge text-bg-warning">
                                    جدید
                                </span>

                            </div>

                        </div>

                    </div>

                </div>

            </div>

            <div class="row g-4 mt-1">

                <div class="col-12 col-xl-8">

                    <div class="card">

                        <div class="card-header bg-white">

                            <h2 class="h5 mb-0">
                                کاربران اخیر
                            </h2>

                        </div>

                        <div class="table-responsive">

                            <table class="table table-hover mb-0">

                                <thead>

                                    <tr>

                                        <th scope="col">
                                            نام
                                        </th>

                                        <th scope="col">
                                            ایمیل
                                        </th>

                                        <th scope="col">
                                            وضعیت
                                        </th>

                                    </tr>

                                </thead>

                                <tbody>

                                    <tr>

                                        <td>
                                            علی احمدی
                                        </td>

                                        <td>
                                            ali@example.com
                                        </td>

                                        <td>

                                            <span class="badge text-bg-success">
                                                فعال
                                            </span>

                                        </td>

                                    </tr>

                                    <tr>

                                        <td>
                                            سارا محمدی
                                        </td>

                                        <td>
                                            sara@example.com
                                        </td>

                                        <td>

                                            <span class="badge text-bg-warning">
                                                در انتظار
                                            </span>

                                        </td>

                                    </tr>

                                    <tr>

                                        <td>
                                            رضا کریمی
                                        </td>

                                        <td>
                                            reza@example.com
                                        </td>

                                        <td>

                                            <span class="badge text-bg-danger">
                                                مسدود
                                            </span>

                                        </td>

                                    </tr>

                                </tbody>

                            </table>

                        </div>

                    </div>

                </div>

                <div class="col-12 col-xl-4">

                    <div class="card">

                        <div class="card-body">

                            <h2 class="h5">
                                تکمیل اطلاعات
                            </h2>

                            <p class="text-secondary">
                                وضعیت اطلاعات شرکت
                            </p>

                            <div
                                class="progress"
                                role="progressbar"
                                aria-label="تکمیل اطلاعات"
                                aria-valuenow="75"
                                aria-valuemin="0"
                                aria-valuemax="100">

                                <div
                                    class="progress-bar"
                                    style="width: 75%">

                                    75%

                                </div>

                            </div>

                        </div>

                    </div>

                </div>

            </div>

        </main>

    </div>

</div>

<div
    class="offcanvas offcanvas-start"
    tabindex="-1"
    id="mobileSidebar">

    <div class="offcanvas-header">

        <h2 class="offcanvas-title h5">
            AdminPanel
        </h2>

        <button
            type="button"
            class="btn-close"
            data-bs-dismiss="offcanvas">
        </button>

    </div>

    <div class="offcanvas-body">

        <nav>

            <ul class="nav nav-pills flex-column gap-2">

                <li class="nav-item">

                    <a
                        href="#"
                        class="nav-link active">

                        داشبورد

                    </a>

                </li>

                <li class="nav-item">

                    <a
                        href="#"
                        class="nav-link">

                        کاربران

                    </a>

                </li>

                <li class="nav-item">

                    <a
                        href="#"
                        class="nav-link">

                        محصولات

                    </a>

                </li>

                <li class="nav-item">

                    <a
                        href="#"
                        class="nav-link">

                        سفارش‌ها

                    </a>

                </li>

                <li class="nav-item">

                    <a
                        href="#"
                        class="nav-link">

                        تنظیمات

                    </a>

                </li>

            </ul>

        </nav>

    </div>

</div>

<script
    src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js">
</script>

</body>

</html>

22. اتصال Dashboard به Backend

در یک پروژه واقعی، اطلاعات زیر معمولاً Static نیستند:

Users Count
Orders Count
Revenue
Tickets
Recent Users
System Status

این اطلاعات از Backend دریافت می‌شوند.

برای مثال:

Admin UI
   ↓
HTTP Request
   ↓
API
   ↓
Database
   ↓
JSON
   ↓
Admin UI

Bootstrap فقط نتیجه را نمایش می‌دهد.

مثلاً API ممکن است داده‌ای مانند این برگرداند:

{
    "users": 12540,
    "orders": 1240,
    "tickets": 24
}

سپس JavaScript یا Framework مورد استفاده، داده‌ها را داخل UI قرار می‌دهد.

23. ساخت Sidebar حرفه‌ای‌تر

در پنل‌های بزرگ تعداد منوها زیاد است.

می‌توانیم از Collapse برای ایجاد Submenu استفاده کنیم.

<a
    class="nav-link text-white"
    data-bs-toggle="collapse"
    href="#contentMenu"
    role="button"
    aria-expanded="false"
    aria-controls="contentMenu">

    مدیریت محتوا

</a>

<div class="collapse" id="contentMenu">

    <ul class="nav flex-column ms-3">

        <li class="nav-item">

            <a
                href="#"
                class="nav-link text-white-50">

                مقالات

            </a>

        </li>

        <li class="nav-item">

            <a
                href="#"
                class="nav-link text-white-50">

                دسته‌بندی‌ها

            </a>

        </li>

    </ul>

</div>

این الگو برای پنل‌هایی با منوی بزرگ بسیار کاربردی است.

24. Pagination در پنل مدیریت

اگر هزاران کاربر داشته باشیم، نباید همه رکوردها را یکجا نمایش دهیم.

از Pagination استفاده می‌کنیم:

<nav aria-label="صفحه کاربران">

    <ul class="pagination">

        <li class="page-item disabled">

            <span class="page-link">
                قبلی
            </span>

        </li>

        <li class="page-item active">

            <a class="page-link" href="#">
                1
            </a>

        </li>

        <li class="page-item">

            <a class="page-link" href="#">
                2
            </a>

        </li>

        <li class="page-item">

            <a class="page-link" href="#">
                3
            </a>

        </li>

        <li class="page-item">

            <a class="page-link" href="#">
                بعدی
            </a>

        </li>

    </ul>

</nav>

در Backend نیز باید Pagination واقعی پیاده‌سازی شود.

مثلاً:

Page = 2
PageSize = 20

و API فقط 20 رکورد مربوط به همان صفحه را برگرداند.

25. جستجو و فیلتر

در پنل‌های مدیریتی جستجو بسیار مهم است.

یک فرم ساده:

<form class="row g-2">

    <div class="col-md-6">

        <input
            type="search"
            class="form-control"
            placeholder="جستجو...">

    </div>

    <div class="col-md-3">

        <select class="form-select">

            <option>
                همه
            </option>

            <option>
                فعال
            </option>

            <option>
                غیرفعال
            </option>

        </select>

    </div>

    <div class="col-md-3">

        <button
            class="btn btn-primary w-100">

            جستجو

        </button>

    </div>

</form>

در یک سیستم واقعی، مقدار Search و Filter به Query Parameters تبدیل می‌شود.

مثلاً:

GET /api/users?search=ali&status=active&page=1

26. RTL در پنل مدیریت

برای پنل فارسی:

<html lang="fa" dir="rtl">

و:

bootstrap.rtl.min.css

استفاده می‌کنیم.

همچنین بهتر است برای فاصله‌ها از Utilityهای منطقی استفاده کنیم:

ms-2
me-2
ps-3
pe-3

به جای وابستگی زیاد به:

margin-left
margin-right

این موضوع باعث می‌شود Layout با جهت صفحه سازگارتر باشد.

27. Accessibility در Admin Panel

پنل مدیریت نیز باید برای کاربران مختلف قابل استفاده باشد.

جدول

از scope استفاده کنید:

<th scope="col">
    نام
</th>

Modal

عنوان مناسب:

<h2 class="modal-title h5">
    حذف کاربر
</h2>

Button

برای عملیات از Button واقعی استفاده کنید:

<button type="button">
    حذف
</button>

Navigation

از nav برای منوی Navigation استفاده کنید.

Focus

نباید با CSS یا طراحی، حالت Focus را به شکلی حذف کنیم که کاربر Keyboard نتواند محل فعلی خود را تشخیص دهد.

28. Responsive Checklist

قبل از نهایی کردن پنل، موارد زیر را بررسی کنید:

Mobile

  • Sidebar به Offcanvas تبدیل می‌شود.

  • جدول قابل Scroll است.

  • کارت‌ها یک ستونه می‌شوند.

  • Buttonها قابل لمس هستند.

  • Header بیش از حد شلوغ نیست.

Tablet

  • Grid مناسب است.

  • Sidebar هنوز فضای زیادی اشغال نمی‌کند.

  • فرم‌ها در چند ستون قابل استفاده هستند.

Desktop

  • Sidebar به‌درستی نمایش داده می‌شود.

  • Main Content فضای کافی دارد.

  • جدول‌ها خوانا هستند.

29. اشتباهات رایج در ساخت Admin Panel

اشتباه اول: Sidebar با عرض ثابت در همه دستگاه‌ها

مثلاً:

.sidebar {
    width: 300px;
}

بدون Responsive Design می‌تواند در موبایل مشکل ایجاد کند.

اشتباه دوم: جدول بدون Responsive Wrapper

اشتباه:

<table class="table">

برای جدول‌های عریض بهتر:

<div class="table-responsive">
    <table class="table">
    </table>
</div>

اشتباه سوم: نمایش تمام داده‌ها

اگر 100,000 کاربر دارید، نباید همه را در یک صفحه Load کنید.

از:

  • Pagination

  • Filtering

  • Search

  • Server-side querying

استفاده کنید.

اشتباه چهارم: انجام عملیات حساس بدون تأیید

مثلاً حذف مستقیم کاربر.

برای عملیات حساس از Confirmation استفاده کنید.

اشتباه پنجم: وابستگی به رنگ تنها

مثلاً وضعیت فقط با رنگ مشخص نشود.

بهتر است:

<span class="badge text-bg-danger">
    مسدود
</span>

هم رنگ و هم متن وضعیت را مشخص می‌کنند.

30. معماری پیشنهادی برای پروژه واقعی

اگر پنل مدیریت قرار است بخشی از یک پروژه واقعی باشد، بهتر است UI را از Backend جدا کنیم.

برای مثال:

Admin Frontend
      ↓
HTTP / API
      ↓
ASP.NET Core
      ↓
Application
      ↓
Database

Bootstrap در بخش Frontend قرار می‌گیرد:

Admin Frontend
 ├── Bootstrap
 ├── Custom CSS
 ├── JavaScript
 └── Components

در پروژه‌هایی مانند Angular یا React نیز Bootstrap می‌تواند برای Styling و Layout استفاده شود.

31. تمرین عملی

تمرین اول: Dashboard

یک Dashboard ایجاد کنید که شامل موارد زیر باشد:

  • Sidebar

  • Header

  • چهار کارت آماری

  • جدول کاربران

  • بخش وضعیت سیستم

  • Footer

تمرین دوم: مدیریت کاربران

صفحه‌ای بسازید که شامل:

  • Search

  • Filter

  • Table

  • Status Badge

  • Edit Button

  • Delete Button

  • Delete Modal

  • Pagination

باشد.

تمرین سوم: مدیریت محصولات

صفحه‌ای بسازید که شامل:

  • Product Table

  • Product Image

  • Product Status

  • Price

  • Category

  • Edit

  • Delete

  • Add Product

باشد.

تمرین چهارم: Sidebar

Sidebar را به شکلی طراحی کنید که:

در Desktop:

Fixed Sidebar

و در Mobile:

Offcanvas Sidebar

باشد.

تمرین پیشرفته

یک Admin Panel کامل برای یک فروشگاه طراحی کنید:

Dashboard
Users
Products
Orders
Categories
Reports
Tickets
Notifications
Settings
Logout

سپس آن را کاملاً Responsive و RTL کنید.

32. جمع‌بندی

در این مقاله یک قدم مهم دیگر در مسیر یادگیری Bootstrap برداشتیم و به جای ساخت Componentهای جداگانه، یک Admin Panel واقعی و Responsive طراحی کردیم. یاد گرفتیم که چگونه Sidebar دسکتاپ را با Offcanvas برای موبایل ترکیب کنیم، چگونه با Grid و Flexbox ساختار اصلی پنل را ایجاد کنیم، چگونه کارت‌های آماری و جدول‌های مدیریتی بسازیم و با Badge، Dropdown، Modal، Alert، Progress و Pagination امکانات مختلفی به Dashboard اضافه کنیم. همچنین دیدیم که Bootstrap فقط ظاهر پنل را ایجاد می‌کند و اطلاعات واقعی باید از Backend و API دریافت شوند. برای پروژه‌های واقعی نیز باید مواردی مانند Pagination سمت سرور، Search، Filtering، Authentication، Authorization، Accessibility، SEO در صفحات عمومی و Performance را در کنار Bootstrap در نظر بگیریم. در نهایت مهم‌ترین نکته این است که یک Admin Panel حرفه‌ای فقط مجموعه‌ای از کلاس‌های Bootstrap نیست؛ بلکه ترکیبی از Layout مناسب، تجربه کاربری، Responsive Design، ساختار قابل نگهداری و اتصال صحیح به Backend است.

۱۰

نظرات

کد در دسترس نیست

هنوز نظری ثبت نشده است.