نبذة تعريفية

رامى أحمد

الحمد لله الذي علَّم بالقلم، علَّم الإنسان ما لم يعلم، والصلاة والسلام على خير معلم الناس الخير سيدنا محمد - صلى الله عليه وسلم .. أما بعد ،،

اسمى رامى أحمد، بفضل الله - مؤسس منصة مرتكز

أسعى من خلال هذه المدونة المتواضعة إلى مشاركة خبرتى ومناقشة آرائي وأفكاري.

وفقنى الله وإياك إلى ما يحبه ويرضاه ،،

تابعنى على

تصميم الصفحات | جـ3

صورة المقال - تصميم الصفحات | جـ3

الحمد لله الذي علَّم بالقلم، علَّم الإنسان ما لم يعلم، والصلاة والسلام على خير معلِّم الناس الخير سيدنا محمد - صلَّى الله عليه وسلم … أما بعد ،،

لمواصلة التعلم والاطلاع على مقالات السلسلة السابقة، يمكنك الرجوع إلى المقال السابق بعنوان "تهيئة التطبيق: اللغة العربية، والخطوط، والألوان"، والذي يعد خطوة مهمة لإكمال الصورة وتطبيق المفاهيم بطريقة متكاملة.

في هذا المقال الجديد من السلسلة الكاملة لتعلم بناء التطبيقات، سنقوم بإنشاء الصفحات الأساسية للتطبيق، والتي تشمل:

  1. صفحة المنتجات: الصفحة الرئيسية للتطبيق، إذ تعرض المنتجات التي تم إضافتها سابقاً.
  2. صفحة إضافة منتج: الصفحة التي تسمح بإضافة منتجات جديدة إلى التطبيق.

صفحة المنتجات

لإضافة صفحات جديدة في التطبيق، قم بإنشاء مجلد باسم pages في المشروع، ثم أضف ملفًا جديدًا باسم index.vue داخله.

ابدأ بكتابة الكود التالي:

<template>
  <div>
    <h2>المنتجات</h2>
  </div>
</template>

بعد ذلك، قم بتحديث القسم الخاص بالقالب template في ملف app.vue ليصبح بالشكل التالي:

<template>
  <v-layout>
    <v-app-bar :elevation="2" color="primary">
      ...
    </v-app-bar>
    <v-main class="ma-4">
      <NuxtPage />
    </v-main>
  </v-layout>
</template>

لاحظ استخدام v-main حيث تمثل المساحة المخصصة لمحتوى الصفحة الرئيسي في Vuetify.

كما استخدمنا المكوّن NuxtPage من Nuxt، والذي يعمل على عرض الصفحة الحالية.

صفحة إضافة منتج

لإضافة صفحة خاصة بإدخال منتجات جديدة، قم بإنشاء ملف add-product.vue داخل مجلد pages وأضف الكود التالي:

<template>
  <div>
    <h2>إضافة منتج</h2>
  </div>
</template>

لعرض هذه الصفحة الجديدة، يمكن فتحها عبر المتصفح بإضافة اسم الصفحة إلى رابط الموقع بالشكل localhost:3000/add-product

إضافة روابط للتنقل بين الصفحات

لتسهيل التنقل بين الصفحات، يُفضل إضافة روابط للترويسة (header).

قبل البدء بذلك، نقوم أولاً بفصل كود الترويسة في مكوّن مستقل لجعل بنية التطبيق أكثر تنظيماً.

  1. أنشئ مجلدًا جديدًا باسم components داخل المشروع.
  2. أضف ملفًا جديدًا داخله باسم header.vue وانقل كود الترويسة الموجود حاليًا في app.vue إلى هذا الملف ليصبح كما يلي:
<template>
  <div>
    <v-app-bar :elevation="2" color="primary">
      <v-app-bar-title>تطبيق المنتجات</v-app-bar-title>
      <template v-slot:append>
        <v-btn icon="mdi-dots-vertical"></v-btn>
      </template>
    </v-app-bar>
  </div>
</template>

في ملف app.vue قم بتحديث الكود ليظهر بهذا الشكل:

<template>
  <v-layout>
    <Header />
    <v-main class="bg-grey-lighten-3" style="min-height: 100vh">
      <NuxtPage />
    </v-main>
  </v-layout>
</template>

تم إضافة وسم <Header /> لاستدعاء مكوّن الترويسة من مجلد components وبذلك نحصل على هيكل تنظيمي أكثر ترتيباً وسهولة في إدارة الكود.

إضافة الروابط

لإضافة الروابط ضمن الترويسة للتنقل بين صفحات التطبيق، قم بتحديث ملف header.vue ليحتوي على الكود التالي:

<template>
  <div>
    <v-app-bar :elevation="2" color="primary">
      <v-btn
        v-for="link in links"
        :key="link.title"
        :text="link.title"
        :to="link.route"
        size="x-large"
      />
      <template v-slot:append>
        <v-btn icon="mdi-dots-vertical"></v-btn>
      </template>
    </v-app-bar>
  </div>
</template>

<script lang="ts" setup>
const links = [
  { title: 'المنتجات', route: '/' },
  { title: 'اضافة منتج', route: '/add-product' },
];
</script>

في هذا الكود، تم إنشاء مصفوفة باسم links ضمن وسم <script> تحتوي على عنوان كل رابط title والمسار الخاص به route

بعد ذلك، استخدمنا مكوّن v-btn من Vuetify لعرض الأزرار التي تمثل الروابط داخل مكوّن v-app-bar.

كل زرّ يظهر عنوان الصفحة ويقود إلى المسار المحدد عند الضغط عليه.

بإمكانك الآن تجربة التنقل بين الصفحات (المنتجات / إضافة منتج) عبر الضغط على الروابط في الترويسة أعلى الصفحة.

تصميم صفحة المنتجات

لعرض تصميم المنتجات ضمن الصفحة قم بتحديث ملف index.vue الموجود في مجلد pages ليصبح بالشكل التالي

<template>
  <div>
    <v-container>
      <h3 class="text-h3 cairo">المنتجات</h3>
      <v-row class="mt-4">
        <v-col
          v-for="product in products"
          :key="product.id"
          cols="12"
          md="6"
          lg="3"
        >
          <v-card>
            <v-img :src="product.image" height="280" cover />
            <v-card-title>{{ product.name }}</v-card-title>
            <v-card-subtitle>{{ `${product.price} جنيه` }}</v-card-subtitle>
            <v-card-text>{{ product.description }}</v-card-text>
          </v-card>
        </v-col>
      </v-row>
    </v-container>
  </div>
</template>

<script lang="ts" setup>
const products = ref([
  {
    id: 1,
    name: 'موبايل سامسونج جالكسي',
    price: 8000,
    image: '/products/samsung-galaxy.jpg',
    description:
      'موبايل سامسونج جالكسي ايه 55 الجيل الخامس 5G، ثنائي شرائح الاتصال، ذاكرة رام 8 جيجا، تخزين 256 ازرق ثلجي',
  },
  {
    id: 2,
    name: 'موبايل ايفون 12 برو ماكس',
    price: 15000,
    image: '/products/12pro-max.jpg',
    description:
      'موبايل ايفون 12 برو ماكس ذاكرة 256 جيجا، شريحة واحدة، ازرق - ضمان لمدة عام اصدار محلي',
  },
  {
    id: 3,
    name: 'موبايل هواوي P40 برو',
    price: 10000,
    image: '/products/Huawei-P40-Pro.jpg',
    description:
      'موبايل هواوي P40 برو ذاكرة 256 جيجا، شريحة واحدة، اسود - ضمان لمدة عام اصدار محلي',
  },
  {
    id: 4,
    name: 'موبايل ريلمي 7',
    price: 5000,
    image: '/products/realme-7.jpg',
    description:
      'موبايل ريلمي 7 ذاكرة 128 جيجا، شريحة واحدة، ازرق - ضمان لمدة عام اصدار محلي',
  },
]);
</script>

في هذا الكود تم تصميم صفحة تعرض قائمة من المنتجات، يحتوي القسم الأول قالب <template> على الواجهة الرسومية لعرض المنتجات.

بدايةً، يتم إنشاء حاوية رئيسية باستخدام <v-container> والتي تضمن تنظيم المحتوى بشكل مناسب ضمن مساحة العرض.

في هذه الحاوية، يظهر عنوان الصفحة "المنتجات" باستخدام عنصر <h3> حيث يتم تطبيق خط Cairo على النصوص داخل الصفحة.

داخل <v-row> يتم وضع المنتجات بشكل صف يحتوي على عدة أعمدة، مما يسمح بتوزيع العناصر بشكل مرن حسب حجم الشاشة، كل عمود يمثل منتجًا واحدًا ويُنشأ باستخدام <v-col>.

يتم ضبط إعدادات العرض بحيث يظهر المنتج بعرض كامل على الشاشات الصغيرة، ويحتل نصف العرض على الشاشات المتوسطة، وربع العرض على الشاشات الكبيرة.

داخل كل عمود، تم استخدام <v-card> لإنشاء بطاقة مخصصة تحتوي على تفاصيل كل منتج.

تتكون البطاقة من عدة عناصر، حيث العنصر <v-img/> يعرض صورة المنتج بارتفاع 280 بكسل مع خاصية cover لضبط الصورة بحيث تغطي المساحة المحددة بالكامل.

يلي ذلك <v-card-title> والذي يعرض اسم المنتج كعنوان للبطاقة، في حين أن <v-card-subtitle> يظهر سعر المنتج بالجنيه.

أما <v-card-text> يوفر مساحة لوصف المنتج بتفاصيل مختصرة داخل البطاقة.

في القسم الخاص بالسكربت <script> يتم تعريف البيانات الخاصة بالمنتجات حيث يتم تخزين قائمة المنتجات ضمن مصفوفة products بحيث يحتوي كل عنصر على مجموعة من الخصائص التي تشمل معرف فريد id واسم المنتج name وسعر price ومسار الصورة image ووصف مختصر للمنتج description.

هذا الكود يتيح إنشاء واجهة منظمة ومرنة تعرض المنتجات بشكل بطاقات منظمة، كل بطاقة تعرض صورة المنتج، اسمه، سعره، ووصفه، مما يسهم في تصميم واجهة جذابة وسهلة الاستخدام.

بالنسبة للصور، تم نسخ ملفات الصور ووضعها داخل المشروع في مجلد باسم products داخل مجلد public.

تصميم صفحة اضافة منتج

لتطبيق استايل الصفحة، قم بتعديل الملف add-product.vue داخل مجلد pages ليصبح بالشكل التالي

<template>
  <div>
    <v-card class="mx-auto px-6 pb-4 pt-2 mt-12" max-width="580">
      <v-card-title class="mb-4 text-h4 cairo">إضافة منتج</v-card-title>

      <v-text-field class="mb-2" label="اسم المنتج" variant="outlined" />

      <v-text-field class="mb-2" label="السعر" variant="outlined" />

      <v-textarea label="الوصف" variant="outlined"></v-textarea>

      <v-btn color="primary" size="large" variant="flat" block>
        اضافة جديد
      </v-btn>
    </v-card>
  </div>
</template>

في هذا الكود، تم تصميم واجهة لإضافة منتج جديد حيث تتألف الواجهة من بطاقة <v-card> تحتوي على حقول إدخال لتجميع بيانات المنتج الأساسية. 

عنصر <v-card> يمثل البطاقة التي تتمركز في منتصف الشاشة وتحدد بعرض أقصى، مما يضمن أن تكون الواجهة متناسقة ومنظمة. 

داخل البطاقة، يبدأ الهيكل بإضافة عنوان رئيسي <v-card-title> الذي يعرض النص "إضافة منتج" ويستخدم خط Cairo لجعل العنوان بارزًا ومتناسقًا مع تصميم الواجهة.

تتبع العنوان ثلاثة حقول إدخال أساسية مصممة لجمع تفاصيل المنتج. 

  • الحقل <v-text-field> مخصص لإدخال اسم المنتج ويعرض تسمية "اسم المنتج" مما يوضح للمستخدم أن هذا الحقل خاص بتحديد الاسم. 
  • الحقل <v-text-field> مُعدّ لإدخال السعر ويعرض تسمية "السعر" ليكون واضحًا أن المستخدم مطالب بإدخال قيمة السعر هنا. 
  • الحقل <v-textarea> وهو حقل متعدد الأسطر مخصص لإدخال وصف المنتج، حيث يتيح للمستخدم كتابة تفاصيل وصفية بشكل أكثر شمولاً، ويظهر بجواره تسمية "الوصف".

في أسفل البطاقة يتم تضمين زر إضافة باستخدام <v-btn> والذي يمتد بعرض البطاقة بالكامل ويظهر بلون مميز يبرز أهميته كزر للتأكيد على عملية إضافة المنتج. 

هذا التصميم يتيح واجهة مبسطة وسهلة الاستخدام، حيث يتمكن المستخدم من إدخال بيانات المنتج الأساسية والضغط على زر الإضافة لإتمام العملية بشكل سريع وفعال.

ملاحظات على الاستايل

في قسم <style> داخل ملف app.vue تم إضافة التنسيقات التالية:

.cairo {
  font-family: 'Cairo', sans-serif;
}

.v-btn {
  letter-spacing: 0;
}

تم تخصيص المعرف cairo لسهولة تطبيق خط Cairo بسهولة على النصوص في الصفحة.

أما بالنسبة للمعرف v-btn فقد تم ضبط خاصية letter-spacing على القيمة 0، وذلك لحل مشكلة المسافة الافتراضية بين الحروف التي يضيفها Vuetify للغة الإنجليزية، والتي تتسبب بفصل الحروف عند الكتابة بالعربية. 

هذا التعديل يضمن عرض النصوص العربية بشكل سليم ومتناسق في الأزرار.

بإمكانك الوصول إلى الكود الكامل للتطبيق على GitHub عبر رابط المشروع هنا.

وفقنى الله وإياك إلى ما يحبه ويرضاه ،،