Add Uzbekistan translation for test project
This commit is contained in:
293
module-a/module-a-uz.md
Normal file
293
module-a/module-a-uz.md
Normal file
@@ -0,0 +1,293 @@
|
||||
# ⚡ Sinov loyihasi: Modul A — Tezlik testi (Speed Test)
|
||||
|
||||
## 1. Loyiha haqida qisqacha ma'lumot
|
||||
|
||||
Ushbu baholash veb-texnologiyalar bo'yicha amaliy ko'nikmalarni tez va aniq baholash uchun mo'ljallangan **Tezlik testi** (Speed Test) hisoblanadi. Ishtirokchilar to'rtta toifa — **A (Dizayn)**, **B (Layout)**, **C (Frontend)** va **D (Backend)** bo'yicha jami 20 ta mustaqil topshiriqni belgilangan vaqt ichida bajarishlari kerak. Har bir topshiriq mustaqil bo'lib, ularni istalgan tartibda bajarish mumkin.
|
||||
|
||||
---
|
||||
|
||||
## 2. Texnologiyalar to'plami (Tech Stack) va cheklovlar
|
||||
|
||||
| Toifa | Ruxsat berilgan texnologiyalar | Cheklovlar |
|
||||
| :--- | :--- | :--- |
|
||||
| **A. Dizayn** | GIMP | Boshqa grafik tahrirlovchilardan (masalan, Photoshop) foydalanish taqiqlanadi |
|
||||
| **B. Layout** | HTML, CSS | JavaScript-dan foydalanish taqiqlanadi |
|
||||
| **C. Frontend** | JavaScript (Vanilla) | Tashqi kutubxonalar yoki freymvorklardan foydalanish taqiqlanadi |
|
||||
| **D. Backend** | PHP, MySQL | Ma'lumotlar bazasiga ulanish uchun faqat PDO ishlatilishi kerak |
|
||||
|
||||
* Barcha natijalar Chrome brauzerining desktop versiyasida tekshiriladi.
|
||||
* Har bir topshiriq natijasini `/module_a/` papkasi ostidagi topshiriq ID-si bilan nomlangan quyi papkaga saqlang (masalan, `/module_a/a1/`, `/module_a/b1/`).
|
||||
* Dizayn topshiriqlari uchun GIMP manba fayli (`.xcf`) topshiriladigan papkada bo'lishi shart.
|
||||
|
||||
---
|
||||
|
||||
## 3. Topshiriqlar
|
||||
|
||||
### 🎨 A. Dizayn — GIMP mahorati
|
||||
|
||||
> **Taqdim etilgan fayllar**: A1 (`source.png`), A2 (`base.jpg`) va A3 (`photo.jpg`, `mask.png`) uchun fayllar har bir topshiriqning ishchi katalogiga joylashtirilgan. A4 va A5 uchun fayllar taqdim etilmagan; ishtirokchilar barcha elementlarni noldan yaratishlari kerak.
|
||||
|
||||
#### **A1. Qatlamlarni birlashtirish va matn joylashtirish** `Oson`
|
||||
|
||||
GIMP-da qatlamli tuzilmadan foydalangan holda rasm yarating.
|
||||
|
||||
* Kanvas o'lchami: **800×400px**, Ruxsat: **72dpi**
|
||||
* **1-qatlam**: Fonni `#2C3E50` rangli foni bilan to'ldiring.
|
||||
* **2-qatlam**: Taqdim etilgan rasmni (`source.png`) oching, uni kanvasning **markaziga** joylashtiring va shaffofligini (opacity) **70%** ga o'rnating.
|
||||
* **3-qatlam**: **"Hello, GIMP"** matnini oq rangda (`#FFFFFF`), 36pt o'lchamda qo'shing va uni kanvasning yuqori chap burchagiga **(x: 20px, y: 20px)** joylashtiring.
|
||||
* Loyihani avval `.xcf` formatida saqlang. Keyin barcha qatlamlarni birlashtiring (Flatten Image) va natijani `result.png` sifatida eksport qiling.
|
||||
|
||||
#### **A2. Tanlash va qatlamlarni birlashtirish** `Oson`
|
||||
|
||||
GIMP-ning tanlash vositalari va qatlamlaridan foydalanib, rasmga shakl effektlarini qo'llang.
|
||||
|
||||
* Taqdim etilgan rasmni (`base.jpg`) fon qatlami sifatida oching.
|
||||
* **1-effekt**: Yangi qatlam qo'shing. "Rectangle Select" (To'rtburchak tanlash) vositasi yordamida yuqori chap burchakdagi **(0, 0) dan (200, 200)** gacha bo'lgan maydonni tanlang, uni `#E74C3C` rang bilan to'ldiring va ushbu qatlamning shaffofligini **60%** ga o'rnating.
|
||||
* **2-effekt**: Yana bitta yangi qatlam qo'shing. Rasmning **markazida** diametri **150px** bo'lgan elliptik tanlov yarating. `Selection → Border` menyusiga kiring, chegara kengligini **3px** qilib belgilang va hosil bo'lgan tanlovni `#FFFFFF` rangi bilan to'ldiring.
|
||||
* Loyihani avval `.xcf` formatida saqlang. Keyin barcha qatlamlarni birlashtiring (Flatten Image) va natijani `result.jpg` sifatida eksport qiling.
|
||||
|
||||
#### **A3. Rangni to'g'rilash va qatlam maskasi (Layer Mask)** `O'rtacha`
|
||||
|
||||
Taqdim etilgan rasmga (`photo.jpg`) rangni to'g'rilash va qatlam maskasini qo'llang.
|
||||
|
||||
* **Rangni to'g'rilash**: "Hue-Saturation" vositasidan foydalanib, to'yinganlikni (Saturation) **+40** ga oshiring.
|
||||
* **Egri chiziqlar (Curves)**: "Curves" vositasidan foydalanib, kontrastni oshirish uchun yorug'lik qiymatini (highlights) **+20 yoki undan ko'proqqa** oshiring va soya qiymatini (shadows) **-20 yoki undan kamroqqa** tushiring.
|
||||
* **Qatlam maskasi**: Rasm qatlamiga qatlam maskasini qo'shing. Taqdim etilgan maska tasvirini (`mask.png`) qatlam maskasiga joylashtiring, shunda asosiy obyektdan tashqaridagi fon olib tashlanadi.
|
||||
* Loyihani avval `.xcf` formatida saqlang. Keyin natijani `result.png` sifatida eksport qiling va shaffof fon saqlanib qolganiga ishonch hosil qiling.
|
||||
|
||||
#### **A4. Matn effekti va porlash (Glow)** `O'rtacha`
|
||||
|
||||
GIMP-da matnga porlash effektini qo'llang.
|
||||
|
||||
* Kanvas o'lchami: **600×200px**, Fon rangi: `#1A1A2E`
|
||||
* **"SPEED TEST"** matnini oq rangda (`#FFFFFF`), qalin (Bold), 60pt o'lchamda kanvas markaziga qo'shing.
|
||||
* Matn qatlamini nusxalang va nusxasini asl matn qatlamining **ostiga** joylashtiring.
|
||||
* Nusxalangan qatlamni rasterlang (Layer → Rasterize). Qatlamlar panelida ushbu qatlamning rejimini (Mode) **`Color`** ga o'rnating. Keyin asosiy rangni (foreground) `#4A90D9` ga o'rnating va `Edit → Fill with Foreground Color` orqali ko'k rangni qo'llang.
|
||||
* Tashqi porlash effektini yakunlash uchun nusxalangan qatlamga **8px** radiusli **Gaussian Blur** filtrini qo'llang.
|
||||
* Loyihani avval `.xcf` formatida saqlang, so'ngra natijani `result.png` sifatida eksport qiling.
|
||||
|
||||
#### **A5. Matnni buzish (Warp) va filtr effektlari** `Qiyin`
|
||||
|
||||
Matnni rasterlang va vizual buzilish effektlarini yaratish uchun GIMP-ning "Distorts" filtrlarini qo'llang.
|
||||
|
||||
* Kanvas o'lchami: **800×300px**, Fon rangi: `#0D0D0D`
|
||||
* **"DISTORTION"** matnini oq rangda (`#FFFFFF`), qalin (Bold), 72pt o'lchamda kanvas markaziga qo'shing.
|
||||
* Matn qatlamini rasterlang (Layer → Rasterize).
|
||||
* Rasterlangan matn qatlamiga quyidagi ikkita "Distorts" filtrini tartib bilan qo'llang:
|
||||
* **Ripple**: Amplituda **8**, To'lqin uzunligi (Wavelength) **40**, Yo'nalish: Horizontal
|
||||
* **Whirl and Pinch**: Whirl burchagi **20** daraja, Pinch **0**, Radius **1.0**
|
||||
* Buzilgan matn qatlamini nusxalang. Nusxaga **3px** radiusli **Gaussian Blur** filtrini qo'llang va "ghosting" (arvohsimon) effektini yaratish uchun uni asl qatlamning **ostiga** joylashtiring.
|
||||
* Loyihani avval `.xcf` formatida saqlang, so'ngra natijani `result.png` sifatida eksport qiling.
|
||||
|
||||
---
|
||||
|
||||
### 📐 B. Layout — Faqat HTML / CSS
|
||||
|
||||
#### **B1. Flexbox Card Layout** `Oson`
|
||||
|
||||
Faqat HTML va CSS yordamida kartalar ro'yxatini yarating.
|
||||
|
||||
* Kartalarni har bir qatorda **4 tadan** joylashtirish uchun **Flexbox** dan foydalaning. (`flex-wrap: wrap` ishlating)
|
||||
* Har bir karta quyidagilarni o'z ichiga olishi kerak: rasm maydoni (`<div>`, balandligi **160px**, fon rangi bilan), sarlavha (`<h3>`), asosiy matn (`<p>`) va tugma (`<button>`).
|
||||
* Kartalar orasidagi masofani (gap) **24px** qilib belgilang.
|
||||
* **8 ta** namunaviy (dummy) karta yarating. Har bir kartaning rasm maydoni har xil fon rangiga ega bo'lishi kerak.
|
||||
|
||||
#### **B2. Sticky Header va CSS interaksiyasi** `Oson`
|
||||
|
||||
Faqat HTML va CSS yordamida CSS interaksiyalariga ega sarlavha (header) yarating.
|
||||
|
||||
* Sarlavhani joylashtirish uchun **Flexbox** dan foydalaning: chapda logotip matni, markazda 4 ta menyu havolasi va o'ngda 2 ta tugma.
|
||||
* Menyu havolasi ustiga kursor olib borilganda (hover), `transition` effekti bilan **2px qalinlikdagi chiziq** paydo bo'ladigan interaksiyani amalga oshiring. (`border-bottom` yoki `::after` psevdo-elementidan foydalaning)
|
||||
* Sarlavhani skroll paytida yuqorida qotib turishi uchun `position: sticky; top: 0;` dan foydalaning.
|
||||
* Skroll qilish imkoniyati bo'lishi uchun sarlavha ostiga kamida **3000px** balandlikdagi namunaviy kontent joylashtiring.
|
||||
|
||||
#### **B3. CSS Grid Ikki ustunli maket** `O'rtacha`
|
||||
|
||||
Faqat HTML va CSS yordamida CSS Grid orqali ikki ustunli sahifa maketini yarating.
|
||||
|
||||
* Chap tomonda mahkamlangan sidebar (**250px**) va o'ng tomonda asosiy kontent maydoni (`1fr`) yaratish uchun **CSS Grid** dan foydalaning.
|
||||
* Chap sidebarga vertikal navigatsiya menyusini (5 ta element) joylashtiring. Birinchi elementni faol holatda ekanligini ko'rsatish uchun fon rangi va matn rangini o'zgartiring.
|
||||
* O'ngdagi asosiy maydonda tartib bilan sarlavha, matn va **3 ustunli karta setkasi** (CSS Grid yordamida, 6 ta karta) joylashtiring.
|
||||
* Umumiy o'rovchi elementga (wrapper) `height: 100vh` va `overflow: hidden` qo'llang. Sidebar va asosiy maydonning har biri alohida skroll bo'lishi uchun ikkalasiga ham `height: 100vh` va `overflow-y: auto` xususiyatlarini bering.
|
||||
|
||||
#### **B4. CSS Animatsiyalar va Transitionlar** `O'rtacha`
|
||||
|
||||
Faqat HTML va CSS yordamida bitta sahifada turli xil CSS animatsiyalari va transition effektlarini amalga oshiring.
|
||||
|
||||
* **Karta hover effekti**: Flexbox yordamida qatorga 4 ta karta joylashtiring. Kursor ustiga kelganda, har bir karta **8px** yuqoriga ko'tarilishi va kuchliroq soyaga ega bo'lishi kerak. (`transform: translateY(-8px)`, `box-shadow` va `transition` ishlating)
|
||||
* **Yuklanish indikatori (Loading spinner)**: `@keyframes` yordamida aylana shaklidagi spinner yarating. Spinner diametri **48px**, chegarasi (border) **4px** bo'lsin. Faqat yuqori chegara (`border-top`) `#3498DB` rangda bo'lishi kerak, qolganlari esa `#e0e0e0`. Spinner cheksiz aylanadi.
|
||||
* **Matnning paydo bo'lishi (Fade-in)**: Sahifa yuklanganda sarlavha (`<h1>`) `@keyframes` yordamida `translateY(20px)` dan `translateY(0)` holatiga o'tishi va `opacity: 0` dan `opacity: 1` ga o'zgarishi kerak. (`animation-duration: 0.8s`, `animation-fill-mode: both`)
|
||||
|
||||
#### **B5. CSS Grid va kengaytirilgan selektorlar** `Qiyin`
|
||||
|
||||
Faqat HTML va CSS yordamida ikki ustunli kontent maketini va faqat CSS-da ishlaydigan tab (sahifa) interaksiyasini yarating.
|
||||
|
||||
* **CSS Grid** yordamida ikki ustunli maket yarating: chap ustun (65%) va o'ng ustun (35%).
|
||||
* **Chap maydon**: Asosiy rasm maydonini (`<div>`, balandligi **300px**, fon rangi bilan) va uning ostida gorizontal rasmchalar (thumbnail) ro'yxatini joylashtiring (Flexbox, `overflow-x: auto`). 5 ta rasmcha bo'lsin, har biri **80×80px** o'lchamdagi va turli fon rangli `<div>` bo'lsin.
|
||||
* **O'ng maydon — yuqori**: Sarlavha, kichik sarlavha va matn joylashtiring.
|
||||
* **O'ng maydon — quyi**: 3 ta tab (Umumiy ko'rinish / Tafsilotlar / Sharhlar) va ularga tegishli kontent maydonlarini yarating.
|
||||
* Faqat tanlangan tab kontentini ko'rsatish uchun **JavaScript-siz** `<input type="radio" name="tab">` va CSS `:checked` selektoridan foydalaning.
|
||||
* `<input type="radio">` elementlarini `display: none` bilan yashiring va mos keladigan `<label>` elementlarini tab tugmalari kabi dizayn qiling.
|
||||
* O'ng maydonning eng pastida yonma-yon "Asosiy" va "Yordamchi" tugmalarni joylashtiring. Asosiy tugma ustiga kursor olib kelganda uning fon rangi silliq o'zgarishi uchun `@keyframes` animatsiyasini qo'llang.
|
||||
|
||||
---
|
||||
|
||||
### ⚡ C. Frontend — JavaScript (Vanilla)
|
||||
|
||||
#### **C1. localStorage asosidagi eslatmalar ilovasi** `Oson`
|
||||
|
||||
Vanilla JavaScript va `localStorage` yordamida oddiy eslatma (memo) ilovasini yarating.
|
||||
|
||||
* Sahifada matn kiritish maydoni (`<textarea>`) va **"Saqlash"** tugmasi bo'lishi kerak.
|
||||
* "Saqlash" tugmasi bosilganda, eslatma `localStorage`-dagi `memos` kaliti ostida JSON massiviga qo'shiladi. Bo'sh matnni saqlash mumkin emas.
|
||||
* Saqlangan eslatmalar ro'yxatini kiritish maydoni ostida ko'rsating. Har bir elementda matn va **"O'chirish"** tugmasi bo'lishi kerak.
|
||||
* "O'chirish" tugmasi bosilganda, element `localStorage`-dan o'chirilishi va ro'yxat darhol yangilanishi kerak.
|
||||
* Sahifa qayta yuklanganda ham eslatmalar ro'yxati saqlanib qolishi kerak.
|
||||
|
||||
#### **C2. DOM manipulyatsiyasi va hodisalarni boshqarish** `Oson`
|
||||
|
||||
Vanilla JavaScript yordamida elementlarni boshqarish imkoniyatiga ega dinamik ro'yxat yarating.
|
||||
|
||||
* Sahifada matn kiritish maydoni (`<input type="text">`) va **"Qo'shish"** tugmasi bo'lishi kerak.
|
||||
* "Qo'shish" tugmasi bosilganda yoki Enter tugmasi bosilganda kiritilgan qiymat yangi ro'yxat elementi sifatida qo'shiladi. Bo'sh qiymat qo'shilmasligi kerak. Qo'shilgandan keyin kiritish maydoni tozalanadi.
|
||||
* Har bir elementda **"Bajarildi"** va **"O'chirish"** tugmalari bo'lishi kerak.
|
||||
* "Bajarildi" tugmasi bosilganda matn ustidan chiziladi (`text-decoration: line-through`). Qayta bosilganda asl holatiga qaytadi.
|
||||
* "O'chirish" tugmasi bosilganda element darhol o'chiriladi.
|
||||
* Ro'yxatning yuqorisida real vaqt rejimida **jami elementlar soni** va **bajarilganlar sonini** ko'rsating.
|
||||
|
||||
#### **C3. Dinamik JSON rendering va filtrlash** `O'rtacha`
|
||||
|
||||
Vanilla JavaScript va Fetch API yordamida mahalliy JSON faylini yuklaydigan va uning mazmunini dinamik ravishda ko'rsatadigan sahifa yarating.
|
||||
|
||||
* `/module_a/c3/posts.json` manzilidagi `posts.json` faylini Fetch API orqali yuklang. Fayl `id`, `title`, `body` va `category` kalitlariga ega bo'lgan obyektlar massivini o'z ichiga oladi (jami 20 ta element).
|
||||
* Ma'lumot yuklanayotgan vaqtda **yuklanish indikatorini** (CSS animatsiyasi) ko'rsating va yuklash tugagach uni olib tashlang.
|
||||
* Barcha elementlarni kartalar ko'rinishida ko'rsating. Har bir kartada `id`, `title`, `body` va `category` bo'lishi kerak.
|
||||
* Qidiruv maydonini yarating, u `title` bo'yicha kartalarni real vaqt rejimida filtrlaydi (katta-kichik harfni farqlamaydi; har bir tugma bosilganda yangilanadi).
|
||||
* Agar Fetch so'rovi muvaffaqiyatsiz tugasa, ekranda **"Failed to load data."** xatosini ko'rsating.
|
||||
|
||||
> **Taqdim etilgan fayl**: `posts.json` (ishtirokchining `/module_a/c3/` ishchi katalogiga joylashtirilgan)
|
||||
|
||||
#### **C4. Formani tekshirish (Validation)** `O'rtacha`
|
||||
|
||||
Vanilla JavaScript yordamida real vaqt rejimida formani tekshirishni amalga oshiring.
|
||||
|
||||
* Quyidagi maydonlarga ega ro'yxatdan o'tish formasini yarating: **Ism**, **Email**, **Parol**, **Parolni tasdiqlash**.
|
||||
* Har bir maydon uchun tekshirish qoidalari:
|
||||
* **Ism**: Majburiy, kamida 2 ta belgi.
|
||||
* **Email**: Majburiy, `@` va `.` belgilarini o'z ichiga olishi kerak.
|
||||
* **Parol**: Majburiy, kamida 8 ta belgi, harflar va raqamlarni o'z ichiga olishi kerak.
|
||||
* **Parolni tasdiqlash**: Majburiy, Parol maydoni bilan to'liq mos kelishi kerak.
|
||||
* Fokus maydondan chiqqanda (`blur` hodisasi), agar qoida buzilgan bo'lsa, o'sha maydon ostida xato xabarini ko'rsating. Shart bajarilishi bilan xato xabarini darhol olib tashlang.
|
||||
* **"Yuborish"** tugmasi faqat barcha maydonlar to'g'ri to'ldirilganda faollashishi kerak. Tugma bosilganda `alert("Registration complete.")` xabari chiqishi kerak.
|
||||
|
||||
#### **C5. IntersectionObserver va kechiktirilgan rendering** `Qiyin`
|
||||
|
||||
`IntersectionObserver` yordamida cheksiz skroll va kechiktirilgan renderingni amalga oshiring.
|
||||
|
||||
* JavaScript-da 50 ta namunaviy elementdan iborat massiv yarating. Har bir element `id`, `title` va `color` ga ega bo'lishi kerak (`color` - ixtiyoriy `#RRGGBB` formatidagi rang).
|
||||
* Dastlabki yuklanishda **10 ta** elementni ko'rsating. Har bir element **200px** balandlikdagi rangli `<div>` va uning `title` matnidan iborat bo'lsin. Birinchi 10 ta element o'zining rangini darhol fon sifatida ko'rsatishi kerak.
|
||||
* Ro'yxatning oxiriga **kuzatuvchi element** (`<div id="sentinel">`) joylashtiring. Ushbu element ko'rinish maydoniga (viewport) kirganda, keyingi 10 ta element avtomatik ravishda qo'shilishi kerak.
|
||||
* Yangi elementlar qo'shilayotganda kuzatuvchi elementdan oldin yuklanish indikatorini ko'rsating va rendering tugagach uni olib tashlang (`setTimeout` yordamida 600ms kechikishni simulyatsiya qiling).
|
||||
* Barcha **50 ta element** yuklab bo'lingandan so'ng, kuzatuvchini to'xtating (`observer.unobserve`) va **"All items loaded."** xabarini ko'rsating.
|
||||
* Yangi elementlar DOM-ga qo'shilganda ularning rangli `<div>`lari dastlab kulrang (`#cccccc`) bo'lishi kerak. Har bir `<div>`ni kuzatish uchun **alohida `IntersectionObserver` nusxasidan** foydalaning va element ekranda ko'rinishi bilan kulrangni elementning `data-color` atributidagi haqiqiy rangga almashtiring.
|
||||
|
||||
---
|
||||
|
||||
### 🛢️ D. Backend — PHP / MySQL
|
||||
|
||||
> **Taqdim etilgan fayllar**: D4 uchun `posts_dump.sql` va D5 uchun `data_dump.sql` har bir topshiriqning ishchi katalogiga joylashtirilgan.
|
||||
|
||||
#### **D1. PDO asosidagi CRUD API** `Oson`
|
||||
|
||||
PHP va MySQL (PDO) yordamida ma'lumotlarni boshqarish uchun REST API yarating.
|
||||
|
||||
* Quyidagi tuzilmada `items` jadvalini yarating. Jadvalni yaratish SQL kodini `table.sql` sifatida topshiring.
|
||||
* `id` (INT, PK, AUTO_INCREMENT), `title` (VARCHAR 100, NOT NULL), `content` (TEXT), `created_at` (TIMESTAMP DEFAULT CURRENT_TIMESTAMP)
|
||||
* Bitta `api.php` faylida HTTP metodlari (`$_SERVER['REQUEST_METHOD']`) bo'yicha ajratilgan 4 ta endpointni amalga oshiring:
|
||||
* `GET /module_a/d1/api.php` → Barcha elementlarni JSON massivi sifatida qaytaradi.
|
||||
* `POST /module_a/d1/api.php` → Yangi element qo'shadi. Body (JSON): `{"title": "...", "content": "..."}`. So'rov tanasini `php://input` orqali o'qing va `json_decode()` bilan tahlil qiling. Muvaffaqiyatli bo'lsa, qo'shilgan qatorni JSON sifatida qaytaring.
|
||||
* `PUT /module_a/d1/api.php?id={id}` → `title` va `content`ni yangilaydi. Body (JSON): `{"title": "...", "content": "..."}`. Muvaffaqiyatli bo'lsa, yangilangan qatorni JSON sifatida qaytaring.
|
||||
* `DELETE /module_a/d1/api.php?id={id}` → Elementni o'chiradi. Muvaffaqiyatli bo'lsa, `{"message": "deleted"}` qaytaring.
|
||||
* Mavjud bo'lmagan `id` uchun PUT/DELETE so'rovlari yuborilsa, **404** HTTP statusi va `{"error": "Not found"}` qaytaring.
|
||||
* Barcha javoblarda `Content-Type: application/json` sarlavhasi (header) bo'lishi shart.
|
||||
|
||||
#### **D2. Fayl yuklashni boshqarish** `Oson`
|
||||
|
||||
PHP yordamida rasm fayllarini yuklash funksiyasini amalga oshiring.
|
||||
|
||||
* `upload.php` faylida fayl yuklash HTML formasini (GET) va yuklashni qayta ishlash mantiqini (POST) amalga oshiring. Formaning `enctype` atributini `multipart/form-data` qilib belgilang.
|
||||
* Yuklash shartlari: faqat **jpg, jpeg, png, gif** kengaytmalariga ruxsat beriladi; fayl o'lchami **2MB yoki undan kam** bo'lishi kerak.
|
||||
* Tekshiruvdan o'tgan fayllarni `uploads/` papkasiga **`{time()}_{asl_fayl_nomi}`** formatida saqlang. Agar `uploads/` papkasi mavjud bo'lmasa, uni kod orqali yarating.
|
||||
* Muvaffaqiyatli yuklangandan so'ng, yuklangan rasmni `<img>` tegi orqali ko'rsating.
|
||||
* Tekshiruv xatolari uchun tegishli xabarlarni chiqaring:
|
||||
* Noto'g'ri kengaytma: **"File type not allowed."**
|
||||
* O'lcham oshib ketgan: **"File size exceeds 2MB."**
|
||||
|
||||
#### **D3. Sessiya asosidagi autentifikatsiya tizimi** `O'rtacha`
|
||||
|
||||
PHP sessiyalari va MySQL yordamida foydalanuvchilarni ro'yxatdan o'tkazish, tizimga kirish va chiqishni amalga oshiring.
|
||||
|
||||
* `users` jadvali: `id` (INT, PK, AUTO_INCREMENT), `email` (VARCHAR 100, UNIQUE), `password` (VARCHAR 255), `name` (VARCHAR 50), `created_at` (TIMESTAMP DEFAULT CURRENT_TIMESTAMP)
|
||||
* **`register.php`**: GET so'rovida ro'yxatdan o'tish formasini chiqaring. POST so'rovida email takrorlanmaganini tekshiring, parolni `password_hash()` bilan shifrlab saqlang va hech qanday xabarsiz darhol `login.php` ga yo'naltiring. Agar email band bo'lsa, forma ustida **"This email is already registered."** xatosini ko'rsating.
|
||||
* **`login.php`**: GET so'rovida kirish formasini chiqaring. POST so'rovida parolni `password_verify()` bilan tekshiring. Muvaffaqiyatli bo'lsa, sessiyada `user_id`, `name` va `email`ni saqlang va `mypage.php` ga yo'naltiring. Xato bo'lsa, **"Incorrect email or password."** xabarini ko'rsating.
|
||||
* **`logout.php`**: `session_destroy()` orqali sessiyani yakunlang va `login.php` ga yo'naltiring.
|
||||
* **`mypage.php`**: Agar sessiyada `user_id` bo'lmasa, `login.php` ga yo'naltiring. Tizimga kirgan bo'lsa, **"Welcome, {name}!"** xabari va chiqish (logout) havolasini ko'rsating.
|
||||
|
||||
#### **D4. Sahifalash (Pagination)** `O'rtacha`
|
||||
|
||||
PHP va MySQL (PDO) yordamida server tomonida sahifalashni amalga oshiring.
|
||||
|
||||
* `posts` jadvalini yarating va taqdim etilgan SQL dump (`posts_dump.sql`) faylini import qiling. Jadval tuzilishi: `id`, `title`, `content`, `created_at`.
|
||||
* `index.php` sahifasida **har bir sahifada 10 ta post** ko'rsating.
|
||||
* Joriy sahifa URL-dagi `?page={n}` so'rovi orqali aniqlanadi (standart: 1). SQL so'rovida faqat kerakli ma'lumotlarni olish uchun `LIMIT` va `OFFSET` dan foydalaning. Agar `page` 1 dan kichik yoki jami sahifalar sonidan ko'p bo'lsa, 1-sahifaga yo'naltiring.
|
||||
* Sahifaning pastki qismida sahifalash havolalarini ko'rsating. **Barcha sahifa raqamlarini ko'rsating**, joriy sahifani "active" uslubi bilan belgilang va "Oldingi/Keyingi" tugmalarini qo'shing. Birinchi sahifada "Oldingi", oxirgi sahifada esa "Keyingi" tugmalarini faolsizlantiring (disable).
|
||||
* Har bir post elementida sarlavha va yaratilgan sana ko'rsatilishi kerak. Sarlavha bosilganda `view.php?id={id}` sahifasiga o'tib, postning to'liq matni ko'rsatiladi.
|
||||
|
||||
#### **D5. Bir nechta jadvalli agregat so'rovlar** `Qiyin`
|
||||
|
||||
Bir nechta jadvallarni birlashtirish (JOIN) va agregat so'rovlar yordamida statistika API-sini yarating.
|
||||
|
||||
* Barcha 3 ta jadvalni yarating va `data_dump.sql` faylini import qiling. **Jadvallar `users` → `posts` → `comments` tartibida yaratilishi kerak** (tashqi kalit bog'liqliklari uchun).
|
||||
* `users` (`id`, `name`, `created_at`)
|
||||
* `posts` (`id`, `user_id`, `title`, `category`, `view_count`, `created_at`)
|
||||
* `comments` (`id`, `post_id`, `created_at`)
|
||||
* Bitta `stats.php` faylida `type` query stringiga qarab quyidagi 3 xil javobni qaytaring:
|
||||
* `GET /module_a/d5/stats.php?type=daily` → Oxirgi 7 kundagi har bir kun uchun yangi postlar sonini sana bo'yicha o'sish tartibida qaytaring. Format: `[{"date": "2026-04-06", "count": 5}, ...]`
|
||||
* `GET /module_a/d5/stats.php?type=category` → Har bir kategoriya bo'yicha jami postlar soni va o'rtacha ko'rishlar sonini, postlar soni kamayish tartibida qaytaring. Format: `[{"category": "tech", "post_count": 12, "avg_views": 340}, ...]`
|
||||
* `GET /module_a/d5/stats.php?type=top` → Izohlar soni bo'yicha eng yuqori 5 ta postni, izohlar soni kamayish tartibida qaytaring. Format: `[{"post_id": 3, "title": "...", "author": "Alice Johnson", "comment_count": 18}, ...]`
|
||||
* Barcha so'rovlarda PDO **Prepared Statements** ishlatilishi shart.
|
||||
* Noma'lum `type` qiymatlari uchun **400** HTTP statusi va `{"error": "Invalid type"}` qaytaring.
|
||||
|
||||
---
|
||||
|
||||
## 4. Topshirish bo'yicha ko'rsatmalar
|
||||
|
||||
Barcha natijalarni serverdagi `/module_a/` katalogiga yuklang. Har bir topshiriq o'zining ID-si bilan nomlangan quyi papkada bo'lishi kerak (masalan, `/module_a/a1/`, `/module_a/b1/`, `/module_a/c1/`, `/module_a/d1/`).
|
||||
|
||||
---
|
||||
|
||||
## 5. Baholash sxemasi — Jami 25 ball
|
||||
|
||||
| Toifa | Topshiriq | Ballar |
|
||||
| :--- | :--- | :---: |
|
||||
| **A. Dizayn** | A1. Layer Compositing and Text Placement | 0.5 |
|
||||
| | A2. Selection and Layer Compositing | 0.5 |
|
||||
| | A3. Color Correction and Layer Mask | 1.5 |
|
||||
| | A4. Text Effect and Glow | 1.5 |
|
||||
| | A5. Text Warp and Filter Effects | 2.0 |
|
||||
| **B. Layout** | B1. Flexbox Card Layout | 0.5 |
|
||||
| | B2. Sticky Header and CSS Interaction | 0.5 |
|
||||
| | B3. CSS Grid Two-Column Layout | 1.5 |
|
||||
| | B4. CSS Animations and Transitions | 1.5 |
|
||||
| | B5. CSS Grid and Advanced Selectors | 2.0 |
|
||||
| **C. Frontend** | C1. localStorage-based Memo App | 0.5 |
|
||||
| | C2. DOM Manipulation and Event Handling | 0.5 |
|
||||
| | C3. Dynamic JSON Rendering and Filtering | 1.5 |
|
||||
| | C4. Form Validation | 1.5 |
|
||||
| | C5. IntersectionObserver and Deferred Rendering | 2.0 |
|
||||
| **D. Backend** | D1. PDO-based CRUD API | 0.5 |
|
||||
| | D2. File Upload Handling | 0.5 |
|
||||
| | D3. Session-based Authentication System | 1.5 |
|
||||
| | D4. Pagination | 1.5 |
|
||||
| | D5. Multi-table Aggregate Queries | 3.0 |
|
||||
| **Jami** | | **25** |
|
||||
203
module-b/module-b-uz.md
Normal file
203
module-b/module-b-uz.md
Normal file
@@ -0,0 +1,203 @@
|
||||
# 🛍️ Sinov loyihasi: Modul B — ShopPress (Onlayn savdo markazi)
|
||||
|
||||
## 1. Loyiha haqida qisqacha ma'lumot
|
||||
|
||||
Jadal rivojlanayotgan elektron tijorat bozorida **ShopPress** startapi ma'murlarga mahsulotlar va buyurtmalarni bevosita boshqarish imkonini beruvchi o'zining savdo platformasini ishga tushirmoqda. Ma'murlar mahsulotlarni ro'yxatdan o'tkazishi va boshqarishi hamda buyurtmalarni qayta ishlashi mumkin, oddiy tashrif buyuruvchilar esa mahsulotlarni ko'rishlari va sotib olishlari mumkin. Ushbu loyihada ishtirokchilar ma'lumotlar bazasini loyihalashdan tortib asosiy funksiyalarni amalga oshirishgacha bo'lgan barcha ishlarga javobgardirlar. Bu MVP (minimal hayotiy mahsulot) bo'lgani uchun asosiy funksionallikni amalga oshirishga e'tibor qarating. **Dizayn baholash mezoni hisoblanmaydi.**
|
||||
|
||||
---
|
||||
|
||||
## 2. Texnologiyalar to'plami va cheklovlar
|
||||
|
||||
* **Texnologiyalar to'plami**: Dasturlash tili yoki freymvork bo'yicha cheklovlar yo'q. Laravel, Django, Ruby on Rails yoki Spring Boot kabi server-side rendering (SSR) qobiliyatiga ega har qanday freymvorkni erkin tanlashingiz mumkin.
|
||||
* **Ish stoli muhiti**: Responsiv (moslashuvchan) dizayn talab qilinmaydi. Ilova faqat Chrome brauzerining desktop versiyasida ishlashi kerak.
|
||||
* **Rasm yuklash**: Mahsulot rasmlari faqat JPG yoki PNG formatida bo'lishi kerak, fayl hajmi **5MB** bilan cheklangan. Ushbu tekshirish (validation) **server tomonida** amalga oshirilishi shart.
|
||||
* **Ma'lumotlar bazasi**: Kategoriyalar alohida jadvalda (`categories`) boshqarilishi kerak. Mahsulotlar jadvali (`products`) `category_id` ni tashqi kalit (FK) sifatida ko'rsatishi kerak.
|
||||
* **Dastlabki ma'lumotlar**: Quyidagi ma'lumotlar birinchi ishga tushirilganda (Seeder yoki Migration orqali) avtomatik ravishda yaratilishi kerak.
|
||||
* Ma'mur (Admin) hisobi: Ismi `Admin`, Email `admin@shoppress.local`, Parol `password` (parol xesh shaklida saqlanishi kerak)
|
||||
* Kamida 3 ta dastlabki kategoriya (masalan, `Kiyim-kechak`, `Elektronika`, `Oziq-ovqat`)
|
||||
|
||||
---
|
||||
|
||||
## 3. Bajarilishi kerak bo'lgan vazifalar
|
||||
|
||||
### **1. Autentifikatsiya**
|
||||
|
||||
#### 1.1 Tizimga kirish va sessiyalarni boshqarish
|
||||
|
||||
Kirish sahifasiga `/admin/login` manzili orqali kirish mumkin. Foydalanuvchi o'z emaili va parolini kiritadi. Muvaffaqiyatli kirishdan so'ng, foydalanuvchi ma'mur paneliga (dashboard) yo'naltiriladi. Xato bo'lsa, **"Incorrect email or password."** xabarini ko'rsating.
|
||||
|
||||
Tizimga kirmasdan `/admin` ostidagi har qanday yo'nalishga kirishga urinish foydalanuvchini kirish sahifasiga qayta yo'naltiradi. Tizimdan chiqish sessiyani yo'q qiladi va kirish sahifasiga yo'naltiradi.
|
||||
|
||||
Hozirda tizimga kirgan ma'murning ismi barcha ma'muriy sahifalarning navigatsiya qismida ko'rsatilishi kerak.
|
||||
|
||||
---
|
||||
|
||||
### **2. Ma'mur (Admin) funksiyalari**
|
||||
|
||||
#### 2.1 Dashboard (Boshqaruv paneli)
|
||||
|
||||
Dashboard standart ma'muriy sahifa bo'lib (`/admin` yoki `/admin/dashboard`), tizimga kirgandan keyin ko'rsatiladigan birinchi sahifadir.
|
||||
|
||||
Dashboardda quyidagi 4 ta statistikani kartalar shaklida ko'rsating.
|
||||
|
||||
| Karta yorlig'i | Mazmuni |
|
||||
| :--- | :--- |
|
||||
| **Total Products** | Mahsulotlarning umumiy soni |
|
||||
| **Active Products** | Statusi `Active` bo'lgan mahsulotlar soni |
|
||||
| **Total Orders** | Buyurtmalarning umumiy soni |
|
||||
| **Total Revenue** | Barcha yakuniy to'lov miqdorlarining yig'indisi (kupon chegirmalaridan keyin) |
|
||||
|
||||
Shuningdek, eng oxirgi joylashtirilgan 5 ta buyurtma ro'yxatini ko'rsating. Har bir qatorda: Buyurtma raqami, Mijoz, Jami summa, Status va Sana bo'lishi kerak.
|
||||
|
||||
#### 2.2 Mahsulotlarni boshqarish
|
||||
|
||||
Mahsulotlarni boshqarish sahifasi (`/admin/products`) barcha mahsulotlarni jadvalda ko'rsatadi.
|
||||
|
||||
Jadval ustunlari: **Nomi**, **Kategoriyasi**, **Narxi**, **Zaxira (Stock)**, **Statusi**, **Yaratilgan sana**, Tahrirlash / O'chirish tugmalari.
|
||||
|
||||
Mahsulotlarni nomi bo'yicha filtrlash uchun qidiruv maydonini taqdim eting. Qidiruv so'zi yuborilganda faqat nomi ushbu kalit so'zni o'z ichiga olgan mahsulotlar ko'rsatiladi.
|
||||
|
||||
**Mahsulotni ro'yxatdan o'tkazish shakli** (`/admin/products/new`) va **mahsulotni tahrirlash shakli** (`/admin/products/{id}/edit`) quyidagi maydonlarni o'z ichiga olishi kerak.
|
||||
|
||||
* **Nomi** (majburiy, maksimal 100 belgi)
|
||||
* **Kategoriya** (majburiy, dropdown — ma'lumotlar bazasidagi kategoriyalar bilan to'ldirilgan)
|
||||
* **Narxi** (majburiy, butun son, 0 yoki undan katta)
|
||||
* **Zaxira (Stock)** (majburiy, butun son, 0 yoki undan katta)
|
||||
* **Tavsifi** (`<textarea>`, ixtiyoriy)
|
||||
* **Rasm** (fayl yuklash, JPG/PNG, maksimal 5MB, **ixtiyoriy** — mahsulotlar rasmsiz ham ro'yxatdan o'tkazilishi mumkin)
|
||||
* **Status** (dropdown: `Active` / `Out of Stock` / `Hidden`)
|
||||
|
||||
Tahrirlash shakliga kirganda, mavjud ma'lumotlar har bir maydonga oldindan to'ldirilgan bo'lishi kerak. Agar yangi rasm yuklanmasa, eski rasm saqlanib qoladi. Agar yangi rasm yuklansa, eski rasm faylini serverdan o'chiring va uni yangisi bilan almashtiring.
|
||||
|
||||
Mahsulotni o'chirishda **"Are you sure you want to delete this product?"** tasdiqlash xabarini ko'rsating. Tasdiqlanganda, agar mahsulot biron bir buyurtmada (`order_items`) mavjud bo'lsa, o'chirishni rad eting va **"Cannot delete a product with order history."** xabarini ko'rsating. Agar mahsulot buyurtmalar tarixida bo'lmasa, uni ma'lumotlar bazasidan o'chiring va uning rasm faylini serverdan olib tashlang.
|
||||
|
||||
#### 2.3 Kategoriyalarni boshqarish
|
||||
|
||||
Kategoriyalarni boshqarish sahifasi (`/admin/categories`) kategoriyalarni qo'shish, tahrirlash va o'chirish imkonini beradi.
|
||||
|
||||
* **Qo'shish**: Kategoriya nomini kiriting va saqlang. Agar bunday nom mavjud bo'lsa, **"Category name already exists."** xabarini ko'rsating.
|
||||
* **Tahrirlash**: Kategoriya nomini o'zgartiring. Mahsulotlar kategoriyaga FK orqali bog'langanligi sababli, `categories` jadvalidagi nomni yangilash bog'langan mahsulotlarda avtomatik ravishda aks etadi.
|
||||
* **O'chirish**: Agar biron bir mahsulot ushbu kategoriyaga tegishli bo'lsa, o'chirishni rad eting va **"Cannot delete a category that has products assigned."** xabarini ko'rsating.
|
||||
|
||||
#### 2.4 Kuponlarni boshqarish
|
||||
|
||||
Kuponlarni boshqarish sahifasi (`/admin/coupons`) chegirma kuponlarini ro'yxatdan o'tkazish va boshqarish imkonini beradi.
|
||||
|
||||
**Kuponni ro'yxatdan o'tkazish shakli** quyidagi maydonlarni o'z ichiga oladi.
|
||||
|
||||
* **Kupon kodi** (majburiy, faqat bosh harflar yoki raqamlar, 6–12 belgi, takrorlanmas bo'lishi kerak)
|
||||
* **Chegirma turi** (dropdown: `Fixed` / `Percent`)
|
||||
* **Chegirma qiymati** (majburiy, butun son, 1 yoki undan katta. Agar `Percent` bo'lsa, 1 va 100 orasida bo'lishi kerak)
|
||||
* **Minimal buyurtma miqdori** (majburiy, butun son, 0 yoki undan katta. Kupon ushbu miqdordan past bo'lgan buyurtmalarga qo'llanilmaydi)
|
||||
* **Amal qilish muddati** (majburiy, `<input type="date">`. Faqat kelajakdagi sanalar tanlanishi mumkin)
|
||||
* **Foydalanish limiti** (majburiy, butun son, 1 yoki undan katta)
|
||||
|
||||
Kuponlar ro'yxati jadvali ustunlari: **Kodi**, **Turi**, **Qiymati**, **Min. buyurtma**, **Amal qilish muddati**, **Qolgan foydalanishlar**, O'chirish tugmasi. Qolgan foydalanishlar `remaining_uses` ustuni orqali boshqariladi, u ro'yxatdan o'tishda Foydalanish limiti qiymatiga tenglashtiriladi va kupon ishlatilganda 1 taga kamaytirib boriladi.
|
||||
|
||||
#### 2.5 Buyurtmalarni boshqarish
|
||||
|
||||
Buyurtmalarni boshqarish sahifasi (`/admin/orders`) barcha buyurtmalarni jadvalda ko'rsatadi.
|
||||
|
||||
Jadval ustunlari: **Buyurtma #**, **Mijoz**, **Telefon**, **Jami**, **Status**, **Sana**.
|
||||
|
||||
Buyurtmalarni status bo'yicha filtrlash uchun dropdown taqdim eting. Status qiymatlari: `Pending` / `Processing` / `Shipped` / `Delivered` / `Cancelled`. Faqat tanlangan statusga mos keladigan buyurtmalar ko'rsatiladi.
|
||||
|
||||
Buyurtma tafsilotlari sahifasi (`/admin/orders/{id}`) quyidagi ma'lumotlarni ko'rsatishi kerak.
|
||||
|
||||
* Mijoz ma'lumotlari: Ismi, Telefoni, Yetkazib berish manzili
|
||||
* Buyurtma elementlari: Mahsulot (mahsulot nomining o'sha paytdagi holati - snapshot), birlik narxi, miqdori, oraliq summa
|
||||
* Kupon: Qo'llanilgan kupon kodi va chegirma miqdori. Agar kupon ishlatilmagan bo'lsa, **"None"** deb ko'rsating.
|
||||
* Jami: Yakuniy to'lov miqdori
|
||||
* **Buyurtma statusi** dropdown (`Pending` / `Processing` / `Shipped` / `Delivered` / `Cancelled`) va Saqlash tugmasi. Muvaffaqiyatli saqlangandan so'ng, xuddi shu sahifada **"Order status updated."** xabarini ko'rsating.
|
||||
* Status **`Cancelled`** ga o'zgartirilganda, buyurtmadagi barcha mahsulotlarning zaxirasini (stock) buyurtma qilingan miqdorda qayta tiklang. Agar buyurtma allaqachon `Cancelled` bo'lsa va status qaytadan `Cancelled` ga o'zgartirilsa, zaxirani ikkinchi marta tiklamang.
|
||||
|
||||
---
|
||||
|
||||
### **3. Ommaviy sahifalar**
|
||||
|
||||
#### 3.1 Bosh sahifa — Mahsulotlar ro'yxati
|
||||
|
||||
Bosh sahifa (`/`) statusi **`Active`** bo'lgan mahsulotlarni kartalar ko'rinishida ko'rsatadi. Har bir kartada mahsulot rasmi (agar rasm bo'lmasa, kulrang placeholder maydonini ko'rsating), mahsulot nomi, kategoriya nomi va narxi ko'rsatiladi.
|
||||
|
||||
Har bir sahifada **12 ta elementni** sahifalash (pagination) bilan ko'rsating. Eng oxirgi ro'yxatdan o'tganlar birinchi bo'lib ko'rinsin.
|
||||
|
||||
Kategoriyalar bo'yicha filtrlash havolalarini taqdim eting. Kategoriyani bosganda faqat o'sha kategoriyadagi **`Active`** mahsulotlar ko'rsatiladi. Sahifalashda joriy kategoriya filtri saqlanib qolishi kerak.
|
||||
|
||||
Kalit so'z bilan qidirish maydonini taqdim eting. Mahsulotlar nomi bo'yicha qidiriladi. Kategoriya filtri va kalit so'z qidiruvi bir vaqtning o'zida qo'llanilishi kerak. Sahifalashda qidiruv shartlari saqlanib qolishi kerak.
|
||||
|
||||
#### 3.2 Mahsulot tafsilotlari
|
||||
|
||||
Mahsulot tafsilotlari sahifasiga `/products/{id}` manzili orqali kirish mumkin. Mavjud bo'lmagan ID-lar yoki statusi **`Hidden`** bo'lgan mahsulotlar uchun 404 sahifasini qaytaring.
|
||||
|
||||
Mahsulot tafsilotlari sahifasida mahsulot rasmi (rasm bo'lmasa kulrang placeholder), mahsulot nomi, kategoriya nomi, narxi, zaxira miqdori va tavsifi ko'rsatiladi.
|
||||
|
||||
Zaxirasi 0 bo'lgan yoki statusi **`Out of Stock`** bo'lgan mahsulotlarda **"Out of Stock"** xabari ko'rsatiladi va sotib olish tugmasi faolsizlantiriladi.
|
||||
|
||||
Zaxirasi 1 yoki undan ortiq va statusi **`Active`** bo'lgan mahsulotlarda miqdor kiritish maydoni (`<input type="number">`, min 1, max joriy zaxira) va **"Buy Now"** tugmasi ko'rsatiladi. Tugma bosilganda mahsulot ID-si va miqdori query string sifatida uzatiladi va buyurtma qilish (checkout) sahifasiga o'tiladi (`/checkout?product_id={id}&quantity={n}`).
|
||||
|
||||
#### 3.3 Buyurtmani rasmiylashtirish (Checkout)
|
||||
|
||||
Checkout sahifasi (`/checkout`) query stringdan `product_id` va `quantity` ni o'qiydi va buyurtma qisqacha mazmunini ko'rsatadi (mahsulot nomi, birlik narxi, miqdori, oraliq summa). Server quyidagi shartlarni tekshirishi va agar ulardan birortasi bajarilmasa, bosh sahifaga (`/`) yo'naltirishi kerak:
|
||||
|
||||
* `product_id` bo'yicha mahsulot mavjud emas
|
||||
* Mahsulot statusi **`Hidden`** yoki **`Out of Stock`**
|
||||
* Zaxira 0 ga teng
|
||||
* `quantity` 1 dan kichik yoki joriy zaxiradan ko'p
|
||||
|
||||
Sahifada xaridorning ismi, telefoni va yetkazib berish manzili uchun forma mavjud. Barcha maydonlar majburiy va buyurtmalar faqat **server tomonidagi tekshiruvdan** o'tgandan keyingina qayta ishlanadi.
|
||||
|
||||
**Coupon Code** kiritish maydoni va **"Apply"** tugmasi mavjud. "Apply" bosilganda, `/checkout/coupon` endpointiga quyidagi formatda POST so'rovini yuborish uchun `fetch` dan foydalaning va sahifani to'liq yangilamasdan natijani aks ettiring. Ushbu endpoint ishtirokchi tomonidan amalga oshirilishi kerak.
|
||||
|
||||
* So'rov tanasi (JSON): `{ "coupon_code": "ABCD1234", "subtotal": 30000 }`
|
||||
* Muvaffaqiyatli javob (JSON): `{ "valid": true, "discount_type": "fixed"|"percent", "discount_value": 3000, "discount_amount": 3000, "final_amount": 27000 }`
|
||||
* Xato javob (JSON): `{ "valid": false, "message": "error message" }`
|
||||
|
||||
* To'g'ri kupon: Chegirmani hisoblang va sahifada yangilangan oraliq summa, chegirma va jami summani ko'rsating.
|
||||
* `Fixed` chegirma: Chegirma qiymatini to'g'ridan-to'g'ri oraliq summadan ayiring.
|
||||
* `Percent` chegirma: `oraliq summa × chegirma stavkasi / 100` ni ayiring. Har qanday o'nlik kasrni pastga qarab yaxlitlang (floor).
|
||||
* Yakuniy summa 0 dan pastga tushmasligi kerak.
|
||||
* Noto'g'ri kupon: Har bir holat uchun tegishli xato xabarini ko'rsating.
|
||||
* Kod mavjud emas: **"Invalid coupon code."**
|
||||
* Kupon muddati o'tgan: **"This coupon has expired."**
|
||||
* Foydalanish limiti tugagan: **"This coupon has reached its usage limit."**
|
||||
* Minimal buyurtma miqdoridan past: **"This coupon requires a minimum order of {n}."**
|
||||
|
||||
Buyurtmani yuborishda quyidagilarni **yagona tranzaksiya** sifatida bajaring.
|
||||
1. Buyurtma ma'lumotlarini `orders` jadvaliga saqlang (xaridor ismi, telefoni, yetkazib berish manzili, qo'llanilgan kupon ID-si — bo'lmasa NULL, chegirma miqdori — bo'lmasa 0, yakuniy to'lov miqdori).
|
||||
2. Buyurtma elementlari ma'lumotlarini `order_items` jadvaliga saqlang (buyurtma ID, mahsulot ID, **mahsulot nomi snapshot**, miqdori, birlik narxi). Mahsulot nomi buyurtma berilgan paytdagi holatida saqlanishi kerak, shunda mahsulot keyinchalik o'chirilsa yoki nomi o'zgartirilsa ham to'g'ri ko'rinadi.
|
||||
3. Buyurtma qilingan miqdorni mahsulot zaxirasidan (`stock`) chegirib tashlang.
|
||||
4. Agar kupon ishlatilgan bo'lsa, kuponning `remaining_uses` qiymatini 1 taga kamaytiring.
|
||||
|
||||
Agar so'ralgan miqdor uchun zaxira yetarli bo'lmasa, tranzaksiyani bekor qiling (roll back) va **"Not enough stock."** xabarini ko'rsating.
|
||||
|
||||
Buyurtma muvaffaqiyatli yuborilgandan so'ng, buyurtma yakunlangan sahifasiga (`/orders/{id}/complete`) yo'naltiring. Ushbu sahifa autentifikatsiyasiz ochiq bo'ladi va Buyurtma raqami, buyurtma elementlari tafsilotlari, chegirma va jami summani ko'rsatadi.
|
||||
|
||||
#### 3.4 Layout (Maket)
|
||||
|
||||
Barcha ommaviy sahifalar sarlavha (header) va foter (footer) qismlarini o'z ichiga oladi. Sarlavhada sayt nomi (**ShopPress**) va bosh sahifaga havola mavjud. Har bir sahifada uning mazmunini aks ettiruvchi tegishli `<title>` tegi bo'lishi kerak.
|
||||
|
||||
Ma'muriy panel sahifalarida sidebar yoki yuqori navigatsiya mavjud. Navigatsiya menyusi elementlari: **Dashboard**, **Products**, **Categories**, **Coupons**, **Orders**.
|
||||
|
||||
---
|
||||
|
||||
## 4. Topshirish bo'yicha ko'rsatmalar
|
||||
|
||||
Barcha natijalarni serverdagi `/module_b/` katalogiga yuklang.
|
||||
|
||||
---
|
||||
|
||||
## 5. Baholash sxemasi — Jami 25 ball
|
||||
|
||||
| Element | Mezon | Ballar |
|
||||
| :--- | :--- | :---: |
|
||||
| **A. Autentifikatsiya** | Kirish/chiqish, sessiya himoyasi, ruxsatsiz kirishni qayta yo'naltirish | 2 |
|
||||
| **B. Dashboard** | 4 ta statistika kartasi (inglizcha yorliqlar), oxirgi 5 ta buyurtma ro'yxati | 1 |
|
||||
| **C. Mahsulotlar boshqaruvi** | Ro'yxat (qidiruv bilan), ro'yxatdan o'tkazish (ixtiyoriy rasm), tahrirlash (eski rasmni saqlash/almashtirish+o'chirish), o'chirish (agar buyurtma tarixi bo'lsa rad etish + rasm faylini o'chirish) | 5 |
|
||||
| **D. Kategoriyalar boshqaruvi** | Qo'shish (takrorlanishni tekshirish), tahrirlash, o'chirish (mahsulotlar biriktirilgan bo'lsa rad etish) | 2 |
|
||||
| **E. Kuponlar boshqaruvi** | Ro'yxatdan o'tkazish (to'liq tekshiruv), ro'yxat (qolgan foydalanishlarni ko'rsatish), o'chirish | 3 |
|
||||
| **F. Buyurtmalar boshqaruvi** | Ro'yxat (status filtri), batafsil ko'rinish, statusni yangilash, "Cancelled" holatida zaxirani tiklash (takroriy tiklashni oldini olish) | 4 |
|
||||
| **G. Ommaviy — Mahsulotlar ro'yxati** | Faol mahsulotlarni filtrlash, kategoriya filtri, kalit so'z qidiruvi, sahifalash (shartlarni saqlash) | 3 |
|
||||
| **H. Ommaviy — Mahsulot tafsilotlari** | Mahsulot ma'lumotlarini ko'rsatish, "Out of Stock" holatini qayta ishlash (zaxira 0 yoki "Out of Stock" statusi), miqdor kiritish va checkoutga o'tish | 1 |
|
||||
| **I. Ommaviy — Checkout** | Kirish tekshiruvi (Out of Stock/Hidden/zaxiradan ko'p miqdor), kuponni qo'llash (fetch + chegirma hisobi), tranzaksiya (buyurtmani saqlash + zaxirani kamaytirish + kuponni kamaytirish), buyurtma yakunlangan sahifasi | 3 |
|
||||
| **J. Validation** | Server tomonida rasm hajmi/kengaytmasini tekshirish, checkout formasi maydonlarini tekshirish | 1 |
|
||||
| **Jami** | | **25** |
|
||||
Reference in New Issue
Block a user