برنامه نویسی

ساخت داشبورد یادگیری و دستاوردهای برجسته با طراحی صورتی (Next.js)

در طول سال ها، اینترنت و شبکه جهانی وب رشد فوق العاده ای داشته است. این به شرکت‌ها این امکان را می‌دهد که تیم‌های چندکاره بسازند و محصولات خود را به طیف وسیع‌تری از مخاطبان ارسال کنند.

به قول معروف، “با قدرت بزرگ، مسئولیت بزرگ به وجود می آید”. سازمان‌های متوسط ​​تا بزرگ با تیم‌های جهانی دائماً با بار کاری ایجاد منبع حقیقت و حفظ یکپارچگی نام تجاری در هنگام ساختن نرم‌افزار در کانال‌های متعدد تحت فشار هستند.

در این پست، نحوه ساخت داشبورد مانیتورینگ با استفاده از Next.js، Appwrite و Pink Design را یاد خواهیم گرفت. مخزن GitHub پروژه را می توانید در اینجا بیابید.

پیش نیازها

برای درک کامل مفاهیم ارائه شده در این آموزش، موارد زیر مورد نیاز است:

  • درک اولیه جاوا اسکریپت و React.js
  • حساب ابری Appwrite (ترجیحا) یا یک نمونه Appwrite در حال اجرا در docker. این مقاله را در مورد نحوه تنظیم یا نصب یک نمونه با یک کلیک روی DigitalOcean یا Gitpod بررسی کنید.

شروع شدن

ما باید با رفتن به دایرکتوری مورد نظر و اجرای دستور زیر در ترمینال، یک پروژه شروع Next.js ایجاد کنیم.

npx create-next-app@latest pink-dashboard && cd pink-dashboard
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این دستور از ما سؤالاتی در مورد نحوه پیکربندی برنامه خود می پرسد. می‌توانیم به سؤالات زیر پاسخ دهیم:

Would you like to use TypeScript with this project? <select "No" and press enter>
Would you like to use ESLint with this project? <select "No" and press enter>
Would you like to use `src/` directory with this project? <select "Yes" and press enter>
Would you like to use experimental `app/` directory with this project? <select "No" and press enter>
What import alias would you like configured? <press enter>
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این دستور یک پروژه Nuxt.js به نام ایجاد می کند pink-dashboard و وارد فهرست پروژه می شود.

نصب وابستگی ها

نصب طرح صورتی

Pink Design سیستم طراحی منبع باز Appwrite برای ایجاد رابط های کاربری سازگار و قابل استفاده مجدد است. مجموعه‌ای از استانداردها را ارائه می‌کند که شرکت‌ها می‌توانند به عنوان منبعی از حقیقت برای ایجاد تجربه یکپارچه در کانال‌های متعدد استفاده کنند. برای استفاده از آن در برنامه ما، دستور زیر را در ترمینال خود اجرا کنید.

npm install @appwrite.io/pink
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در مرحله بعد، ما باید آن را به روز کنیم src/_app.js فایل با CSS مورد نیاز و کتابخانه نماد که Pink Design با آن ارسال می شود.

import '@appwrite.io/pink';
import '@appwrite.io/pink-icons';

export default function App({ Component, pageProps }) {
    return <Component {...pageProps} />;
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در حال نصب Appwrite
Appwrite یک پلتفرم توسعه است که یک API و کنسول مدیریتی قدرتمند برای ساخت سرورهای بک‌اند برای برنامه‌های وب و موبایل ارائه می‌کند. برای نصب آن دستور زیر را اجرا کنید:

npm install appwrite
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

ساخت رابط کاربری (UI)

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

پیش نمایش طراحی

ایجاد اجزا

برای شروع، ابتدا باید به مسیر بروید src دایرکتوری و ایجاد یک component پوشه، و در این پوشه، a ایجاد کنید DashboardCard.js فایل و قطعه زیر را اضافه کنید:

import React from 'react';

const DashboardCard = () => {
    return (
        <div
            className='card u-flex'
            style={{
                boxShadow: 'var(--shadow-small)',
                paddingTop: '0px',
                paddingBottom: '0px',
            }}
        >
            <section
                style={{
                    marginLeft: '40px',
                    borderRightStyle: 'solid',
                    borderRightWidth: '1px',
                    borderRightColor: 'hsl(var(--color-neutral-30))',
                    paddingTop: '33px',
                    paddingBottom: '20px',
                    width: '100%',
                }}
            >
                <div className='u-flex u-cross-center'>
                    <p
                        className='icon-academic-cap'
                        style={{ marginRight: '15px' }}
                    ></p>
                    <h5 className='u-bold'>Total project courses</h5>
                </div>
                <h1
                    className='u-bold'
                    style={{ fontSize: '80px', color: '#5D5FEF' }}
                >
                    1200
                </h1>
            </section>
            <section
                style={{
                    marginLeft: '80px',
                    paddingTop: '33px',
                    paddingBottom: '20px',
                    width: '100%',
                }}
            >
                <div className='u-flex u-cross-center'>
                    <p
                        className='icon-user'
                        style={{ marginRight: '15px' }}
                    ></p>
                    <h5 className='u-bold'>Total students</h5>
                </div>
                <h1
                    className='u-bold'
                    style={{ fontSize: '80px', color: '#5D5FEF' }}
                >
                    120
                </h1>
            </section>
        </div>
    );
};
export default DashboardCard;
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

قطعه بالا از کلاس‌های کاربردی Pink Design، عناصر، طرح‌بندی و نمادها برای ساخت مؤلفه کارت داشبورد استفاده می‌کند.

در نهایت، ما نیاز به ایجاد یک ListingCard.js فایل و قطعه زیر را اضافه کنید:

import React from 'react';

const ListingCard = ({
    firstname,
    lastname,
    projectTitle,
    courses,
    status,
}) => {
    return (
        <div
            className='card u-flex u-main-space-between'
            style={{
                boxShadow: 'var(--shadow-small)',
                paddingTop: '11px',
                paddingBottom: '11px',
                paddingLeft: '30px',
                paddingRight: '30px',
                borderRadius: 'var(--border-radius-small)',
                marginBottom: '15px',
            }}
        >
            <section className='u-flex u-cross-center'>
                <div
                    className='u-flex u-main-center u-cross-center'
                    style={{
                        height: '40px',
                        width: '40px',
                        backgroundColor: '#E084A9',
                        borderRadius: 'var(--border-radius-circular)',
                        marginRight: '30px',
                    }}
                >
                    <p
                        className='u-bold'
                        style={{
                            color: 'hsl(var(--color-neutral-0))',
                            letterSpacing: '4.5%',
                        }}
                    >
                        {`${firstname.charAt(0)} ${lastname.charAt(0)}`}
                    </p>
                </div>
                <div>
                    <p
                        className='u-bold text'
                        style={{
                            color: 'hsl(var(--color-neutral-500))',
                            marginBottom: '7px',
                            textTransform: 'capitalize',
                        }}
                    >
                        {`${firstname} ${lastname}`}
                    </p>
                    <p className='text' style={{ marginBottom: '7px' }}>
                        {projectTitle}
                    </p>
                </div>
            </section>
            <section>
                <div
                    className='u-flex u-cross-center'
                    style={{ marginBottom: '8px' }}
                >
                    <p
                        className='icon-book-open'
                        style={{ marginRight: '15px' }}
                    ></p>
                    <h5 className='u-bold'>{`${courses} courses`}</h5>
                </div>
                <div
                    className='u-bold'
                    style={{
                        paddingTop: '4px',
                        paddingBottom: '4px',
                        paddingLeft: '18px',
                        paddingRight: '18px',
                        backgroundColor: '#DDDDFB',
                        color: '#5D5FEF',
                        textTransform: 'uppercase',
                        borderRadius: 'var(--border-radius-medium)',
                        fontSize: '10px',
                    }}
                >
                    {status}
                </div>
            </section>
        </div>
    );
};
export default ListingCard;
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

قطعه قطعه ای را ایجاد می کند که مجموعه ای از ویژگی های مورد نیاز را می پذیرد و از سیستم Pink Design برای ساخت کارت لیست استفاده می کند.

کنار هم گذاشتن

با کامپوننت های ایجاد شده، می توانیم به روز رسانی کنیم pages/index.js فایل مطابق شکل زیر:

import Head from 'next/head';
import { Inter } from 'next/font/google';
import DashboardCard from '@/components/DashboardCard';
import ListingCard from '@/components/ListingCard';
const inter = Inter({ subsets: ['latin'] });

export default function Home() {
    return (
        <>
            <Head>
                <title>Student Dashbaord</title>
                <meta
                    name='Student Dashboard'
                    content='Generated by create next app'
                />
                <meta
                    name='viewport'
                    content='width=device-width, initial-scale=1'
                />
                <link rel='icon' href='/favicon.ico' />
            </Head>
            <main
                className='u-padding-32'
                style={{ backgroundColor: 'hsl(var(--color-neutral-5))' }}
            >
                <h1
                    className='text u-font-size-32 u-bold'
                    style={{
                        color: 'hsl(var(--color-neutral-500))',
                        marginBottom: '30px',
                    }}
                >
                    Dashboard
                </h1>
                <DashboardCard />
                <section className='' style={{ marginTop: '60px' }}>
                    <h5
                        className='text u-bold heading-level-7'
                        style={{
                            color: 'hsl(var(--color-neutral-500))',
                            marginBottom: '30px',
                        }}
                    >
                        Project listing
                    </h5>
                    <section>
                        <ListingCard
                            firstname='Arnold'
                            lastname='Mark'
                            projectTitle='Leveraging Appwrite to build SaaS company using serverless architecture'
                            courses={35}
                            status='in progress'
                        />
                    </section>
                </section>
            </main>
        </>
    );
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

قطعه بالا از اجزای ایجاد شده برای ساخت رابط داشبورد استفاده می کند.

ما می توانیم برنامه خود را با اجرای دستور زیر آزمایش کنیم:

npm run dev
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

برنامه در حال اجرا

راه اندازی Appwrite

برای شروع، باید وارد حساب کاربری ابری Appwrite خود شویم، ورودی pink_dashboard به عنوان نام، و سپس کلیک کنید پروژه ایجاد کنید.

پروژه ایجاد کنید

یک پایگاه داده، مجموعه، ویژگی ها و داده های نمونه ایجاد کنید

با ایجاد پروژه ما، می توانیم پایگاه داده برنامه خود را راه اندازی کنیم. ابتدا به مسیر بروید پایگاه داده برگه را کلیک کنید ایجاد پایگاه داده دکمه، ورودی projects به عنوان نام، و سپس کلیک کنید ايجاد كردن.

ایجاد پایگاه داده

در مرحله دوم، باید مجموعه ای برای ذخیره جزئیات پروژه ایجاد کنیم. برای انجام این کار، روی مجموعه ایجاد کنید دکمه، ورودی project_listing به عنوان نام، و سپس کلیک کنید ايجاد كردن.

ایجاد مجموعه

ثالثاً، ما نیاز به ایجاد ویژگی هایی برای نمایش فیلدهای پایگاه داده خود داریم. برای انجام این کار، باید به مسیر بروید ویژگی های برگه کنید و برای مجموعه ما مشخصه ها را مطابق شکل زیر ایجاد کنید:

کلید ویژگی نوع صفت اندازه عناصر ضروری
نام کوچک رشته 225 صفر آره
نام خانوادگی رشته 225 صفر آره
عنوان پروژه رشته 5000 صفر آره
دوره های آموزشی بین المللی صفر صفر آره
وضعیت enum صفر در حال پیش رفت
تکمیل شد
متوقف شد
آره

ایجاد عنصر
enum را پیکربندی کنید
صفات ایجاد کرد

چهارم، ما باید مجوز مجموعه خود را به روز کنیم تا آنها را بر اساس آن مدیریت کنیم. برای انجام این کار، به مسیر بروید تنظیمات برگه، به پایین بروید به روز رسانی مجوزها بخش، انتخاب کنید Any، بر این اساس علامت گذاری کنید و به روز رسانی.

Any را انتخاب کنید و به روز کنید

در نهایت، ما باید داده های نمونه را برای شبیه سازی داشبورد خود اضافه کنیم. برای انجام این کار، باید به مسیر بروید سند برگه را کلیک کنید سند ایجاد کنید همانطور که در طرح زیر نشان داده شده است، داده ها را به مجموعه اضافه کنید:

داده های نمونه

داده های اضافه شده در Appwrite

ادغام Appwrite با Next.js

برای شروع، ابتدا باید a را ایجاد کنیم components/utils.js برای انتزاع منطق برنامه از رابط کاربری و اضافه کردن قطعه زیر:

import { Client, Databases, Account } from 'appwrite';

const PROJECT_ID = 'REPLACE WITH PROJECT ID';
const DATABASE_ID = 'REPLACE WITH DATABASE ID';
const COLLECTION_ID = 'REPLACE WITH COLLECTION ID';

const client = new Client();

const databases = new Databases(client);

client.setEndpoint('https://cloud.appwrite.io/v1').setProject(PROJECT_ID);

export const account = new Account(client);

export const getProjectListing = () =>
    databases.listDocuments(DATABASE_ID, COLLECTION_ID);
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

قطعه بالا کارهای زیر را انجام می دهد:

  • وابستگی مورد نیاز را وارد می کند
  • Appwrite را راه اندازی می کند client و databases با آرگومان های مورد نیاز
  • ایجاد می کند account و getProjectListing توابعی برای مدیریت جلسات کاربر و دریافت لیست پروژه ها در پایگاه داده

PS: ما می توانیم شناسه های مورد نیاز را در کنسول Appwrite خود دریافت کنیم.

در مرحله دوم، ما باید به روز رسانی _app.js فایل برای استفاده از account تابع کمکی برای بررسی اینکه آیا کاربر یک جلسه معتبر دارد یا خیر.

import { account } from '@/components/utils';
import '@appwrite.io/pink';
import '@appwrite.io/pink-icons';
import { useEffect } from 'react';

export default function App({ Component, pageProps }) {
    useEffect(() => {
        account
            .get()
            .then()
            .catch((_) => account.createAnonymousSession());
        return () => {};
    }, []);
    return <Component {...pageProps} />;
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در نهایت، ما باید آن را به روز کنیم index.js فایل مطابق شکل زیر:

import Head from 'next/head';
import { Inter } from 'next/font/google';
import DashboardCard from '@/components/DashboardCard';
import ListingCard from '@/components/ListingCard';
import { useState, useEffect } from 'react';
import { getProjectListing } from '@/components/utils';
const inter = Inter({ subsets: ['latin'] });

export default function Home() {
    const [data, setData] = useState(null);

    useEffect(() => {
        getProjectListing()
            .then((res) => setData(res))
            .catch((err) => alert('Error loading dashboard data'));
        return () => {};
    }, []);

    return (
        <>
            <Head>
                <title>Student Dashbaord</title>
                <meta
                    name='Student Dashboard'
                    content='Generated by create next app'
                />
                <meta
                    name='viewport'
                    content='width=device-width, initial-scale=1'
                />
                <link rel='icon' href='/favicon.ico' />
            </Head>
            <main
                className='u-padding-32'
                style={{ backgroundColor: 'hsl(var(--color-neutral-5))' }}
            >
                <h1
                    className='text u-font-size-32 u-bold'
                    style={{
                        color: 'hsl(var(--color-neutral-500))',
                        marginBottom: '30px',
                    }}
                >
                    Dashboard
                </h1>
                <DashboardCard data={data} />
                <section className='' style={{ marginTop: '60px' }}>
                    <h5
                        className='text u-bold heading-level-7'
                        style={{
                            color: 'hsl(var(--color-neutral-500))',
                            marginBottom: '30px',
                        }}
                    >
                        Project listing
                    </h5>
                    <section>
                        {data &&
                            data.documents.map((list) => (
                                <ListingCard
                                    key={list.$id}
                                    firstname={list.firstname}
                                    lastname={list.lastname}
                                    projectTitle={list.projectTitle}
                                    courses={list.courses}
                                    status={list.status}
                                />
                            ))}
                    </section>
                </section>
            </main>
        </>
    );
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

قطعه بالا کارهای زیر را انجام می دهد:

  • وابستگی های مورد نیاز را وارد می کند
  • حالت برنامه را ایجاد می کند
  • استفاده می کند getProjectListing تابع helper برای دریافت لیست پروژه ها پس از رندر
  • اجزا را با عبور دادن قطعات مورد نیاز اصلاح می کند

به روز رسانی کامپوننت ها

ابتدا باید به روز رسانی کنیم DashboardCard.js جزء مطابق شکل زیر:

import React from 'react';

const DashboardCard = ({ data }) => {
    //modify
    const getTotal = () =>
        data.documents
            .map((list) => list.courses)
            .reduce((prev, next) => prev + next);

    return (
        <div
            className='card u-flex'
            style={{
                boxShadow: 'var(--shadow-small)',
                paddingTop: '0px',
                paddingBottom: '0px',
            }}
        >
            <section
                style={{
                    marginLeft: '40px',
                    borderRightStyle: 'solid',
                    borderRightWidth: '1px',
                    borderRightColor: 'hsl(var(--color-neutral-30))',
                    paddingTop: '33px',
                    paddingBottom: '20px',
                    width: '100%',
                }}
            >
                <div className='u-flex u-cross-center'>
                    <p
                        className='icon-academic-cap'
                        style={{ marginRight: '15px' }}
                    ></p>
                    <h5 className='u-bold'>Total project courses</h5>
                </div>
                <h1
                    className='u-bold'
                    style={{ fontSize: '80px', color: '#5D5FEF' }}
                >
                    {data ? getTotal() : 0}
                </h1>
            </section>
            <section
                style={{
                    marginLeft: '80px',
                    paddingTop: '33px',
                    paddingBottom: '20px',
                    width: '100%',
                }}
            >
                <div className='u-flex u-cross-center'>
                    <p
                        className='icon-user'
                        style={{ marginRight: '15px' }}
                    ></p>
                    <h5 className='u-bold'>Total students</h5>
                </div>
                <h1
                    className='u-bold'
                    style={{ fontSize: '80px', color: '#5D5FEF' }}
                >
                    {data ? data.total : 0}
                </h1>
            </section>
        </div>
    );
};
export default DashboardCard;
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

قطعه بالا کارهای زیر را انجام می دهد:

  • کامپوننت را برای پذیرش props تغییر می دهد
  • a را ایجاد می کند getTotal تابع کمکی برای دریافت کل دوره های موجود
  • UI را برای نمایش مقادیر بازگشتی از پایگاه داده تغییر می دهد

در نهایت، ما نیز باید آن را اصلاح کنیم ListingCard.js جزء مطابق شکل زیر:

import React from 'react';

const ListingCard = ({
    firstname,
    lastname,
    projectTitle,
    courses,
    status,
}) => {
    const bgColorHelper = (statusState) =>
        statusState == 'inProgress'
            ? '#DDDDFB'
            : statusState == 'completed'
            ? '#F0FEF7'
            : '#FFF4F5';

    const textColorHelper = (statusState) =>
        statusState == 'inProgress'
            ? '#5D5FEF'
            : statusState == 'completed'
            ? '#01754A'
            : '#B51212';
    return (
        <div
            className='card u-flex u-main-space-between'
            style={{
                boxShadow: 'var(--shadow-small)',
                paddingTop: '11px',
                paddingBottom: '11px',
                paddingLeft: '30px',
                paddingRight: '30px',
                borderRadius: 'var(--border-radius-small)',
                marginBottom: '15px',
            }}
        >
            <section className='u-flex u-cross-center'>
                <div
                    className='u-flex u-main-center u-cross-center'
                    style={{
                        height: '40px',
                        width: '40px',
                        backgroundColor: '#E084A9',
                        borderRadius: 'var(--border-radius-circular)',
                        marginRight: '30px',
                    }}
                >
                    <p
                        className='u-bold'
                        style={{
                            color: 'hsl(var(--color-neutral-0))',
                            letterSpacing: '4.5%',
                            textTransform: 'capitalize',
                        }}
                    >
                        {`${firstname.charAt(0)} ${lastname.charAt(0)}`}
                    </p>
                </div>
                <div>
                    <p
                        className='u-bold text'
                        style={{
                            color: 'hsl(var(--color-neutral-500))',
                            marginBottom: '7px',
                            textTransform: 'capitalize',
                        }}
                    >
                        {`${firstname} ${lastname}`}
                    </p>
                    <p className='text' style={{ marginBottom: '7px' }}>
                        {projectTitle}
                    </p>
                </div>
            </section>
            <section className='u-flex u-flex-vertical u-cross-end'>
                <div
                    className='u-flex u-cross-center'
                    style={{ marginBottom: '8px' }}
                >
                    <p
                        className='icon-book-open'
                        style={{ marginRight: '15px' }}
                    ></p>
                    <h5 className='u-bold'>{`${courses} courses`}</h5>
                </div>
                <div
                    className='u-bold'
                    style={{
                        paddingTop: '4px',
                        paddingBottom: '4px',
                        paddingLeft: '18px',
                        paddingRight: '18px',
                        backgroundColor: bgColorHelper(status),
                        color: textColorHelper(status),
                        textTransform: 'uppercase',
                        borderRadius: 'var(--border-radius-medium)',
                        fontSize: '10px',
                    }}
                >
                    {status}
                </div>
            </section>
        </div>
    );
};

export default ListingCard;
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

قطعه بالا کارهای زیر را انجام می دهد:

  • ایجاد می کند bgColorHelper و textColorHelper توابع برای نشان دادن رنگ مناسب به صورت پویا
  • رابط کاربری را با استفاده از توابع کمکی به روز می کند تا پس زمینه و رنگ فونت مناسب را به صورت پویا نمایش دهد

با انجام این کار، می توانیم یک سرور توسعه را با استفاده از دستور زیر راه اندازی مجدد کنیم:

npm run dev
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

نمونه کار

در این پست نحوه ساخت داشبورد مانیتورینگ با استفاده از Next.js، Appwrite و Pink Design بحث شد. سیستم طراحی صورتی به توسعه دهندگان و شرکت ها اجازه می دهد تا سیستم های پیچیده ای را در محصولات موجود خود بسازند. رویکرد Framework-Agnostic همچنین آن را برای چندین تیم با استفاده از فریم‌ورک‌های front-end مختلف سازگار می‌کند.

این منابع نیز ممکن است مفید باشند:

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا