diff --git a/README.md b/README.md
index 3e1213ef5f7..db846063b90 100644
--- a/README.md
+++ b/README.md
@@ -1,143 +1,574 @@
-# React Product Catalog
-
-Implement the catalog with a shopping cart and favorites page according to one of the next designs:
-
-- [Original](https://www.figma.com/file/T5ttF21UnT6RRmCQQaZc6L/Phone-catalog-(V2)-Original)
-- [Original Dark](https://www.figma.com/file/BUusqCIMAWALqfBahnyIiH/Phone-catalog-(V2)-Original-Dark)
-- [Rounded Blue](https://www.figma.com/file/FRxncC4lfyhs6og1L6FGEU/Phone-catalog-(V2)-Rounded-Style-2?node-id=0%3A1)
-- [Rounded Purple](https://www.figma.com/file/xMK2Dy0mfBbJJSNctmOuLW/Phone-catalog-(V2)-Rounded-Style-1?node-id=0%3A1)
-- [Rounded Orange](https://www.figma.com/file/7JTa0q8n3dTSAyMNaA0u8o/Phone-catalog-(V2)-Rounded-Style-3?node-id=0%3A1)
-
-You may also implement color theme switching!
-
-## If you work in a team
-
-Follow the [Work in a team guideline](https://github.com/mate-academy/react_task-guideline/blob/master/team-flow.md#how-to-work-in-a-team)
-
-## Project Setup from scratch
-
-Follow the [Instruction](https://github.com/mate-academy/react_phone-catalog/blob/master/setup.md) to setup your project, add Eslint, Prettier, Husky and enable auto deploy.
-
-## Data
-
-Use the data from `/public/api` and images from `/public/img` folders. You can reorganize them the way you like.
-
-## App
-
-1. Put components into the `src/components` folder.
- - Each component should be a folder with `index.ts`, `ComponentName.tsx`, `ComponentName.module.scss` files.
- - Use CSS modules.
- - Keep `.module.scss` files together with their components.
-2. Advanced project structure:
- - `src/modules` folder. Inside per page modules `HomePage`, `CartPage`, etc., and `shared` folder with shared content between modules.
- - Inside each module its own `components` folder with the structure described above. And optionally other files/folders: `hooks`, `constants`, and so on.
-3. Add the sticky header with a logo, navigation, favorites, and cart.
-4. The footer with the link to the GitHub repo and `Back to top` button.
- - The content should be limited to the same width as the page content;
- - `Back to top` button should scroll to the top smoothly;
-5. Add `NotFoundPage` containing text `Page not found` for all the unknown URLs.
-6. All changes the hover effects should be smooth.
-7. Scale all image links by 10% on hover.
-8. Implement all form elements and icons according to the UI Kit.
-
-## Home page
-
-Implement Home page at available at `/`.
-
-1. `
Product Catalog ` should be visually hidden.
-2. `PicturesSlider`:
- - Find your own images to personalize the App;
- - Change pictures automatically every 5 seconds;
- - The next buttons should show the first image after the last one;
- - Dashes at the bottom should allow choosing an exact picture.
-3. `ProductsSlider` for the `Hot prices` block:
- - The products with a discount starting from the biggest absolute value;
- - `<` and `>` buttons should scroll products.
-4. `Shop by category` block with links to `/phones`, `/tablets`, and `/accessories`.
-5. Add Brand new block using ProductsSlider with products that are the newest according to the year field.
-
-## Product pages
-
-There should be 3 separate pages `/phones`, `/tablets`, and `/accessories`.
-
-1. Each page loads the data of the required `type`.
-2. Add an `h1` with `Phones/Tablets/Accessories page` (choose required).
-3. Add `ProductsList` component showing all the `products`.
-4. Implement a `Loader` to show it while waiting for the data from the server.
-5. In case of a loading error show the something went wrong message with a reload button.
-6. If there are no products available show the `There are no phones/tablets/accessories yet` message (choose required).
-7. Add a `` with the `Newest`, `Alphabetically`, and `Cheapest` options to sort products by `age`, `title`, or `price` (after discount).
- - Save the sort value in the URL `?sort=age` and apply it after the page reload.
-8. Add `Pagination` buttons and `Items on page` select element with `4`, `8`, `16`, and `all` options.
- - It should limit the products you show to the user;
- - Save pagination params in the URL `?page=2&perPage=8` (`page=1` and `perPage=all` are the default values and should not be added to the URL;
- - Hide pagination elements if they do not make sense;
- - You can use the logic explained in [the React Pagination task](https://github.com/mate-academy/react_pagination#react-pagination).
-
-## Product details page
-
-Create `ProductDetailsPage` available at `/product/:productId`.
-
-1. `ProductCard` image and title should be links to the product details page.
-2. Use `Loader` when fetching the product details.
-3. Show the details on the page:
- - Display the available colors from colorsAvailable and the capacities from capacityAvailable as radio inputs, allowing the selection of one value from the offered options;
- - `About` section should contain a subheader with description;
- - Choose `Tech specs` you want to show.
-4. Add the ability to choose a picture.
-5. Implement `You may also like` block with products chosen randomly:
- - Create `getSuggestedProducts` method fetching the suggested products.
-6. Add `Back` button working the same way as a Browser `Back` button.
-7. Add `Breadcrumbs` at the top with:
- - A Home page link;
- - A category page link (`Phones`, `Tablets`, `Accessories`);
- - The name of the product (just a text).
-8. Show `Product was not found` if there is no product with a given id on the server.
-
-## Shopping Cart page
-
-Create a Cart page with a list of `CartItem`s at `/cart`.
-Each item should have an `id`, `quantity`, and a `product`.
-Use React Context or Redux to store Items.
-
-1. `Add to cart` button in the `ProductCard` should add a product to the `Cart`.
-2. If the product is already in the `Cart` the button should say `Added to cart` and do nothing.
-3. Add the ability to remove items from the `Cart` with an `x` button next to a `CartItem`.
-4. Add a message `Your cart is empty` when there are no products in the `Cart`.
-5. Add the ability to change the item quantity in the `Cart` with `-` and `+` buttons (it should be > 0).
-6. Total amount and quantity should be calculated automatically.
-7. Show the quantity at the `Cart` icon in the header.
-8. Save the `Cart` to `localStorage` on each change and read it on page load.
-9. `Checkout` button should show a modal dialog with the text `Checkout is not implemented yet. Do you want to clear the Cart?`:
- - Clear the Cart if the user confirms the order;
- - Keep the Cart items and close the confirmation on cancel;
- - Use the `confirm` function if you don't have a better solution.
-
-## Favorites page
-
-Create `Favorites` page with a `ProductsList` showing favorite products at `/favorites`.
-
-1. Add/remove a product to favorites by pressing a heart button in the `ProductCard` element.
-2. The heart should be highlighted if the product is already added to the favorites.
-3. Use React Context or Redux to store the favorites.
-4. Show the number of favorites at the `Favorites` icon in the header.
-5. Save favorites to `localStorage` on each change and load them on page load.
-
-## Other tasks
-
-1. Add `NotFoundPage` containing text `Page not found` for all the other URLs with the link to `HomePage`.
-2. Implement the `Product was not found` state for the `ProductDetailsPage`.
-
-## (*) Advanced tasks
-
-- Implement color theme switching!
-- Use [skeletons](https://freefrontend.com/css-skeleton-loadings/) to make loading more natural.
-- Add the ability to change page language.
-
-### Search
-
-Show `input:search` in the header when a page contains a `ProductList` to search in.
-
-1. Save the `Search` value in the URL as a `?query=value` to apply on page load.
-2. Show `There are no phones/tablets/accessories/products matching the query` instead of `ProductList` when needed.
-3. Add `debounce` to the search field.
+# 📱 React Phone Catalog
+
+Um catálogo de produtos completo (phones, tablets e acessórios) com carrinho de compras, favoritos e **tema claro/escuro**, construído com React 18 + TypeScript + Vite.
+
+
+
+
+
+
+
+
+
+
+
+
+
+---
+
+## 📋 Índice
+
+- [Visão Geral](#-visão-geral)
+- [Demo](#-demo)
+- [Tecnologias](#-tecnologias-e-ferramentas)
+- [Funcionalidades](#-funcionalidades-implementadas)
+- [Arquitetura](#-arquitetura-do-projeto)
+- [Estrutura de Pastas](#-estrutura-de-pastas)
+- [Design System](#-design-system)
+- [Componentes](#-componentes)
+- [Páginas e Rotas](#-páginas-e-rotas)
+- [Gerenciamento de Estado](#-gerenciamento-de-estado)
+- [Testes](#-testes)
+- [Instalação](#-instalação-e-execução)
+- [Scripts](#-scripts-disponíveis)
+- [Design de Referência](#-design-de-referência)
+- [Licença](#-licença)
+- [Autor](#-autor)
+
+---
+
+## 🎯 Visão Geral
+
+Este projeto é um catálogo de produtos da Apple com funcionalidades completas de e-commerce: listagem com filtros e paginação, página de detalhes com galeria de imagens e seletores de cor/capacidade, carrinho de compras com controle de quantidade, e favoritos. Inclui suporte nativo a **tema claro/escuro** com persistência via `localStorage` e detecção automática de preferência do sistema.
+
+### Principais Características:
+
+- ✅ **100% Responsivo** (Mobile → Tablet → Desktop)
+- ✅ **Tema Claro/Escuro** com toggle animado (sol/lua) e persistência
+- ✅ **Carrinho de Compras** com `useReducer` e `localStorage`
+- ✅ **Favoritos** com persistência local
+- ✅ **Busca com Debounce** (300ms) integrada à URL
+- ✅ **Paginação e Ordenação** controlados por URL params
+- ✅ **Galeria de Imagens** com seletores de cor e capacidade
+- ✅ **Slider Automático** no banner hero (5s)
+- ✅ **Carrossel de Produtos** (Hot Prices, Brand New)
+- ✅ **React Router v6** com HashRouter e rotas aninhadas
+- ✅ **SCSS Modules** com CSS Custom Properties para temas
+- ✅ **Código Limpo** com ESLint (Airbnb), Prettier e Stylelint
+
+---
+
+## 🌐 Demo
+
+**Produção:** [https://glauccoeng-prog.github.io/react_phone-catalog/](https://glauccoeng-prog.github.io/react_phone-catalog/)
+
+---
+
+## 🚀 Tecnologias e Ferramentas
+
+### Core
+
+| Tecnologia | Versão | Descrição |
+| --------------------------------------------- | ------ | ---------------------------------------- |
+| [React](https://react.dev/) | 18.3.1 | Biblioteca de UI com hooks e Context API |
+| [TypeScript](https://www.typescriptlang.org/) | 5.2 | Tipagem estática para JavaScript |
+| [Vite](https://vitejs.dev/) | 5.3.1 | Build tool ultra-rápida com HMR |
+| [React Router](https://reactrouter.com/) | 6.25.1 | Roteamento SPA com HashRouter |
+| [SCSS/Sass](https://sass-lang.com/) | 1.77.8 | Pré-processador CSS com módulos |
+
+### Estilização
+
+| Tecnologia | Descrição |
+| --------------------------------------------------------- | ---------------------------------------------- |
+| [CSS Modules](https://github.com/css-modules/css-modules) | Estilos escopados por componente |
+| CSS Custom Properties | Sistema de temas claro/escuro |
+| [Mont Font](https://www.fontshop.com/families/mont) | Tipografia principal (Regular, SemiBold, Bold) |
+| Flexbox / CSS Grid | Layouts flexíveis e responsivos |
+| BEM Naming | Convenção de nomenclatura CSS |
+
+### Bibliotecas Adicionais
+
+| Biblioteca | Versão | Descrição |
+| ---------------------------------------------------------------------------- | ------- | ------------------------ |
+| [classnames](https://www.npmjs.com/package/classnames) | 2.5.1 | Classes CSS condicionais |
+| [react-transition-group](https://reactcommunity.org/react-transition-group/) | 4.4.5 | Animações de transição |
+| [i18next](https://www.i18next.com/) | 25.8.14 | Internacionalização |
+| [Font Awesome](https://fontawesome.com/) | 6.5.2 | Biblioteca de ícones |
+
+### Qualidade de Código
+
+| Tecnologia | Versão | Descrição |
+| ---------------------------------- | ------ | ----------------------------------------- |
+| [ESLint](https://eslint.org/) | 8.57.0 | Linter JS/TS (config Airbnb + TypeScript) |
+| [Prettier](https://prettier.io/) | 3.3.2 | Formatador de código automático |
+| [Stylelint](https://stylelint.io/) | 16.7.0 | Linter para CSS/SCSS |
+
+### Testes
+
+| Tecnologia | Versão | Descrição |
+| -------------------------------------------------------- | ------- | --------------------------------- |
+| [Cypress](https://www.cypress.io/) | 13.13.0 | Testes E2E e de componente |
+| [Mochawesome](https://adamgruber.github.io/mochawesome/) | 7.1.3 | Relatórios de testes em JSON/HTML |
+
+---
+
+## ✨ Funcionalidades Implementadas
+
+### 1. 🌓 Tema Claro/Escuro
+
+- **Toggle animado** com ícones SVG inline (sol/lua)
+- **3 fontes de detecção**: `localStorage` → `prefers-color-scheme` → fallback `light`
+- **Persistência** via `localStorage` (chave `theme`)
+- **CSS Custom Properties** para transição suave entre temas
+- **Inversão automática** de ícones SVG no modo escuro (`filter: invert`)
+- **Atributo `data-no-invert`** para excluir ícones específicos (ex: coração vermelho)
+- **Paleta dark**: botões roxos (#905BFF), superfícies #161827, cards #323542
+
+### 2. 🛒 Carrinho de Compras
+
+- **Adicionar/remover** produtos com feedback visual
+- **Controle de quantidade** (incrementar/decrementar)
+- **Cálculo automático** de total (preço × quantidade)
+- **Persistência** em `localStorage` (chave `cart`)
+- **Gerenciado com `useReducer`** (ações: ADD, REMOVE, INCREMENT, DECREMENT, CLEAR)
+- **Checkout** com dialog de confirmação
+
+### 3. ❤️ Favoritos
+
+- **Toggle** de favorito com ícone de coração (outline/filled)
+- **Persistência** em `localStorage` (chave `favorites`)
+- **Busca** dentro dos favoritos via URL param `query`
+- **Contador** no badge do header
+
+### 4. 🔍 Busca com Debounce
+
+- **Input com debounce de 300ms** para performance
+- **Integrado à URL** via `useSearchParams`
+- **Filtra em tempo real** pelo nome do produto
+- **Disponível** nas páginas de listagem e favoritos
+
+### 5. 🖼️ Página de Detalhes do Produto
+
+- **Galeria de imagens** com thumbnails clicáveis
+- **Seletor de cor** com 25+ mapeamentos de nome → hex
+- **Seletor de capacidade** com links dinâmicos
+- **Seção "About"** com descrições renderizadas a partir de array
+- **Tabela de specs** (tela, resolução, processador, RAM, câmera, etc.)
+- **"You may also like"** com produtos sugeridos aleatoriamente
+
+### 6. 📊 Listagem com Filtros e Paginação
+
+- **Ordenação**: Mais novos, A-Z, Preço baixo
+- **Itens por página**: 4, 8, 16, Todos
+- **Paginação** com janela deslizante de 4 páginas visíveis
+- **Todos os parâmetros controlados via URL** (sort, perPage, page, query)
+- **Breadcrumbs** de navegação
+
+### 7. 🎠 Sliders e Carrosséis
+
+- **Banner hero** com 4 imagens, auto-play a cada 5s
+- **"Hot Prices"** — produtos com maior desconto
+- **"Brand New Models"** — produtos mais recentes
+- **Navegação** por setas com botões prev/next
+- **Dot indicators** no banner
+
+### 8. 📱 Design Responsivo
+
+- **3 breakpoints**: Mobile (< 640px), Tablet (640px), Desktop (1200px)
+- **Conteúdo limitado** a `max-width: 1136px`
+- **Header responsivo** com menu hamburger mobile
+- **Grids adaptativos** para categorias e cards
+
+---
+
+## 🏗️ Arquitetura do Projeto
+
+O projeto segue uma arquitetura modular com separação clara de responsabilidades.
+
+### Fluxo de Dados
+
+```
+┌──────────────┐ ┌────────────────┐ ┌──────────────────────┐
+│ HashRouter │────▶│ App.tsx │────▶│ Layout (Header + │
+│ (index.tsx) │ │ (Providers) │ │ Outlet + Footer) │
+└──────────────┘ └────────────────┘ └──────────────────────┘
+ │
+ ┌──────────┼──────────┐
+ ▼ ▼ ▼
+ ThemeProvider CartProvider FavoritesProvider
+ (useState) (useReducer) (useState)
+ │ │ │
+ └──────────┼──────────┘
+ ▼
+ ┌──────────────┐
+ │ /public/api │ ← JSON estático
+ │ (fetch + │
+ │ 300ms delay)│
+ └──────────────┘
+```
+
+### Padrões Utilizados
+
+| Padrão | Onde | Descrição |
+| ------------------------- | ---------------------------------- | ----------------------------------- |
+| **Context + Reducer** | `CartContext` | Gerenciamento de estado complexo |
+| **Context + State** | `FavoritesContext`, `ThemeContext` | Estado simples |
+| **Barrel Exports** | `index.ts` em cada componente | Re-export para imports limpos |
+| **CSS Modules** | Todos componentes | Estilos escopados |
+| **CSS Custom Properties** | `_base.scss` | Temas sem re-render |
+| **URL-driven State** | `ProductsPage` | Sort, page, perPage como URL params |
+| **Debounced Input** | `Header` | Otimização de buscas |
+| **Lazy Initialization** | `CartContext` | `localStorage` lido uma única vez |
+
+---
+
+## 📂 Estrutura de Pastas
+
+```
+react_phone-catalog/
+├── 📄 index.html # HTML principal (entry point)
+├── 📄 package.json # Dependências e scripts npm
+├── 📄 vite.config.ts # Configuração do Vite
+├── 📄 tsconfig.json # Configuração TypeScript
+├── 📄 cypress.config.ts # Configuração do Cypress
+├── 📄 LICENSE # Licença GPL-3.0
+├── 📄 README.md # Esta documentação
+│
+├── 📁 cypress/ # Testes E2E
+│ ├── 📁 integration/
+│ │ └── 📄 page.spec.js # Testes da página
+│ └── 📁 support/
+│ ├── 📄 commands.ts # Comandos customizados
+│ ├── 📄 component.ts # Setup de componentes
+│ ├── 📄 component-index.html # HTML para component testing
+│ └── 📄 e2e.ts # Configuração E2E
+│
+├── 📁 public/ # Assets estáticos
+│ ├── 📁 api/ # JSON API estática
+│ │ ├── 📄 products.json # Todos os produtos (listagem)
+│ │ ├── 📄 phones.json # Detalhes de phones
+│ │ ├── 📄 tablets.json # Detalhes de tablets
+│ │ └── 📄 accessories.json # Detalhes de acessórios
+│ ├── 📁 fonts/ # Fontes Mont (otf)
+│ └── 📁 img/ # Imagens
+│ ├── 📁 icons/ # SVG icons (setas, coração, etc.)
+│ ├── 📁 phones/ # Fotos por modelo de phone
+│ ├── 📁 tablets/ # Fotos por modelo de tablet
+│ └── 📁 accessories/ # Fotos por modelo de acessório
+│
+└── 📁 src/ # Código fonte
+ │
+ ├── 📄 index.tsx # Entry point (HashRouter + App)
+ ├── 📄 App.tsx # Providers + Routes + Layout
+ ├── 📄 App.scss # Estilos globais da App
+ ├── 📄 vite-env.d.ts # Tipos do Vite
+ │
+ ├── 📁 styles/ # Estilos globais
+ │ ├── 📄 _variables.scss # Tokens, fonts, mixins, breakpoints
+ │ └── 📄 _base.scss # Reset, temas (CSS vars), utilitários
+ │
+ ├── 📁 types/ # Interfaces TypeScript
+ │ ├── 📄 Product.ts # Produto (listagem)
+ │ ├── 📄 ProductDetails.ts # Detalhes do produto
+ │ └── 📄 CartItem.ts # Item do carrinho
+ │
+ ├── 📁 utils/
+ │ └── 📄 api.ts # Funções de fetch (JSON estático)
+ │
+ ├── 📁 context/ # React Contexts
+ │ ├── 📄 ThemeContext.tsx # Tema claro/escuro
+ │ ├── 📄 CartContext.tsx # Carrinho (useReducer)
+ │ └── 📄 FavoritesContext.tsx # Favoritos (useState)
+ │
+ ├── 📁 components/ # Componentes reutilizáveis
+ │ ├── 📁 Header/ # Navegação + busca + badges
+ │ ├── 📁 Footer/ # Rodapé + back to top
+ │ ├── 📁 ThemeToggle/ # Botão sol/lua
+ │ ├── 📁 ProductCard/ # Card de produto
+ │ ├── 📁 ProductsSlider/ # Carrossel horizontal
+ │ ├── 📁 PicturesSlider/ # Banner hero auto-play
+ │ ├── 📁 Pagination/ # Paginação com janela deslizante
+ │ ├── 📁 Dropdown/ # Select genérico com label
+ │ ├── 📁 Breadcrumbs/ # Trilha de navegação
+ │ ├── 📁 BackButton/ # Botão voltar (history)
+ │ └── 📁 Loader/ # Spinner de carregamento
+ │
+ └── 📁 modules/ # Páginas (módulos por rota)
+ ├── 📁 HomePage/ # Página inicial (sliders + categorias)
+ ├── 📁 PhonesPage/ # Listagem de phones
+ ├── 📁 TabletsPage/ # Listagem de tablets
+ ├── 📁 AccessoriesPage/ # Listagem de acessórios
+ ├── 📁 ProductsPage/ # Componente de listagem reutilizável
+ ├── 📁 ProductDetailsPage/ # Detalhes com galeria + specs
+ ├── 📁 FavoritesPage/ # Produtos favoritados
+ ├── 📁 CartPage/ # Carrinho de compras
+ └── 📁 NotFoundPage/ # Página 404
+```
+
+---
+
+## 🎨 Design System
+
+### Paleta de Cores — Tema Claro (Light)
+
+| Variável | Valor | Uso |
+| ---------------------- | --------- | -------------------- |
+| `--color-primary` | `#313237` | Textos principais |
+| `--color-secondary` | `#89939A` | Textos secundários |
+| `--color-icons` | `#B4BDC3` | Ícones |
+| `--color-elements` | `#E2E6E9` | Bordas e separadores |
+| `--color-hover-and-bg` | `#FAFBFC` | Hover e backgrounds |
+| `--color-white` | `#FFFFFF` | Fundo principal |
+| `--color-accent` | `#4219D0` | Cor de destaque |
+| `--color-button` | `#313237` | Botões CTA |
+| `--color-surface` | `#FFFFFF` | Superfície dos cards |
+
+### Paleta de Cores — Tema Escuro (Dark)
+
+| Variável | Valor | Uso |
+| ---------------------- | --------- | ---------------------------- |
+| `--color-primary` | `#F1F2F9` | Textos principais |
+| `--color-secondary` | `#75767F` | Textos secundários |
+| `--color-icons` | `#4A4D58` | Ícones |
+| `--color-elements` | `#3B3E4A` | Bordas e separadores |
+| `--color-hover-and-bg` | `#323542` | Hover e Surface 2 |
+| `--color-white` | `#0F1121` | Fundo principal (Gray-Black) |
+| `--color-accent` | `#905BFF` | Cor de destaque (Roxo) |
+| `--color-button` | `#905BFF` | Botões CTA (Roxo) |
+| `--color-surface` | `#161827` | Superfície dos cards |
+
+### Tipografia
+
+| Propriedade | Valor |
+| ------------------ | ----------------------------------------- |
+| Font Family | `Mont, Arial, sans-serif` |
+| Font Weights | 400 (Regular), 600 (SemiBold), 700 (Bold) |
+| Font Size (base) | 14px |
+| Line Height (base) | 21px |
+
+### Breakpoints
+
+| Variável | Valor | Dispositivo |
+| ---------- | ------- | --------------- |
+| Base | < 640px | Mobile (padrão) |
+| `$tablet` | 640px | Tablets |
+| `$desktop` | 1200px | Desktop |
+
+### Grid
+
+| Propriedade | Valor |
+| --------------- | ------ |
+| Max Width | 1136px |
+| Padding Mobile | 16px |
+| Padding Tablet | 24px |
+| Padding Desktop | 48px |
+
+---
+
+## 🧩 Componentes
+
+### Componentes Reutilizáveis
+
+| Componente | Arquivo | Descrição |
+| ---------------- | ---------------------------- | -------------------------------------------- |
+| `Header` | `components/Header/` | Nav + busca debounced + badges + menu mobile |
+| `Footer` | `components/Footer/` | Links + "Back to top" smooth scroll |
+| `ThemeToggle` | `components/ThemeToggle/` | Toggle claro/escuro com SVG animado |
+| `ProductCard` | `components/ProductCard/` | Card com preços, specs, cart e favorito |
+| `ProductsSlider` | `components/ProductsSlider/` | Carrossel com setas (Hot Prices, Brand New) |
+| `PicturesSlider` | `components/PicturesSlider/` | Banner hero com auto-play 5s + dots |
+| `Pagination` | `components/Pagination/` | Paginação com janela de 4 páginas |
+| `Dropdown` | `components/Dropdown/` | Select nativo com label |
+| `Breadcrumbs` | `components/Breadcrumbs/` | Trilha Home > Categoria > Produto |
+| `BackButton` | `components/BackButton/` | Navegação history.back() |
+| `Loader` | `components/Loader/` | Spinner CSS animado |
+
+### Mixins SCSS
+
+| Mixin | Descrição | Uso |
+| ------------------------ | -------------------------- | ---------------------------------- |
+| `on-tablet` | Media query ≥ 640px | `@include on-tablet { ... }` |
+| `on-desktop` | Media query ≥ 1200px | `@include on-desktop { ... }` |
+| `content-padding-inline` | Padding lateral responsivo | `@include content-padding-inline;` |
+
+---
+
+## 🗺️ Páginas e Rotas
+
+| Rota | Componente | Descrição |
+| --------------------- | ---------------------------------- | ------------------------------------------------ |
+| `/` | `HomePage` | Banner, sliders Hot Prices/Brand New, categorias |
+| `/phones` | `PhonesPage` → `ProductsPage` | Listagem de phones com filtros |
+| `/tablets` | `TabletsPage` → `ProductsPage` | Listagem de tablets com filtros |
+| `/accessories` | `AccessoriesPage` → `ProductsPage` | Listagem de acessórios com filtros |
+| `/product/:productId` | `ProductDetailsPage` | Galeria, specs, cor, capacidade, sugestões |
+| `/favorites` | `FavoritesPage` | Produtos favoritados com busca |
+| `/cart` | `CartPage` | Carrinho com quantidades e checkout |
+| `*` | `NotFoundPage` | Página 404 |
+
+> **Nota:** `PhonesPage`, `TabletsPage` e `AccessoriesPage` são wrappers finos que renderizam `ProductsPage` com a categoria correspondente.
+
+---
+
+## 🧠 Gerenciamento de Estado
+
+### Contexts
+
+| Context | Padrão | Persistência | Funcionalidades |
+| ------------------ | ------------ | --------------------------- | ------------------------------------------------------------------------------------------------------------ |
+| `ThemeContext` | `useState` | `localStorage("theme")` | `theme`, `toggleTheme()` |
+| `CartContext` | `useReducer` | `localStorage("cart")` | `addToCart`, `removeFromCart`, `increment`, `decrement`, `clearCart`, `isInCart`, `totalItems`, `totalPrice` |
+| `FavoritesContext` | `useState` | `localStorage("favorites")` | `toggleFavorite`, `isFavorite`, `totalFavorites`, `favorites[]` |
+
+### Hierarquia de Providers
+
+```
+
+ ← Tema (data-theme no )
+ ← Carrinho (useReducer)
+ ← Favoritos (useState)
+
+
+
+
+
+```
+
+### API Layer
+
+| Função | Descrição |
+| ------------------------ | ---------------------------------------------------- |
+| `getProducts()` | Retorna todos os produtos (`products.json`) |
+| `getPhones()` | Retorna detalhes dos phones (`phones.json`) |
+| `getTablets()` | Retorna detalhes dos tablets (`tablets.json`) |
+| `getAccessories()` | Retorna detalhes dos acessórios (`accessories.json`) |
+| `getProductDetails(id)` | Busca nas 3 categorias e retorna o produto por `id` |
+| `getSuggestedProducts()` | Retorna produtos embaralhados aleatoriamente |
+
+> Todas as funções possuem **simulação de delay de 300ms** para UX realista.
+
+---
+
+## 🧪 Testes
+
+### Cypress E2E
+
+O projeto utiliza **Cypress** para testes end-to-end e de componentes.
+
+#### Configuração (`cypress.config.ts`)
+
+```typescript
+e2e: {
+ baseUrl: 'http://localhost:3000',
+ specPattern: 'cypress/integration/**/*.spec.{js,ts,jsx,tsx}',
+},
+component: {
+ framework: 'react',
+ bundler: 'vite',
+},
+video: true,
+viewportHeight: 1920,
+viewportWidth: 1080,
+reporter: 'mochawesome',
+```
+
+#### Executar Testes
+
+```bash
+# Modo interativo (abre navegador)
+npm run test
+
+# Apenas testes (sem lint)
+npm run test -- --only
+```
+
+---
+
+## 🔧 Instalação e Execução
+
+### Pré-requisitos
+
+- **Node.js** v20 ou superior
+- **npm** v9 ou superior
+
+### Passos
+
+```bash
+# 1. Clone o repositório
+git clone https://github.com/glauccoeng-prog/react-phone-catalog.git
+cd react-phone-catalog
+
+# 2. Instale as dependências
+npm install
+
+# 3. Inicie o servidor de desenvolvimento
+npm start
+
+# 4. Acesse no navegador
+# http://localhost:3000
+```
+
+### Build de Produção
+
+```bash
+# Gerar build otimizado
+npm run build
+
+# Deploy para GitHub Pages
+npm run deploy
+```
+
+---
+
+## 📜 Scripts Disponíveis
+
+| Script | Comando | Descrição |
+| ---------------------- | -------------------------------------------- | ---------------------------------- |
+| `npm start` | `mate-scripts start -l` | Inicia servidor de desenvolvimento |
+| `npm run build` | `mate-scripts build` | Gera build de produção |
+| `npm run deploy` | `mate-scripts deploy` | Deploy para GitHub Pages |
+| `npm run lint` | `style-format + format + lint-js + lint-css` | Executa todos os linters |
+| `npm run lint-js` | `mate-scripts lint -j` | Lint JavaScript/TypeScript |
+| `npm run lint-css` | `mate-scripts lint -s` | Lint CSS/SCSS |
+| `npm run format` | `prettier --write` | Formata arquivos TS/TSX |
+| `npm run style-format` | `stylelint --fix` | Corrige estilos SCSS |
+| `npm run test` | `mate-scripts test -l` | Lint + testes Cypress |
+
+---
+
+## 🎨 Design de Referência
+
+Este projeto foi implementado baseado nos designs do Figma:
+
+- **Original:** [Phone-catalog (V2) Original]()
+- **Original Dark:** [Phone-catalog (V2) Original Dark]()
+
+### Páginas Implementadas
+
+1. **Home** — Banner slider + Hot Prices + Shop by Category + Brand New
+2. **Phones/Tablets/Accessories** — Listagem com filtros, sort e paginação
+3. **Product Details** — Galeria + seletores + specs + "You may also like"
+4. **Favorites** — Lista de favoritos com busca
+5. **Cart** — Itens, quantidades, total e checkout
+6. **404** — Página não encontrada
+
+---
+
+## 📄 Licença
+
+Este projeto está sob a licença **GPL-3.0**. Veja o arquivo [LICENSE](./LICENSE) para mais detalhes.
+
+---
+
+## 👨💻 Autor
+
+**Glaucco Siqueira**
+
+[](https://www.linkedin.com/in/glaucco-siqueira/)
+[](https://github.com/glauccoeng-prog)
+
+---
+
+
+ Desenvolvido com 💚 durante o curso da Mate Academy
+
diff --git a/index.html b/index.html
index 095fb3a4537..d3267dc0666 100644
--- a/index.html
+++ b/index.html
@@ -3,7 +3,11 @@
- Vite + React + TS
+
+ Nice Gadgets store
diff --git a/package-lock.json b/package-lock.json
index 836b9e63b46..dc899ad61e2 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -13,14 +13,16 @@
"@fortawesome/fontawesome-free": "^6.5.2",
"bulma": "^1.0.1",
"classnames": "^2.5.1",
+ "i18next": "^25.8.14",
"react": "^18.3.1",
"react-dom": "^18.3.1",
+ "react-i18next": "^16.5.5",
"react-router-dom": "^6.25.1",
"react-transition-group": "^4.4.5"
},
"devDependencies": {
"@cypress/react18": "^2.0.1",
- "@mate-academy/scripts": "^1.8.5",
+ "@mate-academy/scripts": "^2.1.3",
"@mate-academy/students-ts-config": "*",
"@mate-academy/stylelint-config": "*",
"@types/node": "^20.14.10",
@@ -90,6 +92,7 @@
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.9.tgz",
"integrity": "sha512-5e3FI4Q3M3Pbr21+5xJwCv6ZT6KmGkI0vw3Tozy5ODAQFTIWe37iT8Cr7Ice2Ntb+M3iSKCEWMB1MBgKrW3whg==",
"dev": true,
+ "peer": true,
"dependencies": {
"@ampproject/remapping": "^2.2.0",
"@babel/code-frame": "^7.24.7",
@@ -365,12 +368,10 @@
}
},
"node_modules/@babel/runtime": {
- "version": "7.24.8",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.8.tgz",
- "integrity": "sha512-5F7SDGs1T72ZczbRwbGO9lQi0NLjQxzl6i4lJxLxfW9U5UluCSyEJeniWvnhl3/euNiqQVbo8zruhsDfid0esA==",
- "dependencies": {
- "regenerator-runtime": "^0.14.0"
- },
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz",
+ "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==",
+ "license": "MIT",
"engines": {
"node": ">=6.9.0"
}
@@ -449,6 +450,7 @@
"url": "https://opencollective.com/csstools"
}
],
+ "peer": true,
"engines": {
"node": "^14 || ^16 || >=18"
},
@@ -471,6 +473,7 @@
"url": "https://opencollective.com/csstools"
}
],
+ "peer": true,
"engines": {
"node": "^14 || ^16 || >=18"
}
@@ -1184,10 +1187,11 @@
}
},
"node_modules/@mate-academy/scripts": {
- "version": "1.8.5",
- "resolved": "https://registry.npmjs.org/@mate-academy/scripts/-/scripts-1.8.5.tgz",
- "integrity": "sha512-mHRY2FkuoYCf5U0ahIukkaRo5LSZsxrTSgMJheFoyf3VXsTvfM9OfWcZIDIDB521kdPrScHHnRp+JRNjCfUO5A==",
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/@mate-academy/scripts/-/scripts-2.1.3.tgz",
+ "integrity": "sha512-a07wHTj/1QUK2Aac5zHad+sGw4rIvcNl5lJmJpAD7OxeSbnCdyI6RXUHwXhjF5MaVo9YHrJ0xVahyERS2IIyBQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"@octokit/rest": "^17.11.2",
"@types/get-port": "^4.2.0",
@@ -1224,15 +1228,13 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-2.0.0.tgz",
"integrity": "sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==",
- "dev": true,
- "peer": true
+ "dev": true
},
"node_modules/@mate-academy/stylelint-config/node_modules/cosmiconfig": {
"version": "8.3.6",
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz",
"integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==",
"dev": true,
- "peer": true,
"dependencies": {
"import-fresh": "^3.3.0",
"js-yaml": "^4.1.0",
@@ -1259,7 +1261,6 @@
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-5.0.1.tgz",
"integrity": "sha512-VfxadyCECXgQlkoEAjeghAr5gY3Hf+IKjKb+X8tGVDtveCjN+USwprd2q3QXBR9T1+x2DG0XZF5/w+7HAtSaXA==",
"dev": true,
- "peer": true,
"engines": {
"node": ">=10"
},
@@ -1272,7 +1273,6 @@
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-7.0.2.tgz",
"integrity": "sha512-TfW7/1iI4Cy7Y8L6iqNdZQVvdXn0f8B4QcIXmkIbtTIe/Okm/nSlHb4IwGzRVOd3WfSieCgvf5cMzEfySAIl0g==",
"dev": true,
- "peer": true,
"dependencies": {
"flat-cache": "^3.2.0"
},
@@ -1291,7 +1291,6 @@
"resolved": "https://registry.npmjs.org/meow/-/meow-10.1.5.tgz",
"integrity": "sha512-/d+PQ4GKmGvM9Bee/DPa8z3mXs/pkvJE2KEThngVNOqtmljC6K7NMPxtc2JeZYTmpWb9k/TmxjeL18ez3h7vCw==",
"dev": true,
- "peer": true,
"dependencies": {
"@types/minimist": "^1.2.2",
"camelcase-keys": "^7.0.0",
@@ -1318,7 +1317,6 @@
"resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-6.0.0.tgz",
"integrity": "sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==",
"dev": true,
- "peer": true,
"engines": {
"node": ">=12.0"
},
@@ -1335,7 +1333,6 @@
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
"integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
"dev": true,
- "peer": true,
"engines": {
"node": ">=8"
}
@@ -1486,7 +1483,6 @@
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz",
"integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==",
"dev": true,
- "peer": true,
"engines": {
"node": ">=10"
},
@@ -1534,7 +1530,6 @@
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-5.1.1.tgz",
"integrity": "sha512-rh3G3wDO8J9wSjfI436JUKzHIxq8NaiL0tVeB2aXmG6p/9859aUOAjA9pmSPNGGZxfwmaJ9ozOJImuNVJdpvbA==",
"dev": true,
- "peer": true,
"engines": {
"node": ">= 18"
}
@@ -1563,7 +1558,6 @@
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-10.1.1.tgz",
"integrity": "sha512-JYjh5rMOwXMJyUpj028cu0Gbp7qe/ihxfJMLc8VZBMMqSwLgOxDI1911gV4Enl1QSavAQNJcwmwBF9M0VvLh6Q==",
"dev": true,
- "peer": true,
"dependencies": {
"@octokit/types": "^13.0.0",
"universal-user-agent": "^7.0.2"
@@ -1577,7 +1571,6 @@
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-8.1.1.tgz",
"integrity": "sha512-ukiRmuHTi6ebQx/HFRCXKbDlOh/7xEV6QUXaE7MJEKGNAncGI/STSbOkl12qVXZrfZdpXctx5O9X1AIaebiDBg==",
"dev": true,
- "peer": true,
"dependencies": {
"@octokit/request": "^9.0.0",
"@octokit/types": "^13.0.0",
@@ -1591,8 +1584,7 @@
"version": "22.2.0",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-22.2.0.tgz",
"integrity": "sha512-QBhVjcUa9W7Wwhm6DBFu6ZZ+1/t/oYxqc2tp81Pi41YNuJinbFRx8B133qVOrAaBbF7D/m0Et6f9/pZt9Rc+tg==",
- "dev": true,
- "peer": true
+ "dev": true
},
"node_modules/@octokit/plugin-paginate-rest": {
"version": "2.21.3",
@@ -1654,7 +1646,6 @@
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-9.1.3.tgz",
"integrity": "sha512-V+TFhu5fdF3K58rs1pGUJIDH5RZLbZm5BI+MNF+6o/ssFNT4vWlCh/tVpF3NxGtP15HUxTTMUbsG5llAuU2CZA==",
"dev": true,
- "peer": true,
"dependencies": {
"@octokit/endpoint": "^10.0.0",
"@octokit/request-error": "^6.0.1",
@@ -1670,7 +1661,6 @@
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.4.tgz",
"integrity": "sha512-VpAhIUxwhWZQImo/dWAN/NpPqqojR6PSLgLYAituLM6U+ddx9hCioFGwBr5Mi+oi5CLeJkcAs3gJ0PYYzU6wUg==",
"dev": true,
- "peer": true,
"dependencies": {
"@octokit/types": "^13.0.0"
},
@@ -1858,7 +1848,6 @@
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.5.0.tgz",
"integrity": "sha512-HdqWTf5Z3qwDVlzCrP8UJquMwunpDiMPt5er+QjGzL4hqr/vBVY/MauQgS1xWxCDT1oMx1EULyqxncdCY/NVSQ==",
"dev": true,
- "peer": true,
"dependencies": {
"@octokit/openapi-types": "^22.2.0"
}
@@ -2193,8 +2182,7 @@
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz",
"integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==",
- "dev": true,
- "peer": true
+ "dev": true
},
"node_modules/@types/node": {
"version": "20.14.10",
@@ -2209,8 +2197,7 @@
"version": "2.4.4",
"resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz",
"integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==",
- "dev": true,
- "peer": true
+ "dev": true
},
"node_modules/@types/prop-types": {
"version": "15.7.12",
@@ -2223,6 +2210,7 @@
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz",
"integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==",
"dev": true,
+ "peer": true,
"dependencies": {
"@types/prop-types": "*",
"csstype": "^3.0.2"
@@ -2233,6 +2221,7 @@
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz",
"integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==",
"dev": true,
+ "peer": true,
"dependencies": {
"@types/react": "*"
}
@@ -2307,6 +2296,7 @@
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.16.0.tgz",
"integrity": "sha512-ar9E+k7CU8rWi2e5ErzQiC93KKEFAXA2Kky0scAlPcxYblLt8+XZuHUZwlyfXILyQa95P6lQg+eZgh/dDs3+Vw==",
"dev": true,
+ "peer": true,
"dependencies": {
"@typescript-eslint/scope-manager": "7.16.0",
"@typescript-eslint/types": "7.16.0",
@@ -2352,7 +2342,6 @@
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.16.0.tgz",
"integrity": "sha512-j0fuUswUjDHfqV/UdW6mLtOQQseORqfdmoBNDFOqs9rvNVR2e+cmu6zJu/Ku4SDuqiJko6YnhwcL8x45r8Oqxg==",
"dev": true,
- "peer": true,
"dependencies": {
"@typescript-eslint/typescript-estree": "7.16.0",
"@typescript-eslint/utils": "7.16.0",
@@ -2421,7 +2410,6 @@
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.16.0.tgz",
"integrity": "sha512-PqP4kP3hb4r7Jav+NiRCntlVzhxBNWq6ZQ+zQwII1y/G/1gdIPeYDCKr2+dH6049yJQsWZiHU6RlwvIFBXXGNA==",
"dev": true,
- "peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.4.0",
"@typescript-eslint/scope-manager": "7.16.0",
@@ -2486,6 +2474,7 @@
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz",
"integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==",
"dev": true,
+ "peer": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -2809,7 +2798,6 @@
"resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
"integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==",
"dev": true,
- "peer": true,
"engines": {
"node": ">=0.10.0"
}
@@ -2955,8 +2943,7 @@
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-3.0.2.tgz",
"integrity": "sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A==",
- "dev": true,
- "peer": true
+ "dev": true
},
"node_modules/binary-extensions": {
"version": "2.3.0",
@@ -3007,8 +2994,7 @@
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
"integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
- "dev": true,
- "peer": true
+ "dev": true
},
"node_modules/browserslist": {
"version": "4.23.2",
@@ -3029,6 +3015,7 @@
"url": "https://github.com/sponsors/ai"
}
],
+ "peer": true,
"dependencies": {
"caniuse-lite": "^1.0.30001640",
"electron-to-chromium": "^1.4.820",
@@ -3122,7 +3109,6 @@
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
"integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
"dev": true,
- "peer": true,
"engines": {
"node": ">=10"
},
@@ -3135,7 +3121,6 @@
"resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-7.0.2.tgz",
"integrity": "sha512-Rjs1H+A9R+Ig+4E/9oyB66UC5Mj9Xq3N//vcLf2WzgdTi/3gUu3Z9KoqmlrEG4VuuLK8wJHofxzdQXz/knhiYg==",
"dev": true,
- "peer": true,
"dependencies": {
"camelcase": "^6.3.0",
"map-obj": "^4.1.0",
@@ -3154,7 +3139,6 @@
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz",
"integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==",
"dev": true,
- "peer": true,
"engines": {
"node": ">=10"
},
@@ -3324,7 +3308,6 @@
"resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
"integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
"dev": true,
- "peer": true,
"dependencies": {
"string-width": "^4.2.0",
"strip-ansi": "^6.0.0",
@@ -3521,6 +3504,7 @@
"integrity": "sha512-ou/MQUDq4tcDJI2FsPaod2FZpex4kpIK43JJlcBgWrX8WX7R/05ZxGTuxedOuZBfxjZxja+fbijZGyxiLP6CFA==",
"dev": true,
"hasInstallScript": true,
+ "peer": true,
"dependencies": {
"@cypress/request": "^3.0.0",
"@cypress/xvfb": "^1.2.4",
@@ -3772,7 +3756,6 @@
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz",
"integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==",
"dev": true,
- "peer": true,
"engines": {
"node": ">=10"
},
@@ -3785,7 +3768,6 @@
"resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz",
"integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==",
"dev": true,
- "peer": true,
"dependencies": {
"decamelize": "^1.1.0",
"map-obj": "^1.0.0"
@@ -3802,7 +3784,6 @@
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
"integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==",
"dev": true,
- "peer": true,
"engines": {
"node": ">=0.10.0"
}
@@ -3812,7 +3793,6 @@
"resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
"integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==",
"dev": true,
- "peer": true,
"engines": {
"node": ">=0.10.0"
}
@@ -3997,6 +3977,7 @@
"resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz",
"integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==",
"dev": true,
+ "peer": true,
"dependencies": {
"ansi-colors": "^4.1.1",
"strip-ansi": "^6.0.1"
@@ -4268,6 +4249,7 @@
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz",
"integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==",
"dev": true,
+ "peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.6.1",
@@ -4365,6 +4347,7 @@
"resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz",
"integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==",
"dev": true,
+ "peer": true,
"bin": {
"eslint-config-prettier": "bin/cli.js"
},
@@ -4462,6 +4445,7 @@
"resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz",
"integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==",
"dev": true,
+ "peer": true,
"dependencies": {
"array-includes": "^3.1.7",
"array.prototype.findlastindex": "^1.2.3",
@@ -5209,7 +5193,6 @@
"resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
"integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==",
"dev": true,
- "peer": true,
"bin": {
"flat": "cli.js"
}
@@ -5564,7 +5547,6 @@
"integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==",
"deprecated": "Glob versions prior to v9 are no longer supported",
"dev": true,
- "peer": true,
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
@@ -5596,7 +5578,6 @@
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
"integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
"dev": true,
- "peer": true,
"dependencies": {
"brace-expansion": "^2.0.1"
},
@@ -5743,7 +5724,6 @@
"resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz",
"integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==",
"dev": true,
- "peer": true,
"engines": {
"node": ">=6"
}
@@ -5834,7 +5814,6 @@
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
"dev": true,
- "peer": true,
"bin": {
"he": "bin/he"
}
@@ -5844,7 +5823,6 @@
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz",
"integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==",
"dev": true,
- "peer": true,
"dependencies": {
"lru-cache": "^6.0.0"
},
@@ -5857,7 +5835,6 @@
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
"dev": true,
- "peer": true,
"dependencies": {
"yallist": "^4.0.0"
},
@@ -5869,8 +5846,16 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
- "dev": true,
- "peer": true
+ "dev": true
+ },
+ "node_modules/html-parse-stringify": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz",
+ "integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==",
+ "license": "MIT",
+ "dependencies": {
+ "void-elements": "3.1.0"
+ }
},
"node_modules/html-tags": {
"version": "3.3.1",
@@ -5907,6 +5892,38 @@
"node": ">=8.12.0"
}
},
+ "node_modules/i18next": {
+ "version": "25.8.14",
+ "resolved": "https://registry.npmjs.org/i18next/-/i18next-25.8.14.tgz",
+ "integrity": "sha512-paMUYkfWJMsWPeE/Hejcw+XLhHrQPehem+4wMo+uELnvIwvCG019L9sAIljwjCmEMtFQQO3YeitJY8Kctei3iA==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://locize.com"
+ },
+ {
+ "type": "individual",
+ "url": "https://locize.com/i18next.html"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project"
+ }
+ ],
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/runtime": "^7.28.4"
+ },
+ "peerDependencies": {
+ "typescript": "^5"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
"node_modules/ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
@@ -5963,7 +5980,6 @@
"resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz",
"integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==",
"dev": true,
- "peer": true,
"engines": {
"node": ">=8"
}
@@ -6338,7 +6354,6 @@
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
"integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
"dev": true,
- "peer": true,
"engines": {
"node": ">=8"
}
@@ -7079,7 +7094,6 @@
"resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz",
"integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==",
"dev": true,
- "peer": true,
"engines": {
"node": ">=8"
},
@@ -7178,7 +7192,6 @@
"resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz",
"integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==",
"dev": true,
- "peer": true,
"engines": {
"node": ">=4"
}
@@ -7212,7 +7225,6 @@
"resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz",
"integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==",
"dev": true,
- "peer": true,
"dependencies": {
"arrify": "^1.0.1",
"is-plain-obj": "^1.1.0",
@@ -7227,7 +7239,6 @@
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
"integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==",
"dev": true,
- "peer": true,
"engines": {
"node": ">=0.10.0"
}
@@ -7237,7 +7248,6 @@
"resolved": "https://registry.npmjs.org/mocha/-/mocha-10.6.0.tgz",
"integrity": "sha512-hxjt4+EEB0SA0ZDygSS015t65lJw/I2yRCS3Ae+SJ5FrbzrXgfYwJr96f0OvIXdj7h4lv/vLCrH3rkiuizFSvw==",
"dev": true,
- "peer": true,
"dependencies": {
"ansi-colors": "^4.1.3",
"browser-stdout": "^1.3.1",
@@ -7273,7 +7283,6 @@
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
"dev": true,
- "peer": true,
"engines": {
"node": ">=10"
},
@@ -7286,7 +7295,6 @@
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true,
- "peer": true,
"engines": {
"node": ">=8"
}
@@ -7296,7 +7304,6 @@
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
"integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
"dev": true,
- "peer": true,
"dependencies": {
"brace-expansion": "^2.0.1"
},
@@ -7308,15 +7315,13 @@
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
- "dev": true,
- "peer": true
+ "dev": true
},
"node_modules/mocha/node_modules/supports-color": {
"version": "8.1.1",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
"integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
"dev": true,
- "peer": true,
"dependencies": {
"has-flag": "^4.0.0"
},
@@ -7907,7 +7912,6 @@
"resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz",
"integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==",
"dev": true,
- "peer": true,
"dependencies": {
"hosted-git-info": "^4.0.1",
"is-core-module": "^2.5.0",
@@ -8452,6 +8456,7 @@
"url": "https://github.com/sponsors/ai"
}
],
+ "peer": true,
"dependencies": {
"nanoid": "^3.3.7",
"picocolors": "^1.0.1",
@@ -8530,6 +8535,7 @@
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.1.tgz",
"integrity": "sha512-b4dlw/9V8A71rLIDsSwVmak9z2DuBUB7CA1/wSdelNEzqsjoSPeADTWNO09lpH49Diy3/JIZ2bSPB1dI3LJCHg==",
"dev": true,
+ "peer": true,
"dependencies": {
"cssesc": "^3.0.0",
"util-deprecate": "^1.0.2"
@@ -8558,6 +8564,7 @@
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz",
"integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==",
"dev": true,
+ "peer": true,
"bin": {
"prettier": "bin/prettier.cjs"
},
@@ -8688,7 +8695,6 @@
"resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz",
"integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==",
"dev": true,
- "peer": true,
"engines": {
"node": ">=10"
},
@@ -8701,7 +8707,6 @@
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
"integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
"dev": true,
- "peer": true,
"dependencies": {
"safe-buffer": "^5.1.0"
}
@@ -8710,6 +8715,7 @@
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
+ "peer": true,
"dependencies": {
"loose-envify": "^1.1.0"
},
@@ -8721,6 +8727,7 @@
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
+ "peer": true,
"dependencies": {
"loose-envify": "^1.1.0",
"scheduler": "^0.23.2"
@@ -8729,6 +8736,33 @@
"react": "^18.3.1"
}
},
+ "node_modules/react-i18next": {
+ "version": "16.5.5",
+ "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-16.5.5.tgz",
+ "integrity": "sha512-5Z35e2JMALNR16FK/LDNQoAatQTVuO/4m4uHrIzewOPXIyf75gAHzuNLSWwmj5lRDJxDvXRJDECThkxWSAReng==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.28.4",
+ "html-parse-stringify": "^3.0.1",
+ "use-sync-external-store": "^1.6.0"
+ },
+ "peerDependencies": {
+ "i18next": ">= 25.6.2",
+ "react": ">= 16.8.0",
+ "typescript": "^5"
+ },
+ "peerDependenciesMeta": {
+ "react-dom": {
+ "optional": true
+ },
+ "react-native": {
+ "optional": true
+ },
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
"node_modules/react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
@@ -8793,7 +8827,6 @@
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-6.0.0.tgz",
"integrity": "sha512-X1Fu3dPuk/8ZLsMhEj5f4wFAF0DWoK7qhGJvgaijocXxBmSToKfbFtqbxMO7bVjNA1dmE5huAzjXj/ey86iw9Q==",
"dev": true,
- "peer": true,
"dependencies": {
"@types/normalize-package-data": "^2.4.0",
"normalize-package-data": "^3.0.2",
@@ -8812,7 +8845,6 @@
"resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-8.0.0.tgz",
"integrity": "sha512-snVCqPczksT0HS2EC+SxUndvSzn6LRCwpfSvLrIfR5BKDQQZMaI6jPRC9dYvYFDRAuFEAnkwww8kBBNE/3VvzQ==",
"dev": true,
- "peer": true,
"dependencies": {
"find-up": "^5.0.0",
"read-pkg": "^6.0.0",
@@ -8830,7 +8862,6 @@
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz",
"integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==",
"dev": true,
- "peer": true,
"engines": {
"node": ">=10"
},
@@ -8843,7 +8874,6 @@
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz",
"integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==",
"dev": true,
- "peer": true,
"engines": {
"node": ">=10"
},
@@ -8868,7 +8898,6 @@
"resolved": "https://registry.npmjs.org/redent/-/redent-4.0.0.tgz",
"integrity": "sha512-tYkDkVVtYkSVhuQ4zBgfvciymHaeuel+zFKXShfDnFP5SyVEP7qo70Rf1jTOTCx3vGNAbnEi/xFkcfQVMIBWag==",
"dev": true,
- "peer": true,
"dependencies": {
"indent-string": "^5.0.0",
"strip-indent": "^4.0.0"
@@ -8885,7 +8914,6 @@
"resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz",
"integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==",
"dev": true,
- "peer": true,
"engines": {
"node": ">=12"
},
@@ -8914,11 +8942,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/regenerator-runtime": {
- "version": "0.14.1",
- "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
- "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="
- },
"node_modules/regexp.prototype.flags": {
"version": "1.5.2",
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz",
@@ -9223,6 +9246,7 @@
"resolved": "https://registry.npmjs.org/sass/-/sass-1.77.8.tgz",
"integrity": "sha512-4UHg6prsrycW20fqLGPShtEvo/WyHRVRHwOP4DzkUrObWoWI05QBSfzU71TVB7PFaL104TwNaHpjlWXAZbQiNQ==",
"dev": true,
+ "peer": true,
"dependencies": {
"chokidar": ">=3.0.0 <4.0.0",
"immutable": "^4.0.0",
@@ -9260,7 +9284,6 @@
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz",
"integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==",
"dev": true,
- "peer": true,
"dependencies": {
"randombytes": "^2.1.0"
}
@@ -9467,7 +9490,6 @@
"resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz",
"integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==",
"dev": true,
- "peer": true,
"dependencies": {
"spdx-expression-parse": "^3.0.0",
"spdx-license-ids": "^3.0.0"
@@ -9477,15 +9499,13 @@
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz",
"integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==",
- "dev": true,
- "peer": true
+ "dev": true
},
"node_modules/spdx-expression-parse": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
"integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
"dev": true,
- "peer": true,
"dependencies": {
"spdx-exceptions": "^2.1.0",
"spdx-license-ids": "^3.0.0"
@@ -9495,8 +9515,7 @@
"version": "3.0.18",
"resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.18.tgz",
"integrity": "sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ==",
- "dev": true,
- "peer": true
+ "dev": true
},
"node_modules/sshpk": {
"version": "1.18.0",
@@ -9694,7 +9713,6 @@
"resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-4.0.0.tgz",
"integrity": "sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==",
"dev": true,
- "peer": true,
"dependencies": {
"min-indent": "^1.0.1"
},
@@ -9733,8 +9751,7 @@
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz",
"integrity": "sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==",
- "dev": true,
- "peer": true
+ "dev": true
},
"node_modules/stylelint": {
"version": "16.7.0",
@@ -10144,7 +10161,6 @@
"resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-4.1.1.tgz",
"integrity": "sha512-jRKj0n0jXWo6kh62nA5TEh3+4igKDXLvzBJcPpiizP7oOolUrYIxmVBG9TOtHYFHoddUk6YvAkGeGoSVTXfQXQ==",
"dev": true,
- "peer": true,
"engines": {
"node": ">=12"
},
@@ -10334,7 +10350,8 @@
"version": "5.5.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz",
"integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==",
- "dev": true,
+ "devOptional": true,
+ "peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@@ -10368,8 +10385,7 @@
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.2.tgz",
"integrity": "sha512-0JCqzSKnStlRRQfCdowvqy3cy0Dvtlb8xecj/H8JFZuCze4rwjPZQOgvFvn0Ws/usCHQFGpyr+pB9adaGwXn4Q==",
- "dev": true,
- "peer": true
+ "dev": true
},
"node_modules/universalify": {
"version": "2.0.1",
@@ -10438,6 +10454,15 @@
"requires-port": "^1.0.0"
}
},
+ "node_modules/use-sync-external-store": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz",
+ "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
@@ -10458,7 +10483,6 @@
"resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
"integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
"dev": true,
- "peer": true,
"dependencies": {
"spdx-correct": "^3.0.0",
"spdx-expression-parse": "^3.0.0"
@@ -10492,6 +10516,7 @@
"resolved": "https://registry.npmjs.org/vite/-/vite-5.3.3.tgz",
"integrity": "sha512-NPQdeCU0Dv2z5fu+ULotpuq5yfCS1BzKUIPhNbP3YBfAMGJXbt2nS+sbTFu+qchaqWTD+H3JK++nRwr6XIcp6A==",
"dev": true,
+ "peer": true,
"dependencies": {
"esbuild": "^0.21.3",
"postcss": "^8.4.39",
@@ -10542,6 +10567,15 @@
}
}
},
+ "node_modules/void-elements": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz",
+ "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
@@ -10804,8 +10838,7 @@
"version": "6.5.1",
"resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz",
"integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==",
- "dev": true,
- "peer": true
+ "dev": true
},
"node_modules/wrap-ansi": {
"version": "7.0.0",
@@ -10908,7 +10941,6 @@
"resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
"integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
"dev": true,
- "peer": true,
"dependencies": {
"cliui": "^7.0.2",
"escalade": "^3.1.1",
@@ -10927,7 +10959,6 @@
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz",
"integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==",
"dev": true,
- "peer": true,
"engines": {
"node": ">=10"
}
@@ -10937,7 +10968,6 @@
"resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz",
"integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==",
"dev": true,
- "peer": true,
"dependencies": {
"camelcase": "^6.0.0",
"decamelize": "^4.0.0",
diff --git a/package.json b/package.json
index ae251685c8b..23241cee1d7 100644
--- a/package.json
+++ b/package.json
@@ -9,14 +9,16 @@
"@fortawesome/fontawesome-free": "^6.5.2",
"bulma": "^1.0.1",
"classnames": "^2.5.1",
+ "i18next": "^25.8.14",
"react": "^18.3.1",
"react-dom": "^18.3.1",
+ "react-i18next": "^16.5.5",
"react-router-dom": "^6.25.1",
"react-transition-group": "^4.4.5"
},
"devDependencies": {
"@cypress/react18": "^2.0.1",
- "@mate-academy/scripts": "^1.8.5",
+ "@mate-academy/scripts": "^2.1.3",
"@mate-academy/students-ts-config": "*",
"@mate-academy/stylelint-config": "*",
"@types/node": "^20.14.10",
diff --git a/public/api/accessories.json b/public/api/accessories.json
index 6a36890cec7..7d7c430b024 100644
--- a/public/api/accessories.json
+++ b/public/api/accessories.json
@@ -4,11 +4,18 @@
"category": "accessories",
"namespaceId": "apple-watch-series-3",
"name": "Apple Watch Series 3 38mm Space Gray",
- "capacityAvailable": ["38mm", "42mm"],
+ "capacityAvailable": [
+ "38mm",
+ "42mm"
+ ],
"capacity": "38mm",
"priceRegular": 199,
"priceDiscount": 169,
- "colorsAvailable": ["space gray", "silver", "gold"],
+ "colorsAvailable": [
+ "space gray",
+ "silver",
+ "gold"
+ ],
"color": "space gray",
"images": [
"img/accessories/apple-watch-series-3/space-gray/00.webp",
@@ -39,18 +46,29 @@
"resolution": "272x340",
"processor": "Apple S3",
"ram": "768MB",
- "cell": ["Wi-Fi", "Bluetooth", "LTE"]
+ "cell": [
+ "Wi-Fi",
+ "Bluetooth",
+ "LTE"
+ ]
},
{
"id": "apple-watch-series-3-42mm-space-gray",
"category": "accessories",
"namespaceId": "apple-watch-series-3",
"name": "Apple Watch Series 3 42mm Space Gray",
- "capacityAvailable": ["38mm", "42mm"],
+ "capacityAvailable": [
+ "38mm",
+ "42mm"
+ ],
"capacity": "42mm",
"priceRegular": 250,
"priceDiscount": 219,
- "colorsAvailable": ["space gray", "silver", "gold"],
+ "colorsAvailable": [
+ "space gray",
+ "silver",
+ "gold"
+ ],
"color": "space gray",
"images": [
"img/accessories/apple-watch-series-3/space-gray/00.webp",
@@ -81,18 +99,29 @@
"resolution": "272x340",
"processor": "Apple S3",
"ram": "768MB",
- "cell": ["Wi-Fi", "Bluetooth", "LTE"]
+ "cell": [
+ "Wi-Fi",
+ "Bluetooth",
+ "LTE"
+ ]
},
{
"id": "apple-watch-series-3-38mm-gold",
"category": "accessories",
"namespaceId": "apple-watch-series-3",
"name": "Apple Watch Series 3 38mm Gold",
- "capacityAvailable": ["38mm", "42mm"],
+ "capacityAvailable": [
+ "38mm",
+ "42mm"
+ ],
"capacity": "38mm",
"priceRegular": 199,
"priceDiscount": 169,
- "colorsAvailable": ["space gray", "silver", "gold"],
+ "colorsAvailable": [
+ "space gray",
+ "silver",
+ "gold"
+ ],
"color": "gold",
"images": [
"img/accessories/apple-watch-series-3/gold/00.webp",
@@ -123,18 +152,29 @@
"resolution": "272x340",
"processor": "Apple S3",
"ram": "768MB",
- "cell": ["Wi-Fi", "Bluetooth", "LTE"]
+ "cell": [
+ "Wi-Fi",
+ "Bluetooth",
+ "LTE"
+ ]
},
{
"id": "apple-watch-series-3-42mm-gold",
"category": "accessories",
"namespaceId": "apple-watch-series-3",
"name": "Apple Watch Series 3 42mm Gold",
- "capacityAvailable": ["38mm", "42mm"],
+ "capacityAvailable": [
+ "38mm",
+ "42mm"
+ ],
"capacity": "42mm",
"priceRegular": 250,
"priceDiscount": 219,
- "colorsAvailable": ["space gray", "silver", "gold"],
+ "colorsAvailable": [
+ "space gray",
+ "silver",
+ "gold"
+ ],
"color": "gold",
"images": [
"img/accessories/apple-watch-series-3/gold/00.webp",
@@ -165,18 +205,29 @@
"resolution": "272x340",
"processor": "Apple S3",
"ram": "768MB",
- "cell": ["Wi-Fi", "Bluetooth", "LTE"]
+ "cell": [
+ "Wi-Fi",
+ "Bluetooth",
+ "LTE"
+ ]
},
{
"id": "apple-watch-series-3-38mm-silver",
"category": "accessories",
"namespaceId": "apple-watch-series-3",
"name": "Apple Watch Series 3 38mm Silver",
- "capacityAvailable": ["38mm", "42mm"],
+ "capacityAvailable": [
+ "38mm",
+ "42mm"
+ ],
"capacity": "38mm",
"priceRegular": 199,
"priceDiscount": 169,
- "colorsAvailable": ["space gray", "silver", "gold"],
+ "colorsAvailable": [
+ "space gray",
+ "silver",
+ "gold"
+ ],
"color": "silver",
"images": [
"img/accessories/apple-watch-series-3/silver/00.webp",
@@ -207,18 +258,29 @@
"resolution": "272x340",
"processor": "Apple S3",
"ram": "768MB",
- "cell": ["Wi-Fi", "Bluetooth", "LTE"]
+ "cell": [
+ "Wi-Fi",
+ "Bluetooth",
+ "LTE"
+ ]
},
{
"id": "apple-watch-series-3-42mm-silver",
"category": "accessories",
"namespaceId": "apple-watch-series-3",
"name": "Apple Watch Series 3 42mm Silver",
- "capacityAvailable": ["38mm", "42mm"],
+ "capacityAvailable": [
+ "38mm",
+ "42mm"
+ ],
"capacity": "42mm",
"priceRegular": 250,
"priceDiscount": 219,
- "colorsAvailable": ["space gray", "silver", "gold"],
+ "colorsAvailable": [
+ "space gray",
+ "silver",
+ "gold"
+ ],
"color": "silver",
"images": [
"img/accessories/apple-watch-series-3/silver/00.webp",
@@ -249,18 +311,31 @@
"resolution": "272x340",
"processor": "Apple S3",
"ram": "768MB",
- "cell": ["Wi-Fi", "Bluetooth", "LTE"]
+ "cell": [
+ "Wi-Fi",
+ "Bluetooth",
+ "LTE"
+ ]
},
{
"id": "apple-watch-series-6-40mm-space-gray",
"category": "accessories",
"namespaceId": "apple-watch-series-6",
"name": "Apple Watch Series 6 40mm Space Gray",
- "capacityAvailable": ["40mm", "44mm"],
+ "capacityAvailable": [
+ "40mm",
+ "44mm"
+ ],
"capacity": "40mm",
"priceRegular": 399,
"priceDiscount": 329,
- "colorsAvailable": ["space gray", "silver", "gold", "blue", "red"],
+ "colorsAvailable": [
+ "space gray",
+ "silver",
+ "gold",
+ "blue",
+ "red"
+ ],
"color": "space gray",
"images": [
"img/accessories/apple-watch-series-6/space-gray/00.webp",
@@ -291,18 +366,31 @@
"resolution": "324x394",
"processor": "Apple S6",
"ram": "1GB",
- "cell": ["Wi-Fi", "Bluetooth", "LTE"]
+ "cell": [
+ "Wi-Fi",
+ "Bluetooth",
+ "LTE"
+ ]
},
{
"id": "apple-watch-series-6-44mm-space-gray",
"category": "accessories",
"namespaceId": "apple-watch-series-6",
"name": "Apple Watch Series 6 44mm Space Gray",
- "capacityAvailable": ["40mm", "44mm"],
+ "capacityAvailable": [
+ "40mm",
+ "44mm"
+ ],
"capacity": "44mm",
"priceRegular": 429,
"priceDiscount": 359,
- "colorsAvailable": ["space gray", "silver", "gold", "blue", "red"],
+ "colorsAvailable": [
+ "space gray",
+ "silver",
+ "gold",
+ "blue",
+ "red"
+ ],
"color": "space gray",
"images": [
"img/accessories/apple-watch-series-6/space-gray/00.webp",
@@ -333,18 +421,31 @@
"resolution": "324x394",
"processor": "Apple S6",
"ram": "1GB",
- "cell": ["Wi-Fi", "Bluetooth", "LTE"]
+ "cell": [
+ "Wi-Fi",
+ "Bluetooth",
+ "LTE"
+ ]
},
{
"id": "apple-watch-series-6-40mm-silver",
"category": "accessories",
"namespaceId": "apple-watch-series-6",
"name": "Apple Watch Series 6 40mm Silver",
- "capacityAvailable": ["40mm", "44mm"],
+ "capacityAvailable": [
+ "40mm",
+ "44mm"
+ ],
"capacity": "40mm",
"priceRegular": 399,
"priceDiscount": 329,
- "colorsAvailable": ["space gray", "silver", "gold", "blue", "red"],
+ "colorsAvailable": [
+ "space gray",
+ "silver",
+ "gold",
+ "blue",
+ "red"
+ ],
"color": "silver",
"images": [
"img/accessories/apple-watch-series-6/silver/00.webp",
@@ -375,18 +476,31 @@
"resolution": "324x394",
"processor": "Apple S6",
"ram": "1GB",
- "cell": ["Wi-Fi", "Bluetooth", "LTE"]
+ "cell": [
+ "Wi-Fi",
+ "Bluetooth",
+ "LTE"
+ ]
},
{
"id": "apple-watch-series-6-44mm-silver",
"category": "accessories",
"namespaceId": "apple-watch-series-6",
"name": "Apple Watch Series 6 44mm Silver",
- "capacityAvailable": ["40mm", "44mm"],
+ "capacityAvailable": [
+ "40mm",
+ "44mm"
+ ],
"capacity": "44mm",
"priceRegular": 429,
"priceDiscount": 359,
- "colorsAvailable": ["space gray", "silver", "gold", "blue", "red"],
+ "colorsAvailable": [
+ "space gray",
+ "silver",
+ "gold",
+ "blue",
+ "red"
+ ],
"color": "silver",
"images": [
"img/accessories/apple-watch-series-6/silver/00.webp",
@@ -417,18 +531,31 @@
"resolution": "324x394",
"processor": "Apple S6",
"ram": "1GB",
- "cell": ["Wi-Fi", "Bluetooth", "LTE"]
+ "cell": [
+ "Wi-Fi",
+ "Bluetooth",
+ "LTE"
+ ]
},
{
"id": "apple-watch-series-6-40mm-gold",
"category": "accessories",
"namespaceId": "apple-watch-series-6",
"name": "Apple Watch Series 6 40mm Gold",
- "capacityAvailable": ["40mm", "44mm"],
+ "capacityAvailable": [
+ "40mm",
+ "44mm"
+ ],
"capacity": "40mm",
"priceRegular": 399,
"priceDiscount": 329,
- "colorsAvailable": ["space gray", "silver", "gold", "blue", "red"],
+ "colorsAvailable": [
+ "space gray",
+ "silver",
+ "gold",
+ "blue",
+ "red"
+ ],
"color": "gold",
"images": [
"img/accessories/apple-watch-series-6/gold/00.webp",
@@ -459,18 +586,31 @@
"resolution": "324x394",
"processor": "Apple S6",
"ram": "1GB",
- "cell": ["Wi-Fi", "Bluetooth", "LTE"]
+ "cell": [
+ "Wi-Fi",
+ "Bluetooth",
+ "LTE"
+ ]
},
{
"id": "apple-watch-series-6-44mm-gold",
"category": "accessories",
"namespaceId": "apple-watch-series-6",
"name": "Apple Watch Series 6 44mm Gold",
- "capacityAvailable": ["40mm", "44mm"],
+ "capacityAvailable": [
+ "40mm",
+ "44mm"
+ ],
"capacity": "44mm",
"priceRegular": 429,
"priceDiscount": 359,
- "colorsAvailable": ["space gray", "silver", "gold", "blue", "red"],
+ "colorsAvailable": [
+ "space gray",
+ "silver",
+ "gold",
+ "blue",
+ "red"
+ ],
"color": "gold",
"images": [
"img/accessories/apple-watch-series-6/gold/00.webp",
@@ -501,18 +641,31 @@
"resolution": "324x394",
"processor": "Apple S6",
"ram": "1GB",
- "cell": ["Wi-Fi", "Bluetooth", "LTE"]
+ "cell": [
+ "Wi-Fi",
+ "Bluetooth",
+ "LTE"
+ ]
},
{
"id": "apple-watch-series-6-40mm-blue",
"category": "accessories",
"namespaceId": "apple-watch-series-6",
"name": "Apple Watch Series 6 40mm Blue",
- "capacityAvailable": ["40mm", "44mm"],
+ "capacityAvailable": [
+ "40mm",
+ "44mm"
+ ],
"capacity": "40mm",
"priceRegular": 399,
"priceDiscount": 329,
- "colorsAvailable": ["space gray", "silver", "gold", "blue", "red"],
+ "colorsAvailable": [
+ "space gray",
+ "silver",
+ "gold",
+ "blue",
+ "red"
+ ],
"color": "blue",
"images": [
"img/accessories/apple-watch-series-6/blue/00.webp",
@@ -543,18 +696,31 @@
"resolution": "324x394",
"processor": "Apple S6",
"ram": "1GB",
- "cell": ["Wi-Fi", "Bluetooth", "LTE"]
+ "cell": [
+ "Wi-Fi",
+ "Bluetooth",
+ "LTE"
+ ]
},
{
"id": "apple-watch-series-6-44mm-blue",
"category": "accessories",
"namespaceId": "apple-watch-series-6",
"name": "Apple Watch Series 6 44mm Blue",
- "capacityAvailable": ["40mm", "44mm"],
+ "capacityAvailable": [
+ "40mm",
+ "44mm"
+ ],
"capacity": "44mm",
"priceRegular": 429,
"priceDiscount": 359,
- "colorsAvailable": ["space gray", "silver", "gold", "blue", "red"],
+ "colorsAvailable": [
+ "space gray",
+ "silver",
+ "gold",
+ "blue",
+ "red"
+ ],
"color": "blue",
"images": [
"img/accessories/apple-watch-series-6/blue/00.webp",
@@ -585,18 +751,31 @@
"resolution": "324x394",
"processor": "Apple S6",
"ram": "1GB",
- "cell": ["Wi-Fi", "Bluetooth", "LTE"]
+ "cell": [
+ "Wi-Fi",
+ "Bluetooth",
+ "LTE"
+ ]
},
{
"id": "apple-watch-series-6-40mm-red",
"category": "accessories",
"namespaceId": "apple-watch-series-6",
"name": "Apple Watch Series 6 40mm Red",
- "capacityAvailable": ["40mm", "44mm"],
+ "capacityAvailable": [
+ "40mm",
+ "44mm"
+ ],
"capacity": "40mm",
"priceRegular": 399,
"priceDiscount": 329,
- "colorsAvailable": ["space gray", "silver", "gold", "blue", "red"],
+ "colorsAvailable": [
+ "space gray",
+ "silver",
+ "gold",
+ "blue",
+ "red"
+ ],
"color": "red",
"images": [
"img/accessories/apple-watch-series-6/red/00.webp",
@@ -627,18 +806,31 @@
"resolution": "324x394",
"processor": "Apple S6",
"ram": "1GB",
- "cell": ["Wi-Fi", "Bluetooth", "LTE"]
+ "cell": [
+ "Wi-Fi",
+ "Bluetooth",
+ "LTE"
+ ]
},
{
"id": "apple-watch-series-6-44mm-red",
"category": "accessories",
"namespaceId": "apple-watch-series-6",
"name": "Apple Watch Series 6 44mm Red",
- "capacityAvailable": ["40mm", "44mm"],
+ "capacityAvailable": [
+ "40mm",
+ "44mm"
+ ],
"capacity": "44mm",
"priceRegular": 429,
"priceDiscount": 359,
- "colorsAvailable": ["space gray", "silver", "gold", "blue", "red"],
+ "colorsAvailable": [
+ "space gray",
+ "silver",
+ "gold",
+ "blue",
+ "red"
+ ],
"color": "red",
"images": [
"img/accessories/apple-watch-series-6/red/00.webp",
@@ -669,18 +861,29 @@
"resolution": "324x394",
"processor": "Apple S6",
"ram": "1GB",
- "cell": ["Wi-Fi", "Bluetooth", "LTE"]
+ "cell": [
+ "Wi-Fi",
+ "Bluetooth",
+ "LTE"
+ ]
},
{
"id": "apple-watch-series-5-40mm-silver",
"category": "accessories",
"namespaceId": "apple-watch-series-5",
"name": "Apple Watch Series 5 40mm Silver",
- "capacityAvailable": ["40mm", "44mm"],
+ "capacityAvailable": [
+ "40mm",
+ "44mm"
+ ],
"capacity": "40mm",
"priceRegular": 399,
"priceDiscount": 299,
- "colorsAvailable": ["silver", "gold", "space gray"],
+ "colorsAvailable": [
+ "silver",
+ "gold",
+ "space gray"
+ ],
"color": "silver",
"images": [
"img/accessories/apple-watch-series-5/silver/00.webp",
@@ -711,18 +914,29 @@
"resolution": "324x394",
"processor": "Apple S5",
"ram": "1GB",
- "cell": ["Wi-Fi", "Bluetooth", "LTE"]
+ "cell": [
+ "Wi-Fi",
+ "Bluetooth",
+ "LTE"
+ ]
},
{
"id": "apple-watch-series-5-44mm-silver",
"category": "accessories",
"namespaceId": "apple-watch-series-5",
"name": "Apple Watch Series 5 44mm Silver",
- "capacityAvailable": ["40mm", "44mm"],
+ "capacityAvailable": [
+ "40mm",
+ "44mm"
+ ],
"capacity": "44mm",
"priceRegular": 429,
"priceDiscount": 399,
- "colorsAvailable": ["space gray", "silver", "gold"],
+ "colorsAvailable": [
+ "space gray",
+ "silver",
+ "gold"
+ ],
"color": "silver",
"images": [
"img/accessories/apple-watch-series-5/silver/00.webp",
@@ -753,18 +967,29 @@
"resolution": "368x448",
"processor": "Apple S5",
"ram": "1GB",
- "cell": ["Wi-Fi", "Bluetooth", "LTE"]
+ "cell": [
+ "Wi-Fi",
+ "Bluetooth",
+ "LTE"
+ ]
},
{
"id": "apple-watch-series-5-40mm-gold",
"category": "accessories",
"namespaceId": "apple-watch-series-5",
"name": "Apple Watch Series 5 40mm Gold",
- "capacityAvailable": ["40mm", "44mm"],
+ "capacityAvailable": [
+ "40mm",
+ "44mm"
+ ],
"capacity": "40mm",
"priceRegular": 399,
"priceDiscount": 299,
- "colorsAvailable": ["silver", "gold", "space gray"],
+ "colorsAvailable": [
+ "silver",
+ "gold",
+ "space gray"
+ ],
"color": "gold",
"images": [
"img/accessories/apple-watch-series-5/gold/00.webp",
@@ -795,18 +1020,29 @@
"resolution": "324x394",
"processor": "Apple S5",
"ram": "1GB",
- "cell": ["Wi-Fi", "Bluetooth", "LTE"]
+ "cell": [
+ "Wi-Fi",
+ "Bluetooth",
+ "LTE"
+ ]
},
{
"id": "apple-watch-series-5-44mm-gold",
"category": "accessories",
"namespaceId": "apple-watch-series-5",
"name": "Apple Watch Series 5 44mm Gold",
- "capacityAvailable": ["40mm", "44mm"],
+ "capacityAvailable": [
+ "40mm",
+ "44mm"
+ ],
"capacity": "44mm",
"priceRegular": 429,
"priceDiscount": 399,
- "colorsAvailable": ["space gray", "silver", "gold"],
+ "colorsAvailable": [
+ "space gray",
+ "silver",
+ "gold"
+ ],
"color": "gold",
"images": [
"img/accessories/apple-watch-series-5/gold/00.webp",
@@ -837,18 +1073,29 @@
"resolution": "368x448",
"processor": "Apple S5",
"ram": "1GB",
- "cell": ["Wi-Fi", "Bluetooth", "LTE"]
+ "cell": [
+ "Wi-Fi",
+ "Bluetooth",
+ "LTE"
+ ]
},
{
"id": "apple-watch-series-5-40mm-space-gray",
"category": "accessories",
"namespaceId": "apple-watch-series-5",
"name": "Apple Watch Series 5 40mm Space Gray",
- "capacityAvailable": ["40mm", "44mm"],
+ "capacityAvailable": [
+ "40mm",
+ "44mm"
+ ],
"capacity": "40mm",
"priceRegular": 399,
"priceDiscount": 299,
- "colorsAvailable": ["silver", "gold", "space gray"],
+ "colorsAvailable": [
+ "silver",
+ "gold",
+ "space gray"
+ ],
"color": "space-gray",
"images": [
"img/accessories/apple-watch-series-5/space-gray/00.webp",
@@ -879,18 +1126,29 @@
"resolution": "324x394",
"processor": "Apple S5",
"ram": "1GB",
- "cell": ["Wi-Fi", "Bluetooth", "LTE"]
+ "cell": [
+ "Wi-Fi",
+ "Bluetooth",
+ "LTE"
+ ]
},
{
"id": "apple-watch-series-5-44mm-space-gray",
"category": "accessories",
"namespaceId": "apple-watch-series-5",
"name": "Apple Watch Series 5 44mm Space Gray",
- "capacityAvailable": ["40mm", "44mm"],
+ "capacityAvailable": [
+ "40mm",
+ "44mm"
+ ],
"capacity": "44mm",
"priceRegular": 429,
"priceDiscount": 399,
- "colorsAvailable": ["space gray", "silver", "gold"],
+ "colorsAvailable": [
+ "space gray",
+ "silver",
+ "gold"
+ ],
"color": "space-gray",
"images": [
"img/accessories/apple-watch-series-5/space-gray/00.webp",
@@ -921,18 +1179,29 @@
"resolution": "368x448",
"processor": "Apple S5",
"ram": "1GB",
- "cell": ["Wi-Fi", "Bluetooth", "LTE"]
+ "cell": [
+ "Wi-Fi",
+ "Bluetooth",
+ "LTE"
+ ]
},
{
"id": "apple-watch-series-4-40mm-silver",
"category": "accessories",
"namespaceId": "apple-watch-series-4",
"name": "Apple Watch Series 4 40mm Silver",
- "capacityAvailable": ["40mm", "44mm"],
+ "capacityAvailable": [
+ "40mm",
+ "44mm"
+ ],
"capacity": "40mm",
"priceRegular": 399,
"priceDiscount": 349,
- "colorsAvailable": ["silver", "gold", "space gray"],
+ "colorsAvailable": [
+ "silver",
+ "gold",
+ "space gray"
+ ],
"color": "silver",
"images": [
"img/accessories/apple-watch-series-4/silver/00.webp",
@@ -963,18 +1232,29 @@
"resolution": "324x394",
"processor": "Apple S4",
"ram": "0.75GB",
- "cell": ["Wi-Fi", "Bluetooth", "LTE"]
+ "cell": [
+ "Wi-Fi",
+ "Bluetooth",
+ "LTE"
+ ]
},
{
"id": "apple-watch-series-4-44mm-silver",
"category": "accessories",
"namespaceId": "apple-watch-series-4",
"name": "Apple Watch Series 4 44mm Silver",
- "capacityAvailable": ["40mm", "44mm"],
+ "capacityAvailable": [
+ "40mm",
+ "44mm"
+ ],
"capacity": "44mm",
"priceRegular": 429,
"priceDiscount": 379,
- "colorsAvailable": ["silver", "gold", "space gray"],
+ "colorsAvailable": [
+ "silver",
+ "gold",
+ "space gray"
+ ],
"color": "silver",
"images": [
"img/accessories/apple-watch-series-4/silver/00.webp",
@@ -1005,18 +1285,29 @@
"resolution": "368x448",
"processor": "Apple S4",
"ram": "0.75GB",
- "cell": ["Wi-Fi", "Bluetooth", "LTE"]
+ "cell": [
+ "Wi-Fi",
+ "Bluetooth",
+ "LTE"
+ ]
},
{
"id": "apple-watch-series-4-40mm-gold",
"category": "accessories",
"namespaceId": "apple-watch-series-4",
"name": "Apple Watch Series 4 40mm Gold",
- "capacityAvailable": ["40mm", "44mm"],
+ "capacityAvailable": [
+ "40mm",
+ "44mm"
+ ],
"capacity": "40mm",
"priceRegular": 399,
"priceDiscount": 349,
- "colorsAvailable": ["silver", "gold", "space gray"],
+ "colorsAvailable": [
+ "silver",
+ "gold",
+ "space gray"
+ ],
"color": "gold",
"images": [
"img/accessories/apple-watch-series-4/gold/00.webp",
@@ -1047,18 +1338,29 @@
"resolution": "324x394",
"processor": "Apple S4",
"ram": "0.75GB",
- "cell": ["Wi-Fi", "Bluetooth", "LTE"]
+ "cell": [
+ "Wi-Fi",
+ "Bluetooth",
+ "LTE"
+ ]
},
{
"id": "apple-watch-series-4-44mm-gold",
"category": "accessories",
"namespaceId": "apple-watch-series-4",
"name": "Apple Watch Series 4 44mm Gold",
- "capacityAvailable": ["40mm", "44mm"],
+ "capacityAvailable": [
+ "40mm",
+ "44mm"
+ ],
"capacity": "44mm",
"priceRegular": 429,
"priceDiscount": 379,
- "colorsAvailable": ["silver", "gold", "space gray"],
+ "colorsAvailable": [
+ "silver",
+ "gold",
+ "space gray"
+ ],
"color": "gold",
"images": [
"img/accessories/apple-watch-series-4/gold/00.webp",
@@ -1089,18 +1391,29 @@
"resolution": "368x448",
"processor": "Apple S4",
"ram": "0.75GB",
- "cell": ["Wi-Fi", "Bluetooth", "LTE"]
+ "cell": [
+ "Wi-Fi",
+ "Bluetooth",
+ "LTE"
+ ]
},
{
"id": "apple-watch-series-4-40mm-space-gray",
"category": "accessories",
"namespaceId": "apple-watch-series-4",
"name": "Apple Watch Series 4 40mm Space Gray",
- "capacityAvailable": ["40mm", "44mm"],
+ "capacityAvailable": [
+ "40mm",
+ "44mm"
+ ],
"capacity": "40mm",
"priceRegular": 399,
"priceDiscount": 349,
- "colorsAvailable": ["silver", "gold", "space gray"],
+ "colorsAvailable": [
+ "silver",
+ "gold",
+ "space gray"
+ ],
"color": "space-gray",
"images": [
"img/accessories/apple-watch-series-4/space-gray/00.webp",
@@ -1131,18 +1444,29 @@
"resolution": "324x394",
"processor": "Apple S4",
"ram": "0.75GB",
- "cell": ["Wi-Fi", "Bluetooth", "LTE"]
+ "cell": [
+ "Wi-Fi",
+ "Bluetooth",
+ "LTE"
+ ]
},
{
"id": "apple-watch-series-4-44mm-space-gray",
"category": "accessories",
"namespaceId": "apple-watch-series-4",
"name": "Apple Watch Series 4 44mm Space Gray",
- "capacityAvailable": ["40mm", "44mm"],
+ "capacityAvailable": [
+ "40mm",
+ "44mm"
+ ],
"capacity": "44mm",
"priceRegular": 429,
"priceDiscount": 379,
- "colorsAvailable": ["silver", "gold", "space gray"],
+ "colorsAvailable": [
+ "silver",
+ "gold",
+ "space gray"
+ ],
"color": "space-gray",
"images": [
"img/accessories/apple-watch-series-4/space-gray/00.webp",
@@ -1173,18 +1497,29 @@
"resolution": "368x448",
"processor": "Apple S4",
"ram": "0.75GB",
- "cell": ["Wi-Fi", "Bluetooth", "LTE"]
+ "cell": [
+ "Wi-Fi",
+ "Bluetooth",
+ "LTE"
+ ]
},
{
"id": "apple-watch-se-40mm-silver",
"category": "accessories",
"namespaceId": "apple-watch-se",
"name": "Apple Watch SE 40mm Silver",
- "capacityAvailable": ["40mm", "44mm"],
+ "capacityAvailable": [
+ "40mm",
+ "44mm"
+ ],
"capacity": "40mm",
"priceRegular": 279,
"priceDiscount": 249,
- "colorsAvailable": ["silver", "gold", "space gray"],
+ "colorsAvailable": [
+ "silver",
+ "gold",
+ "space gray"
+ ],
"color": "silver",
"images": [
"img/accessories/apple-watch-se/silver/00.webp",
@@ -1215,18 +1550,29 @@
"resolution": "324x394",
"processor": "Apple S5",
"ram": "1GB",
- "cell": ["Wi-Fi", "Bluetooth", "LTE"]
+ "cell": [
+ "Wi-Fi",
+ "Bluetooth",
+ "LTE"
+ ]
},
{
"id": "apple-watch-se-44mm-silver",
"category": "accessories",
"namespaceId": "apple-watch-se",
"name": "Apple Watch SE 44mm Silver",
- "capacityAvailable": ["40mm", "44mm"],
+ "capacityAvailable": [
+ "40mm",
+ "44mm"
+ ],
"capacity": "44mm",
"priceRegular": 309,
"priceDiscount": 279,
- "colorsAvailable": ["silver", "gold", "space gray"],
+ "colorsAvailable": [
+ "silver",
+ "gold",
+ "space gray"
+ ],
"color": "silver",
"images": [
"img/accessories/apple-watch-se/silver/00.webp",
@@ -1257,18 +1603,29 @@
"resolution": "368x448",
"processor": "Apple S5",
"ram": "1GB",
- "cell": ["Wi-Fi", "Bluetooth", "LTE"]
+ "cell": [
+ "Wi-Fi",
+ "Bluetooth",
+ "LTE"
+ ]
},
{
"id": "apple-watch-se-40mm-gold",
"category": "accessories",
"namespaceId": "apple-watch-se",
"name": "Apple Watch SE 40mm Gold",
- "capacityAvailable": ["40mm", "44mm"],
+ "capacityAvailable": [
+ "40mm",
+ "44mm"
+ ],
"capacity": "40mm",
"priceRegular": 279,
"priceDiscount": 259,
- "colorsAvailable": ["silver", "space gray", "gold"],
+ "colorsAvailable": [
+ "silver",
+ "space gray",
+ "gold"
+ ],
"color": "gold",
"images": [
"img/accessories/apple-watch-se/gold/00.webp",
@@ -1299,18 +1656,29 @@
"resolution": "324x394",
"processor": "Apple S5",
"ram": "1GB",
- "cell": ["Wi-Fi", "Bluetooth", "LTE"]
+ "cell": [
+ "Wi-Fi",
+ "Bluetooth",
+ "LTE"
+ ]
},
{
"id": "apple-watch-se-44mm-gold",
"category": "accessories",
"namespaceId": "apple-watch-se",
"name": "Apple Watch SE 44mm Gold",
- "capacityAvailable": ["40mm", "44mm"],
+ "capacityAvailable": [
+ "40mm",
+ "44mm"
+ ],
"capacity": "44mm",
"priceRegular": 309,
"priceDiscount": 289,
- "colorsAvailable": ["space gray", "silver", "gold"],
+ "colorsAvailable": [
+ "space gray",
+ "silver",
+ "gold"
+ ],
"color": "gold",
"images": [
"img/accessories/apple-watch-se/gold/00.webp",
@@ -1341,18 +1709,29 @@
"resolution": "368x448",
"processor": "Apple S5",
"ram": "1GB",
- "cell": ["Wi-Fi", "Bluetooth", "LTE"]
+ "cell": [
+ "Wi-Fi",
+ "Bluetooth",
+ "LTE"
+ ]
},
{
"id": "apple-watch-se-40mm-space-gray",
"category": "accessories",
"namespaceId": "apple-watch-se",
"name": "Apple Watch SE 40mm Space Gray",
- "capacityAvailable": ["40mm", "44mm"],
+ "capacityAvailable": [
+ "40mm",
+ "44mm"
+ ],
"capacity": "40mm",
"priceRegular": 279,
"priceDiscount": 259,
- "colorsAvailable": ["silver", "space gray", "gold"],
+ "colorsAvailable": [
+ "silver",
+ "space gray",
+ "gold"
+ ],
"color": "space gray",
"images": [
"img/accessories/apple-watch-se/space-gray/00.webp",
@@ -1383,18 +1762,29 @@
"resolution": "324x394",
"processor": "Apple S5",
"ram": "1GB",
- "cell": ["Wi-Fi", "Bluetooth", "LTE"]
+ "cell": [
+ "Wi-Fi",
+ "Bluetooth",
+ "LTE"
+ ]
},
{
"id": "apple-watch-se-44mm-space-gray",
"category": "accessories",
"namespaceId": "apple-watch-se",
"name": "Apple Watch SE 44mm Space Gray",
- "capacityAvailable": ["40mm", "44mm"],
+ "capacityAvailable": [
+ "40mm",
+ "44mm"
+ ],
"capacity": "44mm",
"priceRegular": 309,
"priceDiscount": 289,
- "colorsAvailable": ["silver", "space gray", "gold"],
+ "colorsAvailable": [
+ "silver",
+ "space gray",
+ "gold"
+ ],
"color": "space gray",
"images": [
"img/accessories/apple-watch-se/space-gray/00.webp",
@@ -1425,6 +1815,10 @@
"resolution": "368x448",
"processor": "Apple S5",
"ram": "1GB",
- "cell": ["Wi-Fi", "Bluetooth", "LTE"]
+ "cell": [
+ "Wi-Fi",
+ "Bluetooth",
+ "LTE"
+ ]
}
]
diff --git a/public/api/phones.json b/public/api/phones.json
index e1535893222..437829b92df 100644
--- a/public/api/phones.json
+++ b/public/api/phones.json
@@ -4,11 +4,22 @@
"category": "phones",
"namespaceId": "apple-iphone-11",
"name": "Apple iPhone 11 128GB Black",
- "capacityAvailable": ["64GB", "128GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "128GB",
+ "256GB"
+ ],
"capacity": "128GB",
"priceRegular": 1100,
"priceDiscount": 1050,
- "colorsAvailable": ["black", "green", "yellow", "white", "purple", "red"],
+ "colorsAvailable": [
+ "black",
+ "green",
+ "yellow",
+ "white",
+ "purple",
+ "red"
+ ],
"color": "black",
"images": [
"img/phones/apple-iphone-11/black/00.webp",
@@ -44,19 +55,36 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital, 5x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-11-128gb-green",
"category": "phones",
"namespaceId": "apple-iphone-11",
"name": "Apple iPhone 11 128GB Green",
- "capacityAvailable": ["64GB", "128GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "128GB",
+ "256GB"
+ ],
"capacity": "128GB",
"priceRegular": 1100,
"priceDiscount": 1050,
- "colorsAvailable": ["black", "green", "yellow", "white", "purple", "red"],
+ "colorsAvailable": [
+ "black",
+ "green",
+ "yellow",
+ "white",
+ "purple",
+ "red"
+ ],
"color": "green",
"images": [
"img/phones/apple-iphone-11/green/00.webp",
@@ -92,19 +120,36 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital, 5x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-11-128gb-purple",
"category": "phones",
"namespaceId": "apple-iphone-11",
"name": "Apple iPhone 11 128GB Purple",
- "capacityAvailable": ["64GB", "128GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "128GB",
+ "256GB"
+ ],
"capacity": "128GB",
"priceRegular": 1100,
"priceDiscount": 1050,
- "colorsAvailable": ["black", "green", "yellow", "white", "purple", "red"],
+ "colorsAvailable": [
+ "black",
+ "green",
+ "yellow",
+ "white",
+ "purple",
+ "red"
+ ],
"color": "purple",
"images": [
"img/phones/apple-iphone-11/purple/00.webp",
@@ -140,19 +185,36 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital, 5x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-11-128gb-red",
"category": "phones",
"namespaceId": "apple-iphone-11",
"name": "Apple iPhone 11 128GB Red",
- "capacityAvailable": ["64GB", "128GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "128GB",
+ "256GB"
+ ],
"capacity": "128GB",
"priceRegular": 1100,
"priceDiscount": 1050,
- "colorsAvailable": ["black", "green", "yellow", "white", "purple", "red"],
+ "colorsAvailable": [
+ "black",
+ "green",
+ "yellow",
+ "white",
+ "purple",
+ "red"
+ ],
"color": "red",
"images": [
"img/phones/apple-iphone-11/red/00.webp",
@@ -188,19 +250,36 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital, 5x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-11-128gb-white",
"category": "phones",
"namespaceId": "apple-iphone-11",
"name": "Apple iPhone 11 128GB White",
- "capacityAvailable": ["64GB", "128GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "128GB",
+ "256GB"
+ ],
"capacity": "128GB",
"priceRegular": 1100,
"priceDiscount": 1050,
- "colorsAvailable": ["black", "green", "yellow", "white", "purple", "red"],
+ "colorsAvailable": [
+ "black",
+ "green",
+ "yellow",
+ "white",
+ "purple",
+ "red"
+ ],
"color": "white",
"images": [
"img/phones/apple-iphone-11/white/00.webp",
@@ -236,19 +315,36 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital, 5x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-11-128gb-yellow",
"category": "phones",
"namespaceId": "apple-iphone-11",
"name": "Apple iPhone 11 128GB Yellow",
- "capacityAvailable": ["64GB", "128GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "128GB",
+ "256GB"
+ ],
"capacity": "128GB",
"priceRegular": 1100,
"priceDiscount": 1050,
- "colorsAvailable": ["black", "green", "yellow", "white", "purple", "red"],
+ "colorsAvailable": [
+ "black",
+ "green",
+ "yellow",
+ "white",
+ "purple",
+ "red"
+ ],
"color": "yellow",
"images": [
"img/phones/apple-iphone-11/yellow/00.webp",
@@ -284,19 +380,36 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital, 5x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-11-256gb-black",
"category": "phones",
"namespaceId": "apple-iphone-11",
"name": "Apple iPhone 11 256GB Black",
- "capacityAvailable": ["64GB", "128GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "128GB",
+ "256GB"
+ ],
"capacity": "256GB",
"priceRegular": 1172,
"priceDiscount": 1115,
- "colorsAvailable": ["black", "green", "yellow", "white", "purple", "red"],
+ "colorsAvailable": [
+ "black",
+ "green",
+ "yellow",
+ "white",
+ "purple",
+ "red"
+ ],
"color": "black",
"images": [
"img/phones/apple-iphone-11/black/00.webp",
@@ -332,19 +445,36 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital, 5x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-11-256gb-green",
"category": "phones",
"namespaceId": "apple-iphone-11",
"name": "Apple iPhone 11 256GB Green",
- "capacityAvailable": ["64GB", "128GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "128GB",
+ "256GB"
+ ],
"capacity": "256GB",
"priceRegular": 1172,
"priceDiscount": 1115,
- "colorsAvailable": ["black", "green", "yellow", "white", "purple", "red"],
+ "colorsAvailable": [
+ "black",
+ "green",
+ "yellow",
+ "white",
+ "purple",
+ "red"
+ ],
"color": "green",
"images": [
"img/phones/apple-iphone-11/green/00.webp",
@@ -380,19 +510,36 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital, 5x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-11-256gb-purple",
"category": "phones",
"namespaceId": "apple-iphone-11",
"name": "Apple iPhone 11 256GB Purple",
- "capacityAvailable": ["64GB", "128GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "128GB",
+ "256GB"
+ ],
"capacity": "256GB",
"priceRegular": 1172,
"priceDiscount": 1115,
- "colorsAvailable": ["black", "green", "yellow", "white", "purple", "red"],
+ "colorsAvailable": [
+ "black",
+ "green",
+ "yellow",
+ "white",
+ "purple",
+ "red"
+ ],
"color": "purple",
"images": [
"img/phones/apple-iphone-11/purple/00.webp",
@@ -428,19 +575,36 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital, 5x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-11-256gb-red",
"category": "phones",
"namespaceId": "apple-iphone-11",
"name": "Apple iPhone 11 256GB Red",
- "capacityAvailable": ["64GB", "128GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "128GB",
+ "256GB"
+ ],
"capacity": "256GB",
"priceRegular": 1172,
"priceDiscount": 1115,
- "colorsAvailable": ["black", "green", "yellow", "white", "purple", "red"],
+ "colorsAvailable": [
+ "black",
+ "green",
+ "yellow",
+ "white",
+ "purple",
+ "red"
+ ],
"color": "red",
"images": [
"img/phones/apple-iphone-11/red/00.webp",
@@ -476,19 +640,36 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital, 5x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-11-256gb-white",
"category": "phones",
"namespaceId": "apple-iphone-11",
"name": "Apple iPhone 11 256GB White",
- "capacityAvailable": ["64GB", "128GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "128GB",
+ "256GB"
+ ],
"capacity": "256GB",
"priceRegular": 1172,
"priceDiscount": 1115,
- "colorsAvailable": ["black", "green", "yellow", "white", "purple", "red"],
+ "colorsAvailable": [
+ "black",
+ "green",
+ "yellow",
+ "white",
+ "purple",
+ "red"
+ ],
"color": "white",
"images": [
"img/phones/apple-iphone-11/white/00.webp",
@@ -524,19 +705,36 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital, 5x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-11-256gb-yellow",
"category": "phones",
"namespaceId": "apple-iphone-11",
"name": "Apple iPhone 11 256GB Yellow",
- "capacityAvailable": ["64GB", "128GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "128GB",
+ "256GB"
+ ],
"capacity": "256GB",
"priceRegular": 1172,
"priceDiscount": 1115,
- "colorsAvailable": ["black", "green", "yellow", "white", "purple", "red"],
+ "colorsAvailable": [
+ "black",
+ "green",
+ "yellow",
+ "white",
+ "purple",
+ "red"
+ ],
"color": "yellow",
"images": [
"img/phones/apple-iphone-11/yellow/00.webp",
@@ -572,19 +770,36 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital, 5x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-11-64gb-black",
"category": "phones",
"namespaceId": "apple-iphone-11",
"name": "Apple iPhone 11 64GB Black",
- "capacityAvailable": ["64GB", "128GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "128GB",
+ "256GB"
+ ],
"capacity": "64GB",
"priceRegular": 932,
"priceDiscount": 880,
- "colorsAvailable": ["black", "green", "yellow", "white", "purple", "red"],
+ "colorsAvailable": [
+ "black",
+ "green",
+ "yellow",
+ "white",
+ "purple",
+ "red"
+ ],
"color": "black",
"images": [
"img/phones/apple-iphone-11/black/00.webp",
@@ -620,19 +835,36 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital, 5x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-11-64gb-green",
"category": "phones",
"namespaceId": "apple-iphone-11",
"name": "Apple iPhone 11 64GB Green",
- "capacityAvailable": ["64GB", "128GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "128GB",
+ "256GB"
+ ],
"capacity": "64GB",
"priceRegular": 932,
"priceDiscount": 880,
- "colorsAvailable": ["black", "green", "yellow", "white", "purple", "red"],
+ "colorsAvailable": [
+ "black",
+ "green",
+ "yellow",
+ "white",
+ "purple",
+ "red"
+ ],
"color": "green",
"images": [
"img/phones/apple-iphone-11/green/00.webp",
@@ -668,19 +900,36 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital, 5x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-11-64gb-purple",
"category": "phones",
"namespaceId": "apple-iphone-11",
"name": "Apple iPhone 11 64GB Purple",
- "capacityAvailable": ["64GB", "128GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "128GB",
+ "256GB"
+ ],
"capacity": "64GB",
"priceRegular": 932,
"priceDiscount": 880,
- "colorsAvailable": ["black", "green", "yellow", "white", "purple", "red"],
+ "colorsAvailable": [
+ "black",
+ "green",
+ "yellow",
+ "white",
+ "purple",
+ "red"
+ ],
"color": "purple",
"images": [
"img/phones/apple-iphone-11/purple/00.webp",
@@ -716,19 +965,36 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital, 5x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-11-64gb-red",
"category": "phones",
"namespaceId": "apple-iphone-11",
"name": "Apple iPhone 11 64GB Red",
- "capacityAvailable": ["64GB", "128GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "128GB",
+ "256GB"
+ ],
"capacity": "64GB",
"priceRegular": 932,
"priceDiscount": 880,
- "colorsAvailable": ["black", "green", "yellow", "white", "purple", "red"],
+ "colorsAvailable": [
+ "black",
+ "green",
+ "yellow",
+ "white",
+ "purple",
+ "red"
+ ],
"color": "red",
"images": [
"img/phones/apple-iphone-11/red/00.webp",
@@ -764,19 +1030,36 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital, 5x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-11-64gb-white",
"category": "phones",
"namespaceId": "apple-iphone-11",
"name": "Apple iPhone 11 64GB White",
- "capacityAvailable": ["64GB", "128GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "128GB",
+ "256GB"
+ ],
"capacity": "64GB",
"priceRegular": 932,
"priceDiscount": 880,
- "colorsAvailable": ["black", "green", "yellow", "white", "purple", "red"],
+ "colorsAvailable": [
+ "black",
+ "green",
+ "yellow",
+ "white",
+ "purple",
+ "red"
+ ],
"color": "white",
"images": [
"img/phones/apple-iphone-11/white/00.webp",
@@ -812,19 +1095,36 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital, 5x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-11-64gb-yellow",
"category": "phones",
"namespaceId": "apple-iphone-11",
"name": "Apple iPhone 11 64GB Yellow",
- "capacityAvailable": ["64GB", "128GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "128GB",
+ "256GB"
+ ],
"capacity": "64GB",
"priceRegular": 932,
"priceDiscount": 880,
- "colorsAvailable": ["black", "green", "yellow", "white", "purple", "red"],
+ "colorsAvailable": [
+ "black",
+ "green",
+ "yellow",
+ "white",
+ "purple",
+ "red"
+ ],
"color": "yellow",
"images": [
"img/phones/apple-iphone-11/yellow/00.webp",
@@ -860,19 +1160,34 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital, 5x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-11-pro-256gb-gold",
"category": "phones",
"namespaceId": "apple-iphone-11-pro",
"name": "Apple iPhone 11 Pro 256GB Gold",
- "capacityAvailable": ["64GB", "256GB", "512GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB",
+ "512GB"
+ ],
"capacity": "256GB",
"priceRegular": 1640,
"priceDiscount": 1570,
- "colorsAvailable": ["spacegray", "midnightgreen", "gold", "silver"],
+ "colorsAvailable": [
+ "spacegray",
+ "midnightgreen",
+ "gold",
+ "silver"
+ ],
"color": "gold",
"images": [
"img/phones/apple-iphone-11-pro/gold/00.webp",
@@ -906,19 +1221,34 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital, 10x / Optical, 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-11-pro-256gb-midnightgreen",
"category": "phones",
"namespaceId": "apple-iphone-11-pro",
"name": "Apple iPhone 11 Pro 256GB Midnight green",
- "capacityAvailable": ["64GB", "256GB", "512GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB",
+ "512GB"
+ ],
"capacity": "256GB",
"priceRegular": 1640,
"priceDiscount": 1570,
- "colorsAvailable": ["spacegray", "midnightgreen", "gold", "silver"],
+ "colorsAvailable": [
+ "spacegray",
+ "midnightgreen",
+ "gold",
+ "silver"
+ ],
"color": "midnightgreen",
"images": [
"img/phones/apple-iphone-11-pro/midnightgreen/00.webp",
@@ -953,19 +1283,34 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital, 10x / Optical, 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-11-pro-256gb-silver",
"category": "phones",
"namespaceId": "apple-iphone-11-pro",
"name": "Apple iPhone 11 Pro 256GB Silver",
- "capacityAvailable": ["64GB", "256GB", "512GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB",
+ "512GB"
+ ],
"capacity": "256GB",
"priceRegular": 1640,
"priceDiscount": 1570,
- "colorsAvailable": ["spacegray", "midnightgreen", "gold", "silver"],
+ "colorsAvailable": [
+ "spacegray",
+ "midnightgreen",
+ "gold",
+ "silver"
+ ],
"color": "silver",
"images": [
"img/phones/apple-iphone-11-pro/silver/00.webp",
@@ -999,19 +1344,34 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital, 10x / Optical, 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-11-pro-256gb-spacegray",
"category": "phones",
"namespaceId": "apple-iphone-11-pro",
"name": "Apple iPhone 11 Pro 256GB Spacegray",
- "capacityAvailable": ["64GB", "256GB", "512GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB",
+ "512GB"
+ ],
"capacity": "256GB",
"priceRegular": 1640,
"priceDiscount": 1570,
- "colorsAvailable": ["spacegray", "midnightgreen", "gold", "silver"],
+ "colorsAvailable": [
+ "spacegray",
+ "midnightgreen",
+ "gold",
+ "silver"
+ ],
"color": "spacegray",
"images": [
"img/phones/apple-iphone-11-pro/spacegray/00.webp",
@@ -1045,19 +1405,34 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital, 10x / Optical, 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-11-pro-512gb-gold",
"category": "phones",
"namespaceId": "apple-iphone-11-pro",
"name": "Apple iPhone 11 Pro 512GB Gold",
- "capacityAvailable": ["64GB", "256GB", "512GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB",
+ "512GB"
+ ],
"capacity": "512GB",
"priceRegular": 1880,
"priceDiscount": 1780,
- "colorsAvailable": ["spacegray", "midnightgreen", "gold", "silver"],
+ "colorsAvailable": [
+ "spacegray",
+ "midnightgreen",
+ "gold",
+ "silver"
+ ],
"color": "gold",
"images": [
"img/phones/apple-iphone-11-pro/gold/00.webp",
@@ -1091,19 +1466,34 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital, 10x / Optical, 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-11-pro-512gb-midnightgreen",
"category": "phones",
"namespaceId": "apple-iphone-11-pro",
"name": "Apple iPhone 11 Pro 512GB Midnight green",
- "capacityAvailable": ["64GB", "256GB", "512GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB",
+ "512GB"
+ ],
"capacity": "512GB",
"priceRegular": 1880,
"priceDiscount": 1780,
- "colorsAvailable": ["spacegray", "midnightgreen", "gold", "silver"],
+ "colorsAvailable": [
+ "spacegray",
+ "midnightgreen",
+ "gold",
+ "silver"
+ ],
"color": "midnightgreen",
"images": [
"img/phones/apple-iphone-11-pro/midnightgreen/00.webp",
@@ -1138,19 +1528,34 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital, 10x / Optical, 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-11-pro-512gb-silver",
"category": "phones",
"namespaceId": "apple-iphone-11-pro",
"name": "Apple iPhone 11 Pro 512GB Silver",
- "capacityAvailable": ["64GB", "256GB", "512GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB",
+ "512GB"
+ ],
"capacity": "512GB",
"priceRegular": 1880,
"priceDiscount": 1780,
- "colorsAvailable": ["spacegray", "midnightgreen", "gold", "silver"],
+ "colorsAvailable": [
+ "spacegray",
+ "midnightgreen",
+ "gold",
+ "silver"
+ ],
"color": "silver",
"images": [
"img/phones/apple-iphone-11-pro/silver/00.webp",
@@ -1184,19 +1589,34 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital, 10x / Optical, 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-11-pro-512gb-spacegray",
"category": "phones",
"namespaceId": "apple-iphone-11-pro",
"name": "Apple iPhone 11 Pro 512GB Spacegray",
- "capacityAvailable": ["64GB", "256GB", "512GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB",
+ "512GB"
+ ],
"capacity": "512GB",
"priceRegular": 1880,
"priceDiscount": 1780,
- "colorsAvailable": ["spacegray", "midnightgreen", "gold", "silver"],
+ "colorsAvailable": [
+ "spacegray",
+ "midnightgreen",
+ "gold",
+ "silver"
+ ],
"color": "spacegray",
"images": [
"img/phones/apple-iphone-11-pro/spacegray/00.webp",
@@ -1230,19 +1650,34 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital, 10x / Optical, 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-11-pro-64gb-gold",
"category": "phones",
"namespaceId": "apple-iphone-11-pro",
"name": "Apple iPhone 11 Pro 64GB Gold",
- "capacityAvailable": ["64GB", "256GB", "512GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB",
+ "512GB"
+ ],
"capacity": "64GB",
"priceRegular": 1312,
"priceDiscount": 1270,
- "colorsAvailable": ["spacegray", "midnightgreen", "gold", "silver"],
+ "colorsAvailable": [
+ "spacegray",
+ "midnightgreen",
+ "gold",
+ "silver"
+ ],
"color": "gold",
"images": [
"img/phones/apple-iphone-11-pro/gold/00.webp",
@@ -1276,19 +1711,34 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital, 10x / Optical, 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-11-pro-64gb-midnightgreen",
"category": "phones",
"namespaceId": "apple-iphone-11-pro",
"name": "Apple iPhone 11 Pro 64GB Midnight green",
- "capacityAvailable": ["64GB", "256GB", "512GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB",
+ "512GB"
+ ],
"capacity": "64GB",
"priceRegular": 1312,
"priceDiscount": 1270,
- "colorsAvailable": ["spacegray", "midnightgreen", "gold", "silver"],
+ "colorsAvailable": [
+ "spacegray",
+ "midnightgreen",
+ "gold",
+ "silver"
+ ],
"color": "midnightgreen",
"images": [
"img/phones/apple-iphone-11-pro/midnightgreen/00.webp",
@@ -1323,19 +1773,34 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital, 10x / Optical, 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-11-pro-64gb-silver",
"category": "phones",
"namespaceId": "apple-iphone-11-pro",
"name": "Apple iPhone 11 Pro 64GB Silver",
- "capacityAvailable": ["64GB", "256GB", "512GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB",
+ "512GB"
+ ],
"capacity": "64GB",
"priceRegular": 1312,
"priceDiscount": 1270,
- "colorsAvailable": ["spacegray", "midnightgreen", "gold", "silver"],
+ "colorsAvailable": [
+ "spacegray",
+ "midnightgreen",
+ "gold",
+ "silver"
+ ],
"color": "silver",
"images": [
"img/phones/apple-iphone-11-pro/silver/00.webp",
@@ -1369,19 +1834,34 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital, 10x / Optical, 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-11-pro-64gb-spacegray",
"category": "phones",
"namespaceId": "apple-iphone-11-pro",
"name": "Apple iPhone 11 Pro 64GB Spacegray",
- "capacityAvailable": ["64GB", "256GB", "512GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB",
+ "512GB"
+ ],
"capacity": "64GB",
"priceRegular": 1312,
"priceDiscount": 1270,
- "colorsAvailable": ["spacegray", "midnightgreen", "gold", "silver"],
+ "colorsAvailable": [
+ "spacegray",
+ "midnightgreen",
+ "gold",
+ "silver"
+ ],
"color": "spacegray",
"images": [
"img/phones/apple-iphone-11-pro/spacegray/00.webp",
@@ -1415,19 +1895,34 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital, 10x / Optical, 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-11-pro-max-256gb-gold",
"category": "phones",
"namespaceId": "apple-iphone-11-pro-max",
"name": "Apple iPhone 11 Pro Max 256GB Gold",
- "capacityAvailable": ["64GB", "256GB", "512GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB",
+ "512GB"
+ ],
"capacity": "256GB",
"priceRegular": 1776,
"priceDiscount": 1680,
- "colorsAvailable": ["spacegray", "midnightgreen", "gold", "silver"],
+ "colorsAvailable": [
+ "spacegray",
+ "midnightgreen",
+ "gold",
+ "silver"
+ ],
"color": "gold",
"images": [
"img/phones/apple-iphone-11-pro-max/gold/00.webp",
@@ -1461,19 +1956,34 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital, 10x / Optical, 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-11-pro-max-256gb-midnightgreen",
"category": "phones",
"namespaceId": "apple-iphone-11-pro-max",
"name": "Apple iPhone 11 Pro Max 256GB Midnightgreen",
- "capacityAvailable": ["64GB", "256GB", "512GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB",
+ "512GB"
+ ],
"capacity": "256GB",
"priceRegular": 1776,
"priceDiscount": 1680,
- "colorsAvailable": ["spacegray", "midnightgreen", "gold", "silver"],
+ "colorsAvailable": [
+ "spacegray",
+ "midnightgreen",
+ "gold",
+ "silver"
+ ],
"color": "midnightgreen",
"images": [
"img/phones/apple-iphone-11-pro-max/midnightgreen/00.webp",
@@ -1507,19 +2017,34 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital, 10x / Optical, 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-11-pro-max-256gb-silver",
"category": "phones",
"namespaceId": "apple-iphone-11-pro-max",
"name": "Apple iPhone 11 Pro Max 256GB Silver",
- "capacityAvailable": ["64GB", "256GB", "512GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB",
+ "512GB"
+ ],
"capacity": "256GB",
"priceRegular": 1776,
"priceDiscount": 1680,
- "colorsAvailable": ["spacegray", "midnightgreen", "gold", "silver"],
+ "colorsAvailable": [
+ "spacegray",
+ "midnightgreen",
+ "gold",
+ "silver"
+ ],
"color": "silver",
"images": [
"img/phones/apple-iphone-11-pro-max/silver/00.webp",
@@ -1553,19 +2078,34 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital, 10x / Optical, 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-11-pro-max-256gb-spacegray",
"category": "phones",
"namespaceId": "apple-iphone-11-pro-max",
"name": "Apple iPhone 11 Pro Max 256GB Spacegray",
- "capacityAvailable": ["64GB", "256GB", "512GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB",
+ "512GB"
+ ],
"capacity": "256GB",
"priceRegular": 1776,
"priceDiscount": 1680,
- "colorsAvailable": ["spacegray", "midnightgreen", "gold", "silver"],
+ "colorsAvailable": [
+ "spacegray",
+ "midnightgreen",
+ "gold",
+ "silver"
+ ],
"color": "spacegray",
"images": [
"img/phones/apple-iphone-11-pro-max/spacegray/00.webp",
@@ -1599,19 +2139,34 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital, 10x / Optical, 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-11-pro-max-512gb-gold",
"category": "phones",
"namespaceId": "apple-iphone-11-pro-max",
"name": "Apple iPhone 11 Pro Max 512GB Gold",
- "capacityAvailable": ["64GB", "256GB", "512GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB",
+ "512GB"
+ ],
"capacity": "512GB",
"priceRegular": 2020,
"priceDiscount": 1930,
- "colorsAvailable": ["spacegray", "midnightgreen", "gold", "silver"],
+ "colorsAvailable": [
+ "spacegray",
+ "midnightgreen",
+ "gold",
+ "silver"
+ ],
"color": "gold",
"images": [
"img/phones/apple-iphone-11-pro-max/gold/00.webp",
@@ -1645,19 +2200,34 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital, 10x / Optical, 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-11-pro-max-512gb-midnightgreen",
"category": "phones",
"namespaceId": "apple-iphone-11-pro-max",
"name": "Apple iPhone 11 Pro Max 512GB Midnightgreen",
- "capacityAvailable": ["64GB", "256GB", "512GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB",
+ "512GB"
+ ],
"capacity": "512GB",
"priceRegular": 2020,
"priceDiscount": 1930,
- "colorsAvailable": ["spacegray", "midnightgreen", "gold", "silver"],
+ "colorsAvailable": [
+ "spacegray",
+ "midnightgreen",
+ "gold",
+ "silver"
+ ],
"color": "midnightgreen",
"images": [
"img/phones/apple-iphone-11-pro-max/midnightgreen/00.webp",
@@ -1691,19 +2261,34 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital, 10x / Optical, 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-11-pro-max-512gb-silver",
"category": "phones",
"namespaceId": "apple-iphone-11-pro-max",
"name": "Apple iPhone 11 Pro Max 512GB Silver",
- "capacityAvailable": ["64GB", "256GB", "512GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB",
+ "512GB"
+ ],
"capacity": "512GB",
"priceRegular": 2020,
"priceDiscount": 1930,
- "colorsAvailable": ["spacegray", "midnightgreen", "gold", "silver"],
+ "colorsAvailable": [
+ "spacegray",
+ "midnightgreen",
+ "gold",
+ "silver"
+ ],
"color": "silver",
"images": [
"img/phones/apple-iphone-11-pro-max/silver/00.webp",
@@ -1737,19 +2322,34 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital, 10x / Optical, 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-11-pro-max-512gb-spacegray",
"category": "phones",
"namespaceId": "apple-iphone-11-pro-max",
"name": "Apple iPhone 11 Pro Max 512GB Spacegray",
- "capacityAvailable": ["64GB", "256GB", "512GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB",
+ "512GB"
+ ],
"capacity": "512GB",
"priceRegular": 2020,
"priceDiscount": 1930,
- "colorsAvailable": ["spacegray", "midnightgreen", "gold", "silver"],
+ "colorsAvailable": [
+ "spacegray",
+ "midnightgreen",
+ "gold",
+ "silver"
+ ],
"color": "spacegray",
"images": [
"img/phones/apple-iphone-11-pro-max/spacegray/00.webp",
@@ -1783,19 +2383,34 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital, 10x / Optical, 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-11-pro-max-64gb-gold",
"category": "phones",
"namespaceId": "apple-iphone-11-pro-max",
"name": "Apple iPhone 11 Pro Max 64GB Gold",
- "capacityAvailable": ["64GB", "256GB", "512GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB",
+ "512GB"
+ ],
"capacity": "64GB",
"priceRegular": 1480,
"priceDiscount": 1400,
- "colorsAvailable": ["spacegray", "midnightgreen", "gold", "silver"],
+ "colorsAvailable": [
+ "spacegray",
+ "midnightgreen",
+ "gold",
+ "silver"
+ ],
"color": "gold",
"images": [
"img/phones/apple-iphone-11-pro-max/gold/00.webp",
@@ -1829,19 +2444,34 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital, 10x / Optical, 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-11-pro-max-64gb-midnightgreen",
"category": "phones",
"namespaceId": "apple-iphone-11-pro-max",
"name": "Apple iPhone 11 Pro Max 64GB Midnightgreen",
- "capacityAvailable": ["64GB", "256GB", "512GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB",
+ "512GB"
+ ],
"capacity": "64GB",
"priceRegular": 1480,
"priceDiscount": 1400,
- "colorsAvailable": ["spacegray", "midnightgreen", "gold", "silver"],
+ "colorsAvailable": [
+ "spacegray",
+ "midnightgreen",
+ "gold",
+ "silver"
+ ],
"color": "midnightgreen",
"images": [
"img/phones/apple-iphone-11-pro-max/midnightgreen/00.webp",
@@ -1875,19 +2505,34 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital, 10x / Optical, 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-11-pro-max-64gb-silver",
"category": "phones",
"namespaceId": "apple-iphone-11-pro-max",
"name": "Apple iPhone 11 Pro Max 64GB Silver",
- "capacityAvailable": ["64GB", "256GB", "512GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB",
+ "512GB"
+ ],
"capacity": "64GB",
"priceRegular": 1480,
"priceDiscount": 1400,
- "colorsAvailable": ["spacegray", "midnightgreen", "gold", "silver"],
+ "colorsAvailable": [
+ "spacegray",
+ "midnightgreen",
+ "gold",
+ "silver"
+ ],
"color": "silver",
"images": [
"img/phones/apple-iphone-11-pro-max/silver/00.webp",
@@ -1921,19 +2566,34 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital, 10x / Optical, 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-11-pro-max-64gb-spacegray",
"category": "phones",
"namespaceId": "apple-iphone-11-pro-max",
"name": "Apple iPhone 11 Pro Max 64GB Spacegray",
- "capacityAvailable": ["64GB", "256GB", "512GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB",
+ "512GB"
+ ],
"capacity": "64GB",
"priceRegular": 1480,
"priceDiscount": 1400,
- "colorsAvailable": ["spacegray", "midnightgreen", "gold", "silver"],
+ "colorsAvailable": [
+ "spacegray",
+ "midnightgreen",
+ "gold",
+ "silver"
+ ],
"color": "spacegray",
"images": [
"img/phones/apple-iphone-11-pro-max/spacegray/00.webp",
@@ -1967,19 +2627,32 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital, 10x / Optical, 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-7-32gb-black",
"category": "phones",
"namespaceId": "apple-iphone-7",
"name": "Apple iPhone 7 32GB Black",
- "capacityAvailable": ["32GB"],
+ "capacityAvailable": [
+ "32GB"
+ ],
"capacity": "32GB",
"priceRegular": 400,
"priceDiscount": 375,
- "colorsAvailable": ["black", "rosegold", "gold", "silver"],
+ "colorsAvailable": [
+ "black",
+ "rosegold",
+ "gold",
+ "silver"
+ ],
"color": "black",
"images": [
"img/phones/apple-iphone-7/black/00.webp",
@@ -2015,19 +2688,32 @@
"ram": "2GB",
"camera": "12 Mp + 7 Mp",
"zoom": "Digital, 5x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-7-32gb-gold",
"category": "phones",
"namespaceId": "apple-iphone-7",
"name": "Apple iPhone 7 32GB Gold",
- "capacityAvailable": ["32GB"],
+ "capacityAvailable": [
+ "32GB"
+ ],
"capacity": "32GB",
"priceRegular": 400,
"priceDiscount": 375,
- "colorsAvailable": ["black", "rosegold", "gold", "silver"],
+ "colorsAvailable": [
+ "black",
+ "rosegold",
+ "gold",
+ "silver"
+ ],
"color": "gold",
"images": [
"img/phones/apple-iphone-7/gold/00.webp",
@@ -2063,19 +2749,32 @@
"ram": "2GB",
"camera": "12 Mp + 7 Mp",
"zoom": "Digital, 5x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-7-32gb-rosegold",
"category": "phones",
"namespaceId": "apple-iphone-7",
"name": "Apple iPhone 7 32GB Rosegold",
- "capacityAvailable": ["32GB"],
+ "capacityAvailable": [
+ "32GB"
+ ],
"capacity": "32GB",
"priceRegular": 400,
"priceDiscount": 375,
- "colorsAvailable": ["black", "rosegold", "gold", "silver"],
+ "colorsAvailable": [
+ "black",
+ "rosegold",
+ "gold",
+ "silver"
+ ],
"color": "rosegold",
"images": [
"img/phones/apple-iphone-7/rosegold/00.webp",
@@ -2111,19 +2810,32 @@
"ram": "2GB",
"camera": "12 Mp + 7 Mp",
"zoom": "Digital, 5x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-7-32gb-silver",
"category": "phones",
"namespaceId": "apple-iphone-7",
"name": "Apple iPhone 7 32GB Silver",
- "capacityAvailable": ["32GB"],
+ "capacityAvailable": [
+ "32GB"
+ ],
"capacity": "32GB",
"priceRegular": 400,
"priceDiscount": 375,
- "colorsAvailable": ["black", "rosegold", "gold", "silver"],
+ "colorsAvailable": [
+ "black",
+ "rosegold",
+ "gold",
+ "silver"
+ ],
"color": "silver",
"images": [
"img/phones/apple-iphone-7/silver/00.webp",
@@ -2159,19 +2871,32 @@
"ram": "2GB",
"camera": "12 Mp + 7 Mp",
"zoom": "Digital, 5x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-7-plus-32gb-black",
"category": "phones",
"namespaceId": "apple-iphone-7-plus",
"name": "Apple iPhone 7 Plus 32GB Black",
- "capacityAvailable": ["32GB"],
+ "capacityAvailable": [
+ "32GB"
+ ],
"capacity": "32GB",
"priceRegular": 540,
"priceDiscount": 500,
- "colorsAvailable": ["black", "rosegold", "gold", "silver"],
+ "colorsAvailable": [
+ "black",
+ "rosegold",
+ "gold",
+ "silver"
+ ],
"color": "black",
"images": [
"img/phones/apple-iphone-7-plus/black/00.webp",
@@ -2207,19 +2932,32 @@
"ram": "3GB",
"camera": "12 Mp + 7 Mp",
"zoom": "Digital, 10x / Optical, 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-7-plus-32gb-gold",
"category": "phones",
"namespaceId": "apple-iphone-7-plus",
"name": "Apple iPhone 7 Plus 32GB Gold",
- "capacityAvailable": ["32GB"],
+ "capacityAvailable": [
+ "32GB"
+ ],
"capacity": "32GB",
"priceRegular": 540,
"priceDiscount": 500,
- "colorsAvailable": ["black", "rosegold", "gold", "silver"],
+ "colorsAvailable": [
+ "black",
+ "rosegold",
+ "gold",
+ "silver"
+ ],
"color": "gold",
"images": [
"img/phones/apple-iphone-7-plus/gold/00.webp",
@@ -2255,19 +2993,32 @@
"ram": "3GB",
"camera": "12 Mp + 7 Mp",
"zoom": "Digital, 10x / Optical, 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-7-plus-32gb-rosegold",
"category": "phones",
"namespaceId": "apple-iphone-7-plus",
"name": "Apple iPhone 7 Plus 32GB Rosegold",
- "capacityAvailable": ["32GB"],
+ "capacityAvailable": [
+ "32GB"
+ ],
"capacity": "32GB",
"priceRegular": 540,
"priceDiscount": 500,
- "colorsAvailable": ["black", "rosegold", "gold", "silver"],
+ "colorsAvailable": [
+ "black",
+ "rosegold",
+ "gold",
+ "silver"
+ ],
"color": "rosegold",
"images": [
"img/phones/apple-iphone-7-plus/rosegold/00.webp",
@@ -2303,19 +3054,32 @@
"ram": "3GB",
"camera": "12 Mp + 7 Mp",
"zoom": "Digital, 10x / Optical, 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-7-plus-32gb-silver",
"category": "phones",
"namespaceId": "apple-iphone-7-plus",
"name": "Apple iPhone 7 Plus 32GB Silver",
- "capacityAvailable": ["32GB"],
+ "capacityAvailable": [
+ "32GB"
+ ],
"capacity": "32GB",
"priceRegular": 540,
"priceDiscount": 500,
- "colorsAvailable": ["black", "rosegold", "gold", "silver"],
+ "colorsAvailable": [
+ "black",
+ "rosegold",
+ "gold",
+ "silver"
+ ],
"color": "silver",
"images": [
"img/phones/apple-iphone-7-plus/silver/00.webp",
@@ -2351,19 +3115,31 @@
"ram": "3GB",
"camera": "12 Mp + 7 Mp",
"zoom": "Digital, 10x / Optical, 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-8-64gb-gold",
"category": "phones",
"namespaceId": "apple-iphone-8",
"name": "Apple iPhone 8 64GB Gold",
- "capacityAvailable": ["64GB"],
+ "capacityAvailable": [
+ "64GB"
+ ],
"capacity": "64GB",
"priceRegular": 600,
"priceDiscount": 550,
- "colorsAvailable": ["spacegray", "gold", "silver"],
+ "colorsAvailable": [
+ "spacegray",
+ "gold",
+ "silver"
+ ],
"color": "gold",
"images": [
"img/phones/apple-iphone-8/gold/00.webp",
@@ -2398,19 +3174,31 @@
"ram": "2GB",
"camera": "12 Mp + 7 Mp",
"zoom": "Digital, 5x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-8-64gb-silver",
"category": "phones",
"namespaceId": "apple-iphone-8",
"name": "Apple iPhone 8 64GB Silver",
- "capacityAvailable": ["64GB"],
+ "capacityAvailable": [
+ "64GB"
+ ],
"capacity": "64GB",
"priceRegular": 600,
"priceDiscount": 550,
- "colorsAvailable": ["spacegray", "gold", "silver"],
+ "colorsAvailable": [
+ "spacegray",
+ "gold",
+ "silver"
+ ],
"color": "silver",
"images": [
"img/phones/apple-iphone-8/silver/00.webp",
@@ -2445,19 +3233,31 @@
"ram": "2GB",
"camera": "12 Mp + 7 Mp",
"zoom": "Digital, 5x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-8-64gb-spacegray",
"category": "phones",
"namespaceId": "apple-iphone-8",
"name": "Apple iPhone 8 64GB Space Gray",
- "capacityAvailable": ["64GB"],
+ "capacityAvailable": [
+ "64GB"
+ ],
"capacity": "64GB",
"priceRegular": 600,
"priceDiscount": 550,
- "colorsAvailable": ["spacegray", "gold", "silver"],
+ "colorsAvailable": [
+ "spacegray",
+ "gold",
+ "silver"
+ ],
"color": "spacegray",
"images": [
"img/phones/apple-iphone-8/spacegray/00.webp",
@@ -2492,26 +3292,38 @@
"ram": "2GB",
"camera": "12 Mp + 7 Mp",
"zoom": "Digital, 5x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-xr-128gb-coral",
"category": "phones",
"namespaceId": "apple-iphone-xr",
"name": "Apple iPhone XR 128GB Coral",
- "capacityAvailable": ["64GB", "128GB"],
+ "capacityAvailable": [
+ "64GB",
+ "128GB"
+ ],
"capacity": "128GB",
"priceRegular": 880,
"priceDiscount": 815,
- "colorsAvailable": ["white", "yellow", "red", "coral"],
+ "colorsAvailable": [
+ "white",
+ "yellow",
+ "red",
+ "coral"
+ ],
"color": "coral",
"images": [
"img/phones/apple-iphone-xr/coral/00.webp",
"img/phones/apple-iphone-xr/coral/01.webp",
- "img/phones/apple-iphone-xr/coral/02.webp",
- "img/phones/apple-iphone-xr/coral/03.webp",
- "img/phones/apple-iphone-xr/coral/04.webp"
+ "img/phones/apple-iphone-xr/coral/02.webp"
],
"description": [
{
@@ -2540,19 +3352,33 @@
"ram": "3GB",
"camera": "12 Mp + 7 MP",
"zoom": "Digital, 5x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-xr-128gb-red",
"category": "phones",
"namespaceId": "apple-iphone-xr",
"name": "Apple iPhone XR 128GB Red",
- "capacityAvailable": ["64GB", "128GB"],
+ "capacityAvailable": [
+ "64GB",
+ "128GB"
+ ],
"capacity": "128GB",
"priceRegular": 880,
"priceDiscount": 815,
- "colorsAvailable": ["white", "yellow", "red", "coral"],
+ "colorsAvailable": [
+ "white",
+ "yellow",
+ "red",
+ "coral"
+ ],
"color": "red",
"images": [
"img/phones/apple-iphone-xr/red/00.webp",
@@ -2588,26 +3414,39 @@
"ram": "3GB",
"camera": "12 Mp + 7 MP",
"zoom": "Digital, 5x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-xr-128gb-white",
"category": "phones",
"namespaceId": "apple-iphone-xr",
"name": "Apple iPhone XR 128GB White",
- "capacityAvailable": ["64GB", "128GB"],
+ "capacityAvailable": [
+ "64GB",
+ "128GB"
+ ],
"capacity": "128GB",
"priceRegular": 880,
"priceDiscount": 815,
- "colorsAvailable": ["white", "yellow", "red", "coral"],
+ "colorsAvailable": [
+ "white",
+ "yellow",
+ "red",
+ "coral"
+ ],
"color": "white",
"images": [
"img/phones/apple-iphone-xr/white/00.webp",
"img/phones/apple-iphone-xr/white/01.webp",
"img/phones/apple-iphone-xr/white/02.webp",
- "img/phones/apple-iphone-xr/white/03.webp",
- "img/phones/apple-iphone-xr/white/04.webp"
+ "img/phones/apple-iphone-xr/white/03.webp"
],
"description": [
{
@@ -2636,19 +3475,33 @@
"ram": "3GB",
"camera": "12 Mp + 7 MP",
"zoom": "Digital, 5x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-xr-128gb-yellow",
"category": "phones",
"namespaceId": "apple-iphone-xr",
"name": "Apple iPhone XR 128GB Yellow",
- "capacityAvailable": ["64GB", "128GB"],
+ "capacityAvailable": [
+ "64GB",
+ "128GB"
+ ],
"capacity": "128GB",
"priceRegular": 880,
"priceDiscount": 815,
- "colorsAvailable": ["white", "yellow", "red", "coral"],
+ "colorsAvailable": [
+ "white",
+ "yellow",
+ "red",
+ "coral"
+ ],
"color": "yellow",
"images": [
"img/phones/apple-iphone-xr/yellow/00.webp",
@@ -2684,19 +3537,33 @@
"ram": "3GB",
"camera": "12 Mp + 7 MP",
"zoom": "Digital, 5x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-xr-64gb-coral",
"category": "phones",
"namespaceId": "apple-iphone-xr",
"name": "Apple iPhone XR 64GB Coral",
- "capacityAvailable": ["64GB", "128GB"],
+ "capacityAvailable": [
+ "64GB",
+ "128GB"
+ ],
"capacity": "64GB",
"priceRegular": 712,
"priceDiscount": 670,
- "colorsAvailable": ["white", "yellow", "red", "coral"],
+ "colorsAvailable": [
+ "white",
+ "yellow",
+ "red",
+ "coral"
+ ],
"color": "coral",
"images": [
"img/phones/apple-iphone-xr/coral/00.webp",
@@ -2730,19 +3597,33 @@
"ram": "3GB",
"camera": "12 Mp + 7 MP",
"zoom": "Digital, 5x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-xr-64gb-red",
"category": "phones",
"namespaceId": "apple-iphone-xr",
"name": "Apple iPhone XR 64GB Red",
- "capacityAvailable": ["64GB", "128GB"],
+ "capacityAvailable": [
+ "64GB",
+ "128GB"
+ ],
"capacity": "64GB",
"priceRegular": 712,
"priceDiscount": 670,
- "colorsAvailable": ["white", "yellow", "red", "coral"],
+ "colorsAvailable": [
+ "white",
+ "yellow",
+ "red",
+ "coral"
+ ],
"color": "red",
"images": [
"img/phones/apple-iphone-xr/red/00.webp",
@@ -2778,26 +3659,39 @@
"ram": "3GB",
"camera": "12 Mp + 7 MP",
"zoom": "Digital, 5x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-xr-64gb-white",
"category": "phones",
"namespaceId": "apple-iphone-xr",
"name": "Apple iPhone XR 64GB White",
- "capacityAvailable": ["64GB", "128GB"],
+ "capacityAvailable": [
+ "64GB",
+ "128GB"
+ ],
"capacity": "64GB",
"priceRegular": 712,
"priceDiscount": 670,
- "colorsAvailable": ["white", "yellow", "red", "coral"],
+ "colorsAvailable": [
+ "white",
+ "yellow",
+ "red",
+ "coral"
+ ],
"color": "white",
"images": [
"img/phones/apple-iphone-xr/white/00.webp",
"img/phones/apple-iphone-xr/white/01.webp",
"img/phones/apple-iphone-xr/white/02.webp",
- "img/phones/apple-iphone-xr/white/03.webp",
- "img/phones/apple-iphone-xr/white/04.webp"
+ "img/phones/apple-iphone-xr/white/03.webp"
],
"description": [
{
@@ -2826,19 +3720,33 @@
"ram": "3GB",
"camera": "12 Mp + 7 MP",
"zoom": "Digital, 5x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-xr-64gb-yellow",
"category": "phones",
"namespaceId": "apple-iphone-xr",
"name": "Apple iPhone XR 64GB Yellow",
- "capacityAvailable": ["64GB", "128GB"],
+ "capacityAvailable": [
+ "64GB",
+ "128GB"
+ ],
"capacity": "64GB",
"priceRegular": 712,
"priceDiscount": 670,
- "colorsAvailable": ["white", "yellow", "red", "coral"],
+ "colorsAvailable": [
+ "white",
+ "yellow",
+ "red",
+ "coral"
+ ],
"color": "yellow",
"images": [
"img/phones/apple-iphone-xr/yellow/00.webp",
@@ -2874,19 +3782,31 @@
"ram": "3GB",
"camera": "12 Mp + 7 MP",
"zoom": "Digital, 5x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-xs-256gb-gold",
"category": "phones",
"namespaceId": "apple-iphone-xs",
"name": "Apple iPhone XS 256GB Gold",
- "capacityAvailable": ["64GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB"
+ ],
"capacity": "256GB",
"priceRegular": 960,
"priceDiscount": 900,
- "colorsAvailable": ["spacegray", "gold"],
+ "colorsAvailable": [
+ "spacegray",
+ "gold"
+ ],
"color": "gold",
"images": [
"img/phones/apple-iphone-xs/gold/00.webp",
@@ -2922,19 +3842,31 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital, 10x / Optical, 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-xs-256gb-spacegray",
"category": "phones",
"namespaceId": "apple-iphone-xs",
"name": "Apple iPhone XS 256GB Spacegray",
- "capacityAvailable": ["64GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB"
+ ],
"capacity": "256GB",
"priceRegular": 960,
"priceDiscount": 900,
- "colorsAvailable": ["spacegray", "gold"],
+ "colorsAvailable": [
+ "spacegray",
+ "gold"
+ ],
"color": "spacegray",
"images": [
"img/phones/apple-iphone-xs/spacegray/00.webp",
@@ -2970,19 +3902,31 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital, 10x / Optical, 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-xs-64gb-gold",
"category": "phones",
"namespaceId": "apple-iphone-xs",
"name": "Apple iPhone XS 64GB Gold",
- "capacityAvailable": ["64GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB"
+ ],
"capacity": "64GB",
"priceRegular": 760,
"priceDiscount": 720,
- "colorsAvailable": ["spacegray", "gold"],
+ "colorsAvailable": [
+ "spacegray",
+ "gold"
+ ],
"color": "gold",
"images": [
"img/phones/apple-iphone-xs/gold/00.webp",
@@ -3018,19 +3962,31 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital, 10x / Optical, 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-xs-64gb-spacegray",
"category": "phones",
"namespaceId": "apple-iphone-xs",
"name": "Apple iPhone XS 64GB Spacegray",
- "capacityAvailable": ["64GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB"
+ ],
"capacity": "64GB",
"priceRegular": 760,
"priceDiscount": 720,
- "colorsAvailable": ["spacegray", "gold"],
+ "colorsAvailable": [
+ "spacegray",
+ "gold"
+ ],
"color": "spacegray",
"images": [
"img/phones/apple-iphone-xs/spacegray/00.webp",
@@ -3066,19 +4022,32 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital, 10x / Optical, 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-xs-max-256gb-gold",
"category": "phones",
"namespaceId": "apple-iphone-xs-max",
"name": "Apple iPhone XS Max 256GB Gold",
- "capacityAvailable": ["64GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB"
+ ],
"capacity": "256GB",
"priceRegular": 1080,
"priceDiscount": 1000,
- "colorsAvailable": ["spacegray", "gold", "silver"],
+ "colorsAvailable": [
+ "spacegray",
+ "gold",
+ "silver"
+ ],
"color": "gold",
"images": [
"img/phones/apple-iphone-xs-max/gold/00.webp",
@@ -3114,19 +4083,32 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 7MP",
"zoom": "Digital, 10x / Optical, 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-xs-max-256gb-silver",
"category": "phones",
"namespaceId": "apple-iphone-xs-max",
"name": "Apple iPhone XS Max 256GB Silver",
- "capacityAvailable": ["64GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB"
+ ],
"capacity": "256GB",
"priceRegular": 1080,
"priceDiscount": 1000,
- "colorsAvailable": ["spacegray", "gold", "silver"],
+ "colorsAvailable": [
+ "spacegray",
+ "gold",
+ "silver"
+ ],
"color": "silver",
"images": [
"img/phones/apple-iphone-xs-max/silver/00.webp",
@@ -3162,19 +4144,32 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 7MP",
"zoom": "Digital, 10x / Optical, 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-xs-max-256gb-spacegray",
"category": "phones",
"namespaceId": "apple-iphone-xs-max",
"name": "Apple iPhone XS Max 256GB Spacegray",
- "capacityAvailable": ["64GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB"
+ ],
"capacity": "256GB",
"priceRegular": 1080,
"priceDiscount": 1000,
- "colorsAvailable": ["spacegray", "gold", "silver"],
+ "colorsAvailable": [
+ "spacegray",
+ "gold",
+ "silver"
+ ],
"color": "spacegray",
"images": [
"img/phones/apple-iphone-xs-max/spacegray/00.webp",
@@ -3210,19 +4205,32 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 7MP",
"zoom": "Digital, 10x / Optical, 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-xs-max-64gb-gold",
"category": "phones",
"namespaceId": "apple-iphone-xs-max",
"name": "Apple iPhone XS Max 64GB Gold",
- "capacityAvailable": ["64GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB"
+ ],
"capacity": "64GB",
"priceRegular": 960,
"priceDiscount": 900,
- "colorsAvailable": ["spacegray", "gold", "silver"],
+ "colorsAvailable": [
+ "spacegray",
+ "gold",
+ "silver"
+ ],
"color": "gold",
"images": [
"img/phones/apple-iphone-xs-max/gold/00.webp",
@@ -3258,19 +4266,32 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 7MP",
"zoom": "Digital, 10x / Optical, 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-xs-max-64gb-silver",
"category": "phones",
"namespaceId": "apple-iphone-xs-max",
"name": "Apple iPhone XS Max 64GB Silver",
- "capacityAvailable": ["64GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB"
+ ],
"capacity": "64GB",
"priceRegular": 960,
"priceDiscount": 900,
- "colorsAvailable": ["spacegray", "gold", "silver"],
+ "colorsAvailable": [
+ "spacegray",
+ "gold",
+ "silver"
+ ],
"color": "silver",
"images": [
"img/phones/apple-iphone-xs-max/silver/00.webp",
@@ -3306,19 +4327,32 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 7MP",
"zoom": "Digital, 10x / Optical, 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
-
{
"id": "apple-iphone-xs-max-64gb-spacegray",
"category": "phones",
"namespaceId": "apple-iphone-xs-max",
"name": "Apple iPhone XS Max 64GB Spacegray",
- "capacityAvailable": ["64GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB"
+ ],
"capacity": "64GB",
"priceRegular": 960,
"priceDiscount": 900,
- "colorsAvailable": ["spacegray", "gold", "silver"],
+ "colorsAvailable": [
+ "spacegray",
+ "gold",
+ "silver"
+ ],
"color": "spacegray",
"images": [
"img/phones/apple-iphone-xs-max/spacegray/00.webp",
@@ -3354,18 +4388,33 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp + 7MP",
"zoom": "Digital, 10x / Optical, 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
{
"id": "apple-iphone-14-128gb-midnight",
"category": "phones",
"namespaceId": "apple-iphone-14",
"name": "Apple iPhone 14 128GB Midnight",
- "capacityAvailable": ["128GB", "256GB", "512GB"],
+ "capacityAvailable": [
+ "128GB",
+ "256GB",
+ "512GB"
+ ],
"capacity": "128GB",
"priceRegular": 1056,
"priceDiscount": 980,
- "colorsAvailable": ["midnight", "yellow", "purple"],
+ "colorsAvailable": [
+ "midnight",
+ "yellow",
+ "purple"
+ ],
"color": "midnight",
"images": [
"img/phones/apple-iphone-14/midnight/00.webp",
@@ -3401,18 +4450,34 @@
"ram": "6GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital 5x, Optical 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE", "5G"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE",
+ "5G"
+ ]
},
{
"id": "apple-iphone-14-256gb-midnight",
"category": "phones",
"namespaceId": "apple-iphone-14",
"name": "Apple iPhone 14 256GB Midnight",
- "capacityAvailable": ["128GB", "256GB", "512GB"],
+ "capacityAvailable": [
+ "128GB",
+ "256GB",
+ "512GB"
+ ],
"capacity": "256GB",
"priceRegular": 1200,
"priceDiscount": 1160,
- "colorsAvailable": ["midnight", "yellow", "purple"],
+ "colorsAvailable": [
+ "midnight",
+ "yellow",
+ "purple"
+ ],
"color": "midnight",
"images": [
"img/phones/apple-iphone-14/midnight/00.webp",
@@ -3448,18 +4513,34 @@
"ram": "6GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital 5x, Optical 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE", "5G"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE",
+ "5G"
+ ]
},
{
"id": "apple-iphone-14-512gb-midnight",
"category": "phones",
"namespaceId": "apple-iphone-14",
"name": "Apple iPhone 14 512GB Midnight",
- "capacityAvailable": ["128GB", "256GB", "512GB"],
+ "capacityAvailable": [
+ "128GB",
+ "256GB",
+ "512GB"
+ ],
"capacity": "512GB",
"priceRegular": 1466,
"priceDiscount": 1378,
- "colorsAvailable": ["midnight", "yellow", "purple"],
+ "colorsAvailable": [
+ "midnight",
+ "yellow",
+ "purple"
+ ],
"color": "midnight",
"images": [
"img/phones/apple-iphone-14/midnight/00.webp",
@@ -3495,18 +4576,34 @@
"ram": "6GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital 5x, Optical 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE", "5G"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE",
+ "5G"
+ ]
},
{
"id": "apple-iphone-14-128gb-yellow",
"category": "phones",
"namespaceId": "apple-iphone-14",
"name": "Apple iPhone 14 128GB Yellow",
- "capacityAvailable": ["128GB", "256GB", "512GB"],
+ "capacityAvailable": [
+ "128GB",
+ "256GB",
+ "512GB"
+ ],
"capacity": "128GB",
"priceRegular": 1056,
"priceDiscount": 980,
- "colorsAvailable": ["midnight", "yellow", "purple"],
+ "colorsAvailable": [
+ "midnight",
+ "yellow",
+ "purple"
+ ],
"color": "yellow",
"images": [
"img/phones/apple-iphone-14/yellow/00.webp",
@@ -3542,18 +4639,34 @@
"ram": "6GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital 5x, Optical 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE", "5G"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE",
+ "5G"
+ ]
},
{
"id": "apple-iphone-14-256gb-yellow",
"category": "phones",
"namespaceId": "apple-iphone-14",
"name": "Apple iPhone 14 256GB Yellow",
- "capacityAvailable": ["128GB", "256GB", "512GB"],
+ "capacityAvailable": [
+ "128GB",
+ "256GB",
+ "512GB"
+ ],
"capacity": "256GB",
"priceRegular": 1200,
"priceDiscount": 1160,
- "colorsAvailable": ["midnight", "yellow", "purple"],
+ "colorsAvailable": [
+ "midnight",
+ "yellow",
+ "purple"
+ ],
"color": "yellow",
"images": [
"img/phones/apple-iphone-14/yellow/00.webp",
@@ -3589,18 +4702,34 @@
"ram": "6GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital 5x, Optical 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE", "5G"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE",
+ "5G"
+ ]
},
{
"id": "apple-iphone-14-512gb-yellow",
"category": "phones",
"namespaceId": "apple-iphone-14",
"name": "Apple iPhone 14 512GB Yellow",
- "capacityAvailable": ["128GB", "256GB", "512GB"],
+ "capacityAvailable": [
+ "128GB",
+ "256GB",
+ "512GB"
+ ],
"capacity": "512GB",
"priceRegular": 1466,
"priceDiscount": 1378,
- "colorsAvailable": ["midnight", "yellow", "purple"],
+ "colorsAvailable": [
+ "midnight",
+ "yellow",
+ "purple"
+ ],
"color": "yellow",
"images": [
"img/phones/apple-iphone-14/yellow/00.webp",
@@ -3636,18 +4765,34 @@
"ram": "6GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital 5x, Optical 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE", "5G"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE",
+ "5G"
+ ]
},
{
"id": "apple-iphone-14-128gb-purple",
"category": "phones",
"namespaceId": "apple-iphone-14",
"name": "Apple iPhone 14 128GB Purple",
- "capacityAvailable": ["128GB", "256GB", "512GB"],
+ "capacityAvailable": [
+ "128GB",
+ "256GB",
+ "512GB"
+ ],
"capacity": "128GB",
"priceRegular": 1056,
"priceDiscount": 980,
- "colorsAvailable": ["midnight", "yellow", "purple"],
+ "colorsAvailable": [
+ "midnight",
+ "yellow",
+ "purple"
+ ],
"color": "purple",
"images": [
"img/phones/apple-iphone-14/purple/00.webp",
@@ -3683,18 +4828,34 @@
"ram": "6GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital 5x, Optical 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE", "5G"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE",
+ "5G"
+ ]
},
{
"id": "apple-iphone-14-256gb-purple",
"category": "phones",
"namespaceId": "apple-iphone-14",
"name": "Apple iPhone 14 256GB Purple",
- "capacityAvailable": ["128GB", "256GB", "512GB"],
+ "capacityAvailable": [
+ "128GB",
+ "256GB",
+ "512GB"
+ ],
"capacity": "256GB",
"priceRegular": 1256,
"priceDiscount": 1180,
- "colorsAvailable": ["midnight", "yellow", "purple"],
+ "colorsAvailable": [
+ "midnight",
+ "yellow",
+ "purple"
+ ],
"color": "purple",
"images": [
"img/phones/apple-iphone-14/purple/00.webp",
@@ -3730,18 +4891,34 @@
"ram": "6GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital 5x, Optical 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE", "5G"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE",
+ "5G"
+ ]
},
{
"id": "apple-iphone-14-512gb-purple",
"category": "phones",
"namespaceId": "apple-iphone-14",
"name": "Apple iPhone 14 512GB Purple",
- "capacityAvailable": ["128GB", "256GB", "512GB"],
+ "capacityAvailable": [
+ "128GB",
+ "256GB",
+ "512GB"
+ ],
"capacity": "512GB",
"priceRegular": 1600,
"priceDiscount": 1450,
- "colorsAvailable": ["midnight", "yellow", "purple"],
+ "colorsAvailable": [
+ "midnight",
+ "yellow",
+ "purple"
+ ],
"color": "purple",
"images": [
"img/phones/apple-iphone-14/purple/00.webp",
@@ -3777,18 +4954,34 @@
"ram": "6GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital 5x, Optical 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE", "5G"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE",
+ "5G"
+ ]
},
{
"id": "apple-iphone-14-pro-128gb-spaceblack",
"category": "phones",
"namespaceId": "apple-iphone-14-pro",
"name": "Apple iPhone 14 Pro 128GB Space Black",
- "capacityAvailable": ["128GB", "256GB", "512GB", "1TB"],
+ "capacityAvailable": [
+ "128GB",
+ "256GB",
+ "512GB",
+ "1TB"
+ ],
"capacity": "128GB",
"priceRegular": 1056,
"priceDiscount": 980,
- "colorsAvailable": ["spaceblack", "gold"],
+ "colorsAvailable": [
+ "spaceblack",
+ "gold"
+ ],
"color": "spaceblack",
"images": [
"img/phones/apple-iphone-14-pro/spaceblack/00.webp",
@@ -3824,18 +5017,34 @@
"ram": "6GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital 5x, Optical 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE", "5G"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE",
+ "5G"
+ ]
},
{
"id": "apple-iphone-14-pro-256gb-spaceblack",
"category": "phones",
"namespaceId": "apple-iphone-14-pro",
"name": "Apple iPhone 14 Pro 256GB Space Black",
- "capacityAvailable": ["128GB", "256GB", "512GB", "1TB"],
+ "capacityAvailable": [
+ "128GB",
+ "256GB",
+ "512GB",
+ "1TB"
+ ],
"capacity": "256GB",
"priceRegular": 1200,
"priceDiscount": 1160,
- "colorsAvailable": ["spaceblack", "gold"],
+ "colorsAvailable": [
+ "spaceblack",
+ "gold"
+ ],
"color": "spaceblack",
"images": [
"img/phones/apple-iphone-14-pro/spaceblack/00.webp",
@@ -3871,18 +5080,34 @@
"ram": "6GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital 5x, Optical 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE", "5G"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE",
+ "5G"
+ ]
},
{
"id": "apple-iphone-14-pro-512gb-spaceblack",
"category": "phones",
"namespaceId": "apple-iphone-14-pro",
"name": "Apple iPhone 14 Pro 512GB Space Black",
- "capacityAvailable": ["128GB", "256GB", "512GB", "1TB"],
+ "capacityAvailable": [
+ "128GB",
+ "256GB",
+ "512GB",
+ "1TB"
+ ],
"capacity": "512GB",
"priceRegular": 1466,
"priceDiscount": 1378,
- "colorsAvailable": ["spaceblack", "gold"],
+ "colorsAvailable": [
+ "spaceblack",
+ "gold"
+ ],
"color": "spaceblack",
"images": [
"img/phones/apple-iphone-14-pro/spaceblack/00.webp",
@@ -3918,18 +5143,34 @@
"ram": "6GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital 5x, Optical 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE", "5G"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE",
+ "5G"
+ ]
},
{
"id": "apple-iphone-14-pro-1tb-spaceblack",
"category": "phones",
"namespaceId": "apple-iphone-14-pro",
"name": "Apple iPhone 14 Pro 1TB Space Black",
- "capacityAvailable": ["128GB", "256GB", "512GB", "1TB"],
+ "capacityAvailable": [
+ "128GB",
+ "256GB",
+ "512GB",
+ "1TB"
+ ],
"capacity": "1TB",
"priceRegular": 1740,
"priceDiscount": 1520,
- "colorsAvailable": ["spaceblack", "gold"],
+ "colorsAvailable": [
+ "spaceblack",
+ "gold"
+ ],
"color": "spaceblack",
"images": [
"img/phones/apple-iphone-14-pro/spaceblack/00.webp",
@@ -3965,18 +5206,35 @@
"ram": "6GB",
"camera": "48 Mp + 12 Mp + 12MP + 12Mp",
"zoom": "Digital 5x, Optical 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE", "5G"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE",
+ "5G"
+ ]
},
{
"id": "apple-iphone-12-64gb-black",
"category": "phones",
"namespaceId": "apple-iphone-12",
"name": "Apple iPhone 12 64GB Black",
- "capacityAvailable": ["64GB", "128GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "128GB",
+ "256GB"
+ ],
"capacity": "64GB",
"priceRegular": 880,
"priceDiscount": 800,
- "colorsAvailable": ["black", "white", "purple", "red"],
+ "colorsAvailable": [
+ "black",
+ "white",
+ "purple",
+ "red"
+ ],
"color": "black",
"images": [
"img/phones/apple-iphone-12/black/00.webp",
@@ -4010,18 +5268,34 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp",
"zoom": "Optical, 2x; Digital, 5x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
{
"id": "apple-iphone-12-128gb-black",
"category": "phones",
"namespaceId": "apple-iphone-12",
"name": "Apple iPhone 12 128GB Black",
- "capacityAvailable": ["64GB", "128GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "128GB",
+ "256GB"
+ ],
"capacity": "128GB",
"priceRegular": 980,
"priceDiscount": 900,
- "colorsAvailable": ["black", "white", "purple", "red"],
+ "colorsAvailable": [
+ "black",
+ "white",
+ "purple",
+ "red"
+ ],
"color": "black",
"images": [
"img/phones/apple-iphone-12/black/00.webp",
@@ -4055,18 +5329,34 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp",
"zoom": "Optical, 2x; Digital, 5x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
{
"id": "apple-iphone-12-256gb-black",
"category": "phones",
"namespaceId": "apple-iphone-12",
"name": "Apple iPhone 12 256GB Black",
- "capacityAvailable": ["64GB", "128GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "128GB",
+ "256GB"
+ ],
"capacity": "256GB",
"priceRegular": 1180,
"priceDiscount": 1100,
- "colorsAvailable": ["black", "white", "purple", "red"],
+ "colorsAvailable": [
+ "black",
+ "white",
+ "purple",
+ "red"
+ ],
"color": "black",
"images": [
"img/phones/apple-iphone-12/black/00.webp",
@@ -4100,18 +5390,34 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp",
"zoom": "Optical, 2x; Digital, 5x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
{
"id": "apple-iphone-12-64gb-purple",
"category": "phones",
"namespaceId": "apple-iphone-12",
"name": "Apple iPhone 12 64GB Purple",
- "capacityAvailable": ["64GB", "128GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "128GB",
+ "256GB"
+ ],
"capacity": "64GB",
"priceRegular": 880,
"priceDiscount": 800,
- "colorsAvailable": ["black", "white", "purple", "red"],
+ "colorsAvailable": [
+ "black",
+ "white",
+ "purple",
+ "red"
+ ],
"color": "purple",
"images": [
"img/phones/apple-iphone-12/purple/00.webp",
@@ -4145,18 +5451,34 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp",
"zoom": "Optical, 2x; Digital, 5x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
{
"id": "apple-iphone-12-128gb-purple",
"category": "phones",
"namespaceId": "apple-iphone-12",
"name": "Apple iPhone 12 128GB Purple",
- "capacityAvailable": ["64GB", "128GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "128GB",
+ "256GB"
+ ],
"capacity": "128GB",
"priceRegular": 980,
"priceDiscount": 900,
- "colorsAvailable": ["black", "white", "purple", "red"],
+ "colorsAvailable": [
+ "black",
+ "white",
+ "purple",
+ "red"
+ ],
"color": "purple",
"images": [
"img/phones/apple-iphone-12/purple/00.webp",
@@ -4190,18 +5512,34 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp",
"zoom": "Optical, 2x; Digital, 5x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
{
"id": "apple-iphone-12-256gb-purple",
"category": "phones",
"namespaceId": "apple-iphone-12",
"name": "Apple iPhone 12 256GB Purple",
- "capacityAvailable": ["64GB", "128GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "128GB",
+ "256GB"
+ ],
"capacity": "256GB",
"priceRegular": 1180,
"priceDiscount": 1100,
- "colorsAvailable": ["black", "white", "purple", "red"],
+ "colorsAvailable": [
+ "black",
+ "white",
+ "purple",
+ "red"
+ ],
"color": "purple",
"images": [
"img/phones/apple-iphone-12/purple/00.webp",
@@ -4235,18 +5573,34 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp",
"zoom": "Optical, 2x; Digital, 5x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
{
"id": "apple-iphone-12-64gb-red",
"category": "phones",
"namespaceId": "apple-iphone-12",
"name": "Apple iPhone 12 64GB Red",
- "capacityAvailable": ["64GB", "128GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "128GB",
+ "256GB"
+ ],
"capacity": "64GB",
"priceRegular": 880,
"priceDiscount": 800,
- "colorsAvailable": ["black", "white", "purple", "red"],
+ "colorsAvailable": [
+ "black",
+ "white",
+ "purple",
+ "red"
+ ],
"color": "red",
"images": [
"img/phones/apple-iphone-12/red/00.webp",
@@ -4280,18 +5634,34 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp",
"zoom": "Optical, 2x; Digital, 5x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
{
"id": "apple-iphone-12-128gb-red",
"category": "phones",
"namespaceId": "apple-iphone-12",
"name": "Apple iPhone 12 128GB Red",
- "capacityAvailable": ["64GB", "128GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "128GB",
+ "256GB"
+ ],
"capacity": "128GB",
"priceRegular": 980,
"priceDiscount": 900,
- "colorsAvailable": ["black", "white", "purple", "red"],
+ "colorsAvailable": [
+ "black",
+ "white",
+ "purple",
+ "red"
+ ],
"color": "red",
"images": [
"img/phones/apple-iphone-12/red/00.webp",
@@ -4325,18 +5695,34 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp",
"zoom": "Optical, 2x; Digital, 5x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
{
"id": "apple-iphone-12-256gb-red",
"category": "phones",
"namespaceId": "apple-iphone-12",
"name": "Apple iPhone 12 256GB Red",
- "capacityAvailable": ["64GB", "128GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "128GB",
+ "256GB"
+ ],
"capacity": "256GB",
"priceRegular": 1180,
"priceDiscount": 1100,
- "colorsAvailable": ["black", "white", "purple", "red"],
+ "colorsAvailable": [
+ "black",
+ "white",
+ "purple",
+ "red"
+ ],
"color": "red",
"images": [
"img/phones/apple-iphone-12/red/00.webp",
@@ -4370,23 +5756,39 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp",
"zoom": "Optical, 2x; Digital, 5x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
{
"id": "apple-iphone-12-64gb-white",
"category": "phones",
"namespaceId": "apple-iphone-12",
"name": "Apple iPhone 12 64GB White",
- "capacityAvailable": ["64GB", "128GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "128GB",
+ "256GB"
+ ],
"capacity": "64GB",
"priceRegular": 880,
"priceDiscount": 800,
- "colorsAvailable": ["black", "white", "purple", "red"],
+ "colorsAvailable": [
+ "black",
+ "white",
+ "purple",
+ "red"
+ ],
"color": "white",
"images": [
"img/phones/apple-iphone-12/white/00.webp",
"img/phones/apple-iphone-12/white/01.webp",
- "img/phones/apple-iphone-12/white/02.webp",
+ "img/phones/apple-iphone-12/white/04.webp",
"img/phones/apple-iphone-12/white/03.webp"
],
"description": [
@@ -4415,23 +5817,39 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp",
"zoom": "Optical, 2x; Digital, 5x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
{
"id": "apple-iphone-12-128gb-white",
"category": "phones",
"namespaceId": "apple-iphone-12",
"name": "Apple iPhone 12 128GB White",
- "capacityAvailable": ["64GB", "128GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "128GB",
+ "256GB"
+ ],
"capacity": "128GB",
"priceRegular": 980,
"priceDiscount": 900,
- "colorsAvailable": ["black", "white", "purple", "red"],
+ "colorsAvailable": [
+ "black",
+ "white",
+ "purple",
+ "red"
+ ],
"color": "white",
"images": [
"img/phones/apple-iphone-12/white/00.webp",
"img/phones/apple-iphone-12/white/01.webp",
- "img/phones/apple-iphone-12/white/02.webp",
+ "img/phones/apple-iphone-12/white/04.webp",
"img/phones/apple-iphone-12/white/03.webp"
],
"description": [
@@ -4460,23 +5878,39 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp",
"zoom": "Optical, 2x; Digital, 5x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
{
"id": "apple-iphone-12-256gb-white",
"category": "phones",
"namespaceId": "apple-iphone-12",
"name": "Apple iPhone 12 256GB White",
- "capacityAvailable": ["64GB", "128GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "128GB",
+ "256GB"
+ ],
"capacity": "256GB",
"priceRegular": 1180,
"priceDiscount": 1100,
- "colorsAvailable": ["black", "white", "purple", "red"],
+ "colorsAvailable": [
+ "black",
+ "white",
+ "purple",
+ "red"
+ ],
"color": "white",
"images": [
"img/phones/apple-iphone-12/white/00.webp",
"img/phones/apple-iphone-12/white/01.webp",
- "img/phones/apple-iphone-12/white/02.webp",
+ "img/phones/apple-iphone-12/white/04.webp",
"img/phones/apple-iphone-12/white/03.webp"
],
"description": [
@@ -4505,18 +5939,34 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp",
"zoom": "Optical, 2x; Digital, 5x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE"
+ ]
},
{
"id": "apple-iphone-13-mini-64gb-midnight",
"category": "phones",
"namespaceId": "apple-iphone-13-mini",
"name": "Apple iPhone 13 Mini 64GB Midnight",
- "capacityAvailable": ["64GB", "128GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "128GB",
+ "256GB"
+ ],
"capacity": "64GB",
"priceRegular": 880,
"priceDiscount": 800,
- "colorsAvailable": ["midnight", "white", "blue", "pink"],
+ "colorsAvailable": [
+ "midnight",
+ "white",
+ "blue",
+ "pink"
+ ],
"color": "midnight",
"images": [
"img/phones/apple-iphone-13-mini/midnight/00.webp",
@@ -4550,18 +6000,34 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp",
"zoom": "Optical, 2x; Digital, 5x",
- "cell": ["GSM", "CDMA", "HSPA", "EVDO", "LTE", "5G"]
+ "cell": [
+ "GSM",
+ "CDMA",
+ "HSPA",
+ "EVDO",
+ "LTE",
+ "5G"
+ ]
},
{
"id": "apple-iphone-13-mini-128gb-midnight",
"category": "phones",
"namespaceId": "apple-iphone-13-mini",
"name": "Apple iPhone 13 Mini 128GB Midnight",
- "capacityAvailable": ["64GB", "128GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "128GB",
+ "256GB"
+ ],
"capacity": "128GB",
"priceRegular": 980,
"priceDiscount": 900,
- "colorsAvailable": ["midnight", "white", "blue", "pink"],
+ "colorsAvailable": [
+ "midnight",
+ "white",
+ "blue",
+ "pink"
+ ],
"color": "midnight",
"images": [
"img/phones/apple-iphone-13-mini/midnight/00.webp",
@@ -4595,18 +6061,34 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp",
"zoom": "Optical, 2x; Digital, 5x",
- "cell": ["GSM", "CDMA", "HSPA", "EVDO", "LTE", "5G"]
+ "cell": [
+ "GSM",
+ "CDMA",
+ "HSPA",
+ "EVDO",
+ "LTE",
+ "5G"
+ ]
},
{
"id": "apple-iphone-13-mini-256gb-midnight",
"category": "phones",
"namespaceId": "apple-iphone-13-mini",
"name": "Apple iPhone 13 Mini 256GB Midnight",
- "capacityAvailable": ["64GB", "128GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "128GB",
+ "256GB"
+ ],
"capacity": "256GB",
"priceRegular": 1180,
"priceDiscount": 1100,
- "colorsAvailable": ["midnight", "white", "blue", "pink"],
+ "colorsAvailable": [
+ "midnight",
+ "white",
+ "blue",
+ "pink"
+ ],
"color": "midnight",
"images": [
"img/phones/apple-iphone-13-mini/midnight/00.webp",
@@ -4640,18 +6122,34 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp",
"zoom": "Optical, 2x; Digital, 5x",
- "cell": ["GSM", "CDMA", "HSPA", "EVDO", "LTE", "5G"]
+ "cell": [
+ "GSM",
+ "CDMA",
+ "HSPA",
+ "EVDO",
+ "LTE",
+ "5G"
+ ]
},
{
"id": "apple-iphone-13-mini-64gb-pink",
"category": "phones",
"namespaceId": "apple-iphone-13-mini",
"name": "Apple iPhone 13 Mini 64GB Pink",
- "capacityAvailable": ["64GB", "128GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "128GB",
+ "256GB"
+ ],
"capacity": "64GB",
"priceRegular": 880,
"priceDiscount": 800,
- "colorsAvailable": ["midnight", "white", "blue", "pink"],
+ "colorsAvailable": [
+ "midnight",
+ "white",
+ "blue",
+ "pink"
+ ],
"color": "pink",
"images": [
"img/phones/apple-iphone-13-mini/pink/00.webp",
@@ -4685,18 +6183,34 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp",
"zoom": "Optical, 2x; Digital, 5x",
- "cell": ["GSM", "CDMA", "HSPA", "EVDO", "LTE", "5G"]
+ "cell": [
+ "GSM",
+ "CDMA",
+ "HSPA",
+ "EVDO",
+ "LTE",
+ "5G"
+ ]
},
{
"id": "apple-iphone-13-mini-128gb-pink",
"category": "phones",
"namespaceId": "apple-iphone-13-mini",
"name": "Apple iPhone 13 Mini 128GB Pink",
- "capacityAvailable": ["64GB", "128GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "128GB",
+ "256GB"
+ ],
"capacity": "128GB",
"priceRegular": 980,
"priceDiscount": 900,
- "colorsAvailable": ["midnight", "white", "blue", "pink"],
+ "colorsAvailable": [
+ "midnight",
+ "white",
+ "blue",
+ "pink"
+ ],
"color": "pink",
"images": [
"img/phones/apple-iphone-13-mini/pink/00.webp",
@@ -4730,18 +6244,34 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp",
"zoom": "Optical, 2x; Digital, 5x",
- "cell": ["GSM", "CDMA", "HSPA", "EVDO", "LTE", "5G"]
+ "cell": [
+ "GSM",
+ "CDMA",
+ "HSPA",
+ "EVDO",
+ "LTE",
+ "5G"
+ ]
},
{
"id": "apple-iphone-13-mini-256gb-pink",
"category": "phones",
"namespaceId": "apple-iphone-13-mini",
"name": "Apple iPhone 13 Mini 256GB Pink",
- "capacityAvailable": ["64GB", "128GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "128GB",
+ "256GB"
+ ],
"capacity": "256GB",
"priceRegular": 1180,
"priceDiscount": 1100,
- "colorsAvailable": ["midnight", "white", "blue", "pink"],
+ "colorsAvailable": [
+ "midnight",
+ "white",
+ "blue",
+ "pink"
+ ],
"color": "pink",
"images": [
"img/phones/apple-iphone-13-mini/pink/00.webp",
@@ -4775,18 +6305,34 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp",
"zoom": "Optical, 2x; Digital, 5x",
- "cell": ["GSM", "CDMA", "HSPA", "EVDO", "LTE", "5G"]
+ "cell": [
+ "GSM",
+ "CDMA",
+ "HSPA",
+ "EVDO",
+ "LTE",
+ "5G"
+ ]
},
{
"id": "apple-iphone-13-mini-64gb-white",
"category": "phones",
"namespaceId": "apple-iphone-13-mini",
"name": "Apple iPhone 13 Mini 64GB White",
- "capacityAvailable": ["64GB", "128GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "128GB",
+ "256GB"
+ ],
"capacity": "64GB",
"priceRegular": 880,
"priceDiscount": 800,
- "colorsAvailable": ["midnight", "white", "blue", "pink"],
+ "colorsAvailable": [
+ "midnight",
+ "white",
+ "blue",
+ "pink"
+ ],
"color": "white",
"images": [
"img/phones/apple-iphone-13-mini/white/00.webp",
@@ -4820,18 +6366,34 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp",
"zoom": "Optical, 2x; Digital, 5x",
- "cell": ["GSM", "CDMA", "HSPA", "EVDO", "LTE", "5G"]
+ "cell": [
+ "GSM",
+ "CDMA",
+ "HSPA",
+ "EVDO",
+ "LTE",
+ "5G"
+ ]
},
{
"id": "apple-iphone-13-mini-128gb-white",
"category": "phones",
"namespaceId": "apple-iphone-13-mini",
"name": "Apple iPhone 13 Mini 128GB White",
- "capacityAvailable": ["64GB", "128GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "128GB",
+ "256GB"
+ ],
"capacity": "128GB",
"priceRegular": 980,
"priceDiscount": 900,
- "colorsAvailable": ["midnight", "white", "blue", "pink"],
+ "colorsAvailable": [
+ "midnight",
+ "white",
+ "blue",
+ "pink"
+ ],
"color": "white",
"images": [
"img/phones/apple-iphone-13-mini/white/00.webp",
@@ -4865,18 +6427,34 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp",
"zoom": "Optical, 2x; Digital, 5x",
- "cell": ["GSM", "CDMA", "HSPA", "EVDO", "LTE", "5G"]
+ "cell": [
+ "GSM",
+ "CDMA",
+ "HSPA",
+ "EVDO",
+ "LTE",
+ "5G"
+ ]
},
{
"id": "apple-iphone-13-mini-256gb-white",
"category": "phones",
"namespaceId": "apple-iphone-13-mini",
"name": "Apple iPhone 13 Mini 256GB White",
- "capacityAvailable": ["64GB", "128GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "128GB",
+ "256GB"
+ ],
"capacity": "256GB",
"priceRegular": 999,
"priceDiscount": 949,
- "colorsAvailable": ["midnight", "white", "blue", "pink"],
+ "colorsAvailable": [
+ "midnight",
+ "white",
+ "blue",
+ "pink"
+ ],
"color": "white",
"images": [
"img/phones/apple-iphone-13-mini/white/00.webp",
@@ -4910,18 +6488,34 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp",
"zoom": "Optical, 2x; Digital, 5x",
- "cell": ["GSM", "CDMA", "HSPA", "EVDO", "LTE", "5G"]
+ "cell": [
+ "GSM",
+ "CDMA",
+ "HSPA",
+ "EVDO",
+ "LTE",
+ "5G"
+ ]
},
{
"id": "apple-iphone-13-mini-64gb-blue",
"category": "phones",
"namespaceId": "apple-iphone-13-mini",
"name": "Apple iPhone 13 Mini 64GB Blue",
- "capacityAvailable": ["64GB", "128GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "128GB",
+ "256GB"
+ ],
"capacity": "64GB",
"priceRegular": 880,
"priceDiscount": 800,
- "colorsAvailable": ["midnight", "white", "blue", "pink"],
+ "colorsAvailable": [
+ "midnight",
+ "white",
+ "blue",
+ "pink"
+ ],
"color": "blue",
"images": [
"img/phones/apple-iphone-13-mini/blue/00.webp",
@@ -4955,18 +6549,34 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp",
"zoom": "Optical, 2x; Digital, 5x",
- "cell": ["GSM", "CDMA", "HSPA", "EVDO", "LTE", "5G"]
+ "cell": [
+ "GSM",
+ "CDMA",
+ "HSPA",
+ "EVDO",
+ "LTE",
+ "5G"
+ ]
},
{
"id": "apple-iphone-13-mini-128gb-blue",
"category": "phones",
"namespaceId": "apple-iphone-13-mini",
"name": "Apple iPhone 13 Mini 128GB Blue",
- "capacityAvailable": ["64GB", "128GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "128GB",
+ "256GB"
+ ],
"capacity": "128GB",
"priceRegular": 980,
"priceDiscount": 900,
- "colorsAvailable": ["midnight", "white", "blue", "pink"],
+ "colorsAvailable": [
+ "midnight",
+ "white",
+ "blue",
+ "pink"
+ ],
"color": "blue",
"images": [
"img/phones/apple-iphone-13-mini/blue/00.webp",
@@ -5000,18 +6610,34 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp",
"zoom": "Optical, 2x; Digital, 5x",
- "cell": ["GSM", "CDMA", "HSPA", "EVDO", "LTE", "5G"]
+ "cell": [
+ "GSM",
+ "CDMA",
+ "HSPA",
+ "EVDO",
+ "LTE",
+ "5G"
+ ]
},
{
"id": "apple-iphone-13-mini-256gb-blue",
"category": "phones",
"namespaceId": "apple-iphone-13-mini",
"name": "Apple iPhone 13 Mini 256GB Blue",
- "capacityAvailable": ["64GB", "128GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "128GB",
+ "256GB"
+ ],
"capacity": "256GB",
"priceRegular": 999,
"priceDiscount": 949,
- "colorsAvailable": ["midnight", "white", "blue", "pink"],
+ "colorsAvailable": [
+ "midnight",
+ "white",
+ "blue",
+ "pink"
+ ],
"color": "blue",
"images": [
"img/phones/apple-iphone-13-mini/blue/00.webp",
@@ -5045,18 +6671,34 @@
"ram": "4GB",
"camera": "12 Mp + 12 Mp",
"zoom": "Optical, 2x; Digital, 5x",
- "cell": ["GSM", "CDMA", "HSPA", "EVDO", "LTE", "5G"]
+ "cell": [
+ "GSM",
+ "CDMA",
+ "HSPA",
+ "EVDO",
+ "LTE",
+ "5G"
+ ]
},
{
"id": "apple-iphone-13-pro-max-128gb-sierrablue",
"category": "phones",
"namespaceId": "apple-iphone-13-pro-max",
"name": "Apple iPhone 13 Pro Max 128GB Sierra Blue",
- "capacityAvailable": ["128GB", "256GB", "512GB", "1TB"],
+ "capacityAvailable": [
+ "128GB",
+ "256GB",
+ "512GB",
+ "1TB"
+ ],
"capacity": "128GB",
"priceRegular": 1286,
"priceDiscount": 1260,
- "colorsAvailable": ["graphite", "gold", "sierrablue"],
+ "colorsAvailable": [
+ "graphite",
+ "gold",
+ "sierrablue"
+ ],
"color": "sierrablue",
"images": [
"img/phones/apple-iphone-13-pro-max/sierrablue/00.webp",
@@ -5096,18 +6738,34 @@
"ram": "6GB",
"camera": "12 Mp + 12 Mp + 12 Mp",
"zoom": "Optical, 3x; Digital, up to 15x",
- "cell": ["GSM", "CDMA", "HSPA", "EVDO", "LTE", "5G"]
+ "cell": [
+ "GSM",
+ "CDMA",
+ "HSPA",
+ "EVDO",
+ "LTE",
+ "5G"
+ ]
},
{
"id": "apple-iphone-13-pro-max-256gb-sierrablue",
"category": "phones",
"namespaceId": "apple-iphone-13-pro-max",
"name": "Apple iPhone 13 Pro Max 256GB Sierra Blue",
- "capacityAvailable": ["128GB", "256GB", "512GB", "1TB"],
+ "capacityAvailable": [
+ "128GB",
+ "256GB",
+ "512GB",
+ "1TB"
+ ],
"capacity": "256GB",
"priceRegular": 1399,
"priceDiscount": 1379,
- "colorsAvailable": ["graphite", "gold", "sierrablue"],
+ "colorsAvailable": [
+ "graphite",
+ "gold",
+ "sierrablue"
+ ],
"color": "sierrablue",
"images": [
"img/phones/apple-iphone-13-pro-max/sierrablue/00.webp",
@@ -5147,18 +6805,34 @@
"ram": "6GB",
"camera": "12 Mp + 12 Mp + 12 Mp",
"zoom": "Optical, 3x; Digital, up to 15x",
- "cell": ["GSM", "CDMA", "HSPA", "EVDO", "LTE", "5G"]
+ "cell": [
+ "GSM",
+ "CDMA",
+ "HSPA",
+ "EVDO",
+ "LTE",
+ "5G"
+ ]
},
{
"id": "apple-iphone-13-pro-max-512gb-sierrablue",
"category": "phones",
"namespaceId": "apple-iphone-13-pro-max",
"name": "Apple iPhone 13 Pro Max 512GB Sierra Blue",
- "capacityAvailable": ["128GB", "256GB", "512GB", "1TB"],
+ "capacityAvailable": [
+ "128GB",
+ "256GB",
+ "512GB",
+ "1TB"
+ ],
"capacity": "512GB",
"priceRegular": 1426,
"priceDiscount": 1371,
- "colorsAvailable": ["graphite", "gold", "sierrablue"],
+ "colorsAvailable": [
+ "graphite",
+ "gold",
+ "sierrablue"
+ ],
"color": "sierrablue",
"images": [
"img/phones/apple-iphone-13-pro-max/sierrablue/00.webp",
@@ -5198,18 +6872,34 @@
"ram": "6GB",
"camera": "12 Mp + 12 Mp + 12 Mp",
"zoom": "Optical, 3x; Digital, up to 15x",
- "cell": ["GSM", "CDMA", "HSPA", "EVDO", "LTE", "5G"]
+ "cell": [
+ "GSM",
+ "CDMA",
+ "HSPA",
+ "EVDO",
+ "LTE",
+ "5G"
+ ]
},
{
"id": "apple-iphone-13-pro-max-1tb-sierrablue",
"category": "phones",
"namespaceId": "apple-iphone-13-pro-max",
"name": "Apple iPhone 13 Pro Max 1TB Sierra Blue",
- "capacityAvailable": ["128GB", "256GB", "512GB", "1TB"],
+ "capacityAvailable": [
+ "128GB",
+ "256GB",
+ "512GB",
+ "1TB"
+ ],
"capacity": "1TB",
"priceRegular": 1700,
"priceDiscount": 1540,
- "colorsAvailable": ["graphite", "gold", "sierrablue"],
+ "colorsAvailable": [
+ "graphite",
+ "gold",
+ "sierrablue"
+ ],
"color": "sierrablue",
"images": [
"img/phones/apple-iphone-13-pro-max/sierrablue/00.webp",
@@ -5244,18 +6934,35 @@
"ram": "6GB",
"camera": "48 Mp + 12 Mp + 12MP + 12Mp",
"zoom": "Digital 5x, Optical 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE", "5G"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE",
+ "5G"
+ ]
},
{
"id": "apple-iphone-13-pro-max-128gb-graphite",
"category": "phones",
"namespaceId": "apple-iphone-13-pro-max",
"name": "Apple iPhone 13 Pro Max 128GB Graphite",
- "capacityAvailable": ["128GB", "256GB", "512GB", "1TB"],
+ "capacityAvailable": [
+ "128GB",
+ "256GB",
+ "512GB",
+ "1TB"
+ ],
"capacity": "128GB",
"priceRegular": 1286,
"priceDiscount": 1260,
- "colorsAvailable": ["graphite", "gold", "sierrablue"],
+ "colorsAvailable": [
+ "graphite",
+ "gold",
+ "sierrablue"
+ ],
"color": "graphite",
"images": [
"img/phones/apple-iphone-13-pro-max/graphite/00.webp",
@@ -5295,18 +7002,34 @@
"ram": "6GB",
"camera": "12 Mp + 12 Mp + 12 Mp",
"zoom": "Optical, 3x; Digital, up to 15x",
- "cell": ["GSM", "CDMA", "HSPA", "EVDO", "LTE", "5G"]
+ "cell": [
+ "GSM",
+ "CDMA",
+ "HSPA",
+ "EVDO",
+ "LTE",
+ "5G"
+ ]
},
{
"id": "apple-iphone-13-pro-max-256gb-graphite",
"category": "phones",
"namespaceId": "apple-iphone-13-pro-max",
"name": "Apple iPhone 13 Pro Max 256GB Graphite",
- "capacityAvailable": ["128GB", "256GB", "512GB", "1TB"],
+ "capacityAvailable": [
+ "128GB",
+ "256GB",
+ "512GB",
+ "1TB"
+ ],
"capacity": "256GB",
"priceRegular": 1399,
"priceDiscount": 1379,
- "colorsAvailable": ["graphite", "gold", "sierrablue"],
+ "colorsAvailable": [
+ "graphite",
+ "gold",
+ "sierrablue"
+ ],
"color": "graphite",
"images": [
"img/phones/apple-iphone-13-pro-max/graphite/00.webp",
@@ -5346,18 +7069,34 @@
"ram": "6GB",
"camera": "12 Mp + 12 Mp + 12 Mp",
"zoom": "Optical, 3x; Digital, up to 15x",
- "cell": ["GSM", "CDMA", "HSPA", "EVDO", "LTE", "5G"]
+ "cell": [
+ "GSM",
+ "CDMA",
+ "HSPA",
+ "EVDO",
+ "LTE",
+ "5G"
+ ]
},
{
"id": "apple-iphone-13-pro-max-512gb-graphite",
"category": "phones",
"namespaceId": "apple-iphone-13-pro-max",
"name": "Apple iPhone 13 Pro Max 512GB Graphite",
- "capacityAvailable": ["128GB", "256GB", "512GB", "1TB"],
+ "capacityAvailable": [
+ "128GB",
+ "256GB",
+ "512GB",
+ "1TB"
+ ],
"capacity": "512GB",
"priceRegular": 1426,
"priceDiscount": 1371,
- "colorsAvailable": ["graphite", "gold", "sierrablue"],
+ "colorsAvailable": [
+ "graphite",
+ "gold",
+ "sierrablue"
+ ],
"color": "graphite",
"images": [
"img/phones/apple-iphone-13-pro-max/graphite/00.webp",
@@ -5397,18 +7136,34 @@
"ram": "6GB",
"camera": "12 Mp + 12 Mp + 12 Mp",
"zoom": "Optical, 3x; Digital, up to 15x",
- "cell": ["GSM", "CDMA", "HSPA", "EVDO", "LTE", "5G"]
+ "cell": [
+ "GSM",
+ "CDMA",
+ "HSPA",
+ "EVDO",
+ "LTE",
+ "5G"
+ ]
},
{
"id": "apple-iphone-13-pro-max-1tb-graphite",
"category": "phones",
"namespaceId": "apple-iphone-13-pro-max",
"name": "Apple iPhone 13 Pro Max 1TB Graphite",
- "capacityAvailable": ["128GB", "256GB", "512GB", "1TB"],
+ "capacityAvailable": [
+ "128GB",
+ "256GB",
+ "512GB",
+ "1TB"
+ ],
"capacity": "1TB",
"priceRegular": 1700,
"priceDiscount": 1540,
- "colorsAvailable": ["graphite", "gold", "sierrablue"],
+ "colorsAvailable": [
+ "graphite",
+ "gold",
+ "sierrablue"
+ ],
"color": "graphite",
"images": [
"img/phones/apple-iphone-13-pro-max/graphite/00.webp",
@@ -5443,18 +7198,35 @@
"ram": "6GB",
"camera": "48 Mp + 12 Mp + 12MP + 12Mp",
"zoom": "Digital 5x, Optical 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE", "5G"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE",
+ "5G"
+ ]
},
{
"id": "apple-iphone-13-pro-max-128gb-gold",
"category": "phones",
"namespaceId": "apple-iphone-13-pro-max",
"name": "Apple iPhone 13 Pro Max 128GB Gold",
- "capacityAvailable": ["128GB", "256GB", "512GB", "1TB"],
+ "capacityAvailable": [
+ "128GB",
+ "256GB",
+ "512GB",
+ "1TB"
+ ],
"capacity": "128GB",
"priceRegular": 1286,
"priceDiscount": 1260,
- "colorsAvailable": ["graphite", "gold", "sierrablue"],
+ "colorsAvailable": [
+ "graphite",
+ "gold",
+ "sierrablue"
+ ],
"color": "gold",
"images": [
"img/phones/apple-iphone-13-pro-max/gold/00.webp",
@@ -5494,18 +7266,34 @@
"ram": "6GB",
"camera": "12 Mp + 12 Mp + 12 Mp",
"zoom": "Optical, 3x; Digital, up to 15x",
- "cell": ["GSM", "CDMA", "HSPA", "EVDO", "LTE", "5G"]
+ "cell": [
+ "GSM",
+ "CDMA",
+ "HSPA",
+ "EVDO",
+ "LTE",
+ "5G"
+ ]
},
{
"id": "apple-iphone-13-pro-max-256gb-gold",
"category": "phones",
"namespaceId": "apple-iphone-13-pro-max",
"name": "Apple iPhone 13 Pro Max 256GB Gold",
- "capacityAvailable": ["128GB", "256GB", "512GB", "1TB"],
+ "capacityAvailable": [
+ "128GB",
+ "256GB",
+ "512GB",
+ "1TB"
+ ],
"capacity": "256GB",
"priceRegular": 1399,
"priceDiscount": 1379,
- "colorsAvailable": ["graphite", "gold", "sierrablue"],
+ "colorsAvailable": [
+ "graphite",
+ "gold",
+ "sierrablue"
+ ],
"color": "gold",
"images": [
"img/phones/apple-iphone-13-pro-max/gold/00.webp",
@@ -5545,18 +7333,34 @@
"ram": "6GB",
"camera": "12 Mp + 12 Mp + 12 Mp",
"zoom": "Optical, 3x; Digital, up to 15x",
- "cell": ["GSM", "CDMA", "HSPA", "EVDO", "LTE", "5G"]
+ "cell": [
+ "GSM",
+ "CDMA",
+ "HSPA",
+ "EVDO",
+ "LTE",
+ "5G"
+ ]
},
{
"id": "apple-iphone-13-pro-max-512gb-gold",
"category": "phones",
"namespaceId": "apple-iphone-13-pro-max",
"name": "Apple iPhone 13 Pro Max 512GB Gold",
- "capacityAvailable": ["128GB", "256GB", "512GB", "1TB"],
+ "capacityAvailable": [
+ "128GB",
+ "256GB",
+ "512GB",
+ "1TB"
+ ],
"capacity": "512GB",
"priceRegular": 1426,
"priceDiscount": 1371,
- "colorsAvailable": ["graphite", "gold", "sierrablue"],
+ "colorsAvailable": [
+ "graphite",
+ "gold",
+ "sierrablue"
+ ],
"color": "gold",
"images": [
"img/phones/apple-iphone-13-pro-max/gold/00.webp",
@@ -5596,18 +7400,34 @@
"ram": "6GB",
"camera": "12 Mp + 12 Mp + 12 Mp",
"zoom": "Optical, 3x; Digital, up to 15x",
- "cell": ["GSM", "CDMA", "HSPA", "EVDO", "LTE", "5G"]
+ "cell": [
+ "GSM",
+ "CDMA",
+ "HSPA",
+ "EVDO",
+ "LTE",
+ "5G"
+ ]
},
{
"id": "apple-iphone-13-pro-max-1tb-gold",
"category": "phones",
"namespaceId": "apple-iphone-13-pro-max",
"name": "Apple iPhone 13 Pro Max 1TB Gold",
- "capacityAvailable": ["128GB", "256GB", "512GB", "1TB"],
+ "capacityAvailable": [
+ "128GB",
+ "256GB",
+ "512GB",
+ "1TB"
+ ],
"capacity": "1TB",
"priceRegular": 1700,
"priceDiscount": 1540,
- "colorsAvailable": ["graphite", "gold", "sierrablue"],
+ "colorsAvailable": [
+ "graphite",
+ "gold",
+ "sierrablue"
+ ],
"color": "gold",
"images": [
"img/phones/apple-iphone-13-pro-max/gold/00.webp",
@@ -5642,18 +7462,34 @@
"ram": "6GB",
"camera": "48 Mp + 12 Mp + 12MP + 12Mp",
"zoom": "Digital 5x, Optical 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE", "5G"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE",
+ "5G"
+ ]
},
{
"id": "apple-iphone-14-pro-128gb-gold",
"category": "phones",
"namespaceId": "apple-iphone-14-pro",
"name": "Apple iPhone 14 Pro 128GB Gold",
- "capacityAvailable": ["128GB", "256GB", "512GB", "1TB"],
+ "capacityAvailable": [
+ "128GB",
+ "256GB",
+ "512GB",
+ "1TB"
+ ],
"capacity": "128GB",
"priceRegular": 1056,
"priceDiscount": 980,
- "colorsAvailable": ["spaceblack", "gold"],
+ "colorsAvailable": [
+ "spaceblack",
+ "gold"
+ ],
"color": "gold",
"images": [
"img/phones/apple-iphone-14-pro/gold/00.webp",
@@ -5689,18 +7525,34 @@
"ram": "6GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital 5x, Optical 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE", "5G"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE",
+ "5G"
+ ]
},
{
"id": "apple-iphone-14-pro-256gb-gold",
"category": "phones",
"namespaceId": "apple-iphone-14-pro",
"name": "Apple iPhone 14 Pro 256GB Gold",
- "capacityAvailable": ["128GB", "256GB", "512GB", "1TB"],
+ "capacityAvailable": [
+ "128GB",
+ "256GB",
+ "512GB",
+ "1TB"
+ ],
"capacity": "256GB",
"priceRegular": 1200,
"priceDiscount": 1160,
- "colorsAvailable": ["spaceblack", "gold"],
+ "colorsAvailable": [
+ "spaceblack",
+ "gold"
+ ],
"color": "gold",
"images": [
"img/phones/apple-iphone-14-pro/gold/00.webp",
@@ -5736,18 +7588,34 @@
"ram": "6GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital 5x, Optical 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE", "5G"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE",
+ "5G"
+ ]
},
{
- "id": "apple-iphone-14-pro-512gb",
+ "id": "apple-iphone-14-pro-512gb-gold",
"category": "phones",
"namespaceId": "apple-iphone-14-pro",
- "name": "Apple iPhone 14 Pro 512GB Space Black",
- "capacityAvailable": ["128GB", "256GB", "512GB", "1TB"],
+ "name": "Apple iPhone 14 Pro 512GB Gold",
+ "capacityAvailable": [
+ "128GB",
+ "256GB",
+ "512GB",
+ "1TB"
+ ],
"capacity": "512GB",
"priceRegular": 1466,
"priceDiscount": 1378,
- "colorsAvailable": ["spaceblack", "gold"],
+ "colorsAvailable": [
+ "spaceblack",
+ "gold"
+ ],
"color": "gold",
"images": [
"img/phones/apple-iphone-14-pro/gold/00.webp",
@@ -5783,18 +7651,34 @@
"ram": "6GB",
"camera": "12 Mp + 12 Mp + 12MP",
"zoom": "Digital 5x, Optical 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE", "5G"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE",
+ "5G"
+ ]
},
{
"id": "apple-iphone-14-pro-1tb-gold",
"category": "phones",
"namespaceId": "apple-iphone-14-pro",
"name": "Apple iPhone 14 Pro 1TB Gold",
- "capacityAvailable": ["128GB", "256GB", "512GB", "1TB"],
+ "capacityAvailable": [
+ "128GB",
+ "256GB",
+ "512GB",
+ "1TB"
+ ],
"capacity": "1TB",
"priceRegular": 1740,
"priceDiscount": 1520,
- "colorsAvailable": ["spaceblack", "gold"],
+ "colorsAvailable": [
+ "spaceblack",
+ "gold"
+ ],
"color": "gold",
"images": [
"img/phones/apple-iphone-14-pro/gold/00.webp",
@@ -5830,6 +7714,14 @@
"ram": "6GB",
"camera": "48 Mp + 12 Mp + 12MP + 12Mp",
"zoom": "Digital 5x, Optical 2x",
- "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE", "5G"]
+ "cell": [
+ "GPRS",
+ "EDGE",
+ "WCDMA",
+ "UMTS",
+ "HSPA",
+ "LTE",
+ "5G"
+ ]
}
]
diff --git a/public/api/tablets.json b/public/api/tablets.json
index dc555396f72..ac8e66aa6c6 100644
--- a/public/api/tablets.json
+++ b/public/api/tablets.json
@@ -4,11 +4,20 @@
"category": "tablets",
"namespaceId": "apple-ipad-pro-11-2021",
"name": "Apple iPad Pro 11 (2021) 128GB Space Gray",
- "capacityAvailable": ["128GB", "256GB", "512GB", "1TB", "2TB"],
+ "capacityAvailable": [
+ "128GB",
+ "256GB",
+ "512GB",
+ "1TB",
+ "2TB"
+ ],
"capacity": "128GB",
"priceRegular": 799,
"priceDiscount": 749,
- "colorsAvailable": ["spacegray", "silver"],
+ "colorsAvailable": [
+ "spacegray",
+ "silver"
+ ],
"color": "spacegray",
"images": [
"img/tablets/apple-ipad-pro-11-2021/spacegray/00.webp",
@@ -44,18 +53,29 @@
"ram": "8GB",
"camera": "12MP + 12MP",
"zoom": "Digital zoom up to 5x",
- "cell": ["Not applicable"]
+ "cell": [
+ "Not applicable"
+ ]
},
{
"id": "apple-ipad-pro-11-2021-256gb-spacegray",
"category": "tablets",
"namespaceId": "apple-ipad-pro-11-2021",
"name": "Apple iPad Pro 11 (2021) 256GB Space Gray",
- "capacityAvailable": ["128GB", "256GB", "512GB", "1TB", "2TB"],
+ "capacityAvailable": [
+ "128GB",
+ "256GB",
+ "512GB",
+ "1TB",
+ "2TB"
+ ],
"capacity": "256GB",
"priceRegular": 829,
"priceDiscount": 799,
- "colorsAvailable": ["spacegray", "silver"],
+ "colorsAvailable": [
+ "spacegray",
+ "silver"
+ ],
"color": "spacegray",
"images": [
"img/tablets/apple-ipad-pro-11-2021/spacegray/00.webp",
@@ -91,18 +111,29 @@
"ram": "8GB",
"camera": "12MP + 12MP",
"zoom": "Digital zoom up to 5x",
- "cell": ["Not applicable"]
+ "cell": [
+ "Not applicable"
+ ]
},
{
"id": "apple-ipad-pro-11-2021-512gb-spacegray",
"category": "tablets",
"namespaceId": "apple-ipad-pro-11-2021",
"name": "Apple iPad Pro 11 (2021) 512GB Space Gray",
- "capacityAvailable": ["128GB", "256GB", "512GB", "1TB", "2TB"],
+ "capacityAvailable": [
+ "128GB",
+ "256GB",
+ "512GB",
+ "1TB",
+ "2TB"
+ ],
"capacity": "512GB",
"priceRegular": 869,
"priceDiscount": 819,
- "colorsAvailable": ["spacegray", "silver"],
+ "colorsAvailable": [
+ "spacegray",
+ "silver"
+ ],
"color": "spacegray",
"images": [
"img/tablets/apple-ipad-pro-11-2021/spacegray/00.webp",
@@ -138,18 +169,29 @@
"ram": "8GB",
"camera": "12MP + 12MP",
"zoom": "Digital zoom up to 5x",
- "cell": ["Not applicable"]
+ "cell": [
+ "Not applicable"
+ ]
},
{
"id": "apple-ipad-pro-11-2021-1tb-spacegray",
"category": "tablets",
"namespaceId": "apple-ipad-pro-11-2021",
"name": "Apple iPad Pro 11 (2021) 1TB Space Gray",
- "capacityAvailable": ["128GB", "256GB", "512GB", "1TB", "2TB"],
+ "capacityAvailable": [
+ "128GB",
+ "256GB",
+ "512GB",
+ "1TB",
+ "2TB"
+ ],
"capacity": "1TB",
"priceRegular": 899,
"priceDiscount": 879,
- "colorsAvailable": ["spacegray", "silver"],
+ "colorsAvailable": [
+ "spacegray",
+ "silver"
+ ],
"color": "spacegray",
"images": [
"img/tablets/apple-ipad-pro-11-2021/spacegray/00.webp",
@@ -185,18 +227,29 @@
"ram": "16GB",
"camera": "12MP + 12MP",
"zoom": "Digital zoom up to 5x",
- "cell": ["Not applicable"]
+ "cell": [
+ "Not applicable"
+ ]
},
{
"id": "apple-ipad-pro-11-2021-2tb-spacegray",
"category": "tablets",
"namespaceId": "apple-ipad-pro-11-2021",
"name": "Apple iPad Pro 11 (2021) 2TB Space Gray",
- "capacityAvailable": ["128GB", "256GB", "512GB", "1TB", "2TB"],
+ "capacityAvailable": [
+ "128GB",
+ "256GB",
+ "512GB",
+ "1TB",
+ "2TB"
+ ],
"capacity": "2TB",
"priceRegular": 999,
"priceDiscount": 939,
- "colorsAvailable": ["spacegray", "silver"],
+ "colorsAvailable": [
+ "spacegray",
+ "silver"
+ ],
"color": "spacegray",
"images": [
"img/tablets/apple-ipad-pro-11-2021/spacegray/00.webp",
@@ -232,18 +285,29 @@
"ram": "16GB",
"camera": "12MP + 12MP",
"zoom": "Digital zoom up to 5x",
- "cell": ["Not applicable"]
+ "cell": [
+ "Not applicable"
+ ]
},
{
"id": "apple-ipad-pro-11-2021-128gb-silver",
"category": "tablets",
"namespaceId": "apple-ipad-pro-11-2021",
"name": "Apple iPad Pro 11 (2021) 128GB Silver",
- "capacityAvailable": ["128GB", "256GB", "512GB", "1TB", "2TB"],
+ "capacityAvailable": [
+ "128GB",
+ "256GB",
+ "512GB",
+ "1TB",
+ "2TB"
+ ],
"capacity": "128GB",
"priceRegular": 799,
"priceDiscount": 749,
- "colorsAvailable": ["spacegray", "silver"],
+ "colorsAvailable": [
+ "spacegray",
+ "silver"
+ ],
"color": "silver",
"images": [
"img/tablets/apple-ipad-pro-11-2021/silver/00.webp",
@@ -279,18 +343,29 @@
"ram": "8GB",
"camera": "12MP + 12MP",
"zoom": "Digital zoom up to 5x",
- "cell": ["Not applicable"]
+ "cell": [
+ "Not applicable"
+ ]
},
{
"id": "apple-ipad-pro-11-2021-256gb-silver",
"category": "tablets",
"namespaceId": "apple-ipad-pro-11-2021",
"name": "Apple iPad Pro 11 (2021) 256GB Silver",
- "capacityAvailable": ["128GB", "256GB", "512GB", "1TB", "2TB"],
+ "capacityAvailable": [
+ "128GB",
+ "256GB",
+ "512GB",
+ "1TB",
+ "2TB"
+ ],
"capacity": "256GB",
"priceRegular": 829,
"priceDiscount": 799,
- "colorsAvailable": ["spacegray", "silver"],
+ "colorsAvailable": [
+ "spacegray",
+ "silver"
+ ],
"color": "silver",
"images": [
"img/tablets/apple-ipad-pro-11-2021/silver/00.webp",
@@ -326,18 +401,29 @@
"ram": "8GB",
"camera": "12MP + 12MP",
"zoom": "Digital zoom up to 5x",
- "cell": ["Not applicable"]
+ "cell": [
+ "Not applicable"
+ ]
},
{
"id": "apple-ipad-pro-11-2021-512gb-silver",
"category": "tablets",
"namespaceId": "apple-ipad-pro-11-2021",
"name": "Apple iPad Pro 11 (2021) 512GB Silver",
- "capacityAvailable": ["128GB", "256GB", "512GB", "1TB", "2TB"],
+ "capacityAvailable": [
+ "128GB",
+ "256GB",
+ "512GB",
+ "1TB",
+ "2TB"
+ ],
"capacity": "512GB",
"priceRegular": 869,
"priceDiscount": 819,
- "colorsAvailable": ["spacegray", "silver"],
+ "colorsAvailable": [
+ "spacegray",
+ "silver"
+ ],
"color": "silver",
"images": [
"img/tablets/apple-ipad-pro-11-2021/silver/00.webp",
@@ -373,18 +459,29 @@
"ram": "8GB",
"camera": "12MP + 12MP",
"zoom": "Digital zoom up to 5x",
- "cell": ["Not applicable"]
+ "cell": [
+ "Not applicable"
+ ]
},
{
"id": "apple-ipad-pro-11-2021-1tb-silver",
"category": "tablets",
"namespaceId": "apple-ipad-pro-11-2021",
"name": "Apple iPad Pro 11 (2021) 1TB Silver",
- "capacityAvailable": ["128GB", "256GB", "512GB", "1TB", "2TB"],
+ "capacityAvailable": [
+ "128GB",
+ "256GB",
+ "512GB",
+ "1TB",
+ "2TB"
+ ],
"capacity": "1TB",
"priceRegular": 899,
"priceDiscount": 879,
- "colorsAvailable": ["spacegray", "silver"],
+ "colorsAvailable": [
+ "spacegray",
+ "silver"
+ ],
"color": "silver",
"images": [
"img/tablets/apple-ipad-pro-11-2021/silver/00.webp",
@@ -420,18 +517,29 @@
"ram": "16GB",
"camera": "12MP + 12MP",
"zoom": "Digital zoom up to 5x",
- "cell": ["Not applicable"]
+ "cell": [
+ "Not applicable"
+ ]
},
{
"id": "apple-ipad-pro-11-2021-2tb-silver",
"category": "tablets",
"namespaceId": "apple-ipad-pro-11-2021",
"name": "Apple iPad Pro 11 (2021) 2TB Silver",
- "capacityAvailable": ["128GB", "256GB", "512GB", "1TB", "2TB"],
+ "capacityAvailable": [
+ "128GB",
+ "256GB",
+ "512GB",
+ "1TB",
+ "2TB"
+ ],
"capacity": "2TB",
"priceRegular": 999,
"priceDiscount": 939,
- "colorsAvailable": ["spacegray", "silver"],
+ "colorsAvailable": [
+ "spacegray",
+ "silver"
+ ],
"color": "silver",
"images": [
"img/tablets/apple-ipad-pro-11-2021/silver/00.webp",
@@ -467,18 +575,28 @@
"ram": "16GB",
"camera": "12MP + 12MP",
"zoom": "Digital zoom up to 5x",
- "cell": ["Not applicable"]
+ "cell": [
+ "Not applicable"
+ ]
},
{
"id": "apple-ipad-air-4th-gen-256gb-rose-gold",
"category": "tablets",
"namespaceId": "apple-ipad-air-4th-gen",
"name": "Apple iPad Air (4th Gen) 256GB Rose Gold",
- "capacityAvailable": ["64GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB"
+ ],
"capacity": "256GB",
"priceRegular": 749,
"priceDiscount": 699,
- "colorsAvailable": ["rose gold", "silver", "green", "sky blue"],
+ "colorsAvailable": [
+ "rose gold",
+ "silver",
+ "green",
+ "sky blue"
+ ],
"color": "rose gold",
"images": [
"img/tablets/apple-ipad-air-4th-gen/rose-gold/00.webp",
@@ -515,18 +633,28 @@
"ram": "4GB",
"camera": "12MP",
"zoom": "Digital zoom up to 5x",
- "cell": ["Not applicable"]
+ "cell": [
+ "Not applicable"
+ ]
},
{
"id": "apple-ipad-air-4th-gen-64gb-rose-gold",
"category": "tablets",
"namespaceId": "apple-ipad-air-4th-gen",
"name": "Apple iPad Air (4th Gen) 64GB Rose Gold",
- "capacityAvailable": ["64GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB"
+ ],
"capacity": "64GB",
"priceRegular": 599,
"priceDiscount": 549,
- "colorsAvailable": ["rose gold", "silver", "green", "sky blue"],
+ "colorsAvailable": [
+ "rose gold",
+ "silver",
+ "green",
+ "sky blue"
+ ],
"color": "rose gold",
"images": [
"img/tablets/apple-ipad-air-4th-gen/rose-gold/00.webp",
@@ -563,18 +691,28 @@
"ram": "4GB",
"camera": "12MP",
"zoom": "Digital zoom up to 5x",
- "cell": ["Not applicable"]
+ "cell": [
+ "Not applicable"
+ ]
},
{
"id": "apple-ipad-air-4th-gen-64gb-silver",
"category": "tablets",
"namespaceId": "apple-ipad-air-4th-gen",
"name": "Apple iPad Air (4th Gen) 64GB Silver",
- "capacityAvailable": ["64GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB"
+ ],
"capacity": "64GB",
"priceRegular": 599,
"priceDiscount": 549,
- "colorsAvailable": ["rose gold", "silver", "green", "sky blue"],
+ "colorsAvailable": [
+ "rose gold",
+ "silver",
+ "green",
+ "sky blue"
+ ],
"color": "silver",
"images": [
"img/tablets/apple-ipad-air-4th-gen/silver/00.webp",
@@ -611,18 +749,28 @@
"ram": "4GB",
"camera": "12MP",
"zoom": "Digital zoom up to 5x",
- "cell": ["Not applicable"]
+ "cell": [
+ "Not applicable"
+ ]
},
{
"id": "apple-ipad-air-4th-gen-256gb-silver",
"category": "tablets",
"namespaceId": "apple-ipad-air-4th-gen",
"name": "Apple iPad Air (4th Gen) 256GB Silver",
- "capacityAvailable": ["64GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB"
+ ],
"capacity": "256GB",
"priceRegular": 749,
"priceDiscount": 699,
- "colorsAvailable": ["rose gold", "silver", "green", "sky blue"],
+ "colorsAvailable": [
+ "rose gold",
+ "silver",
+ "green",
+ "sky blue"
+ ],
"color": "silver",
"images": [
"img/tablets/apple-ipad-air-4th-gen/silver/00.webp",
@@ -659,22 +807,32 @@
"ram": "4GB",
"camera": "12MP",
"zoom": "Digital zoom up to 5x",
- "cell": ["Not applicable"]
+ "cell": [
+ "Not applicable"
+ ]
},
{
"id": "apple-ipad-air-4th-gen-256gb-green",
"category": "tablets",
"namespaceId": "apple-ipad-air-4th-gen",
"name": "Apple iPad Air (4th Gen) 256GB Green",
- "capacityAvailable": ["64GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB"
+ ],
"capacity": "256GB",
"priceRegular": 749,
"priceDiscount": 699,
- "colorsAvailable": ["rose gold", "silver", "green", "sky blue"],
+ "colorsAvailable": [
+ "rose gold",
+ "silver",
+ "green",
+ "sky blue"
+ ],
"color": "green",
"images": [
"img/tablets/apple-ipad-air-4th-gen/green/00.webp",
- "img/tablets/apple-ipad-air-4th-gen/green/01.webp",
+ "img/tablets/apple-ipad-air-4th-gen/green/04.webp",
"img/tablets/apple-ipad-air-4th-gen/green/02.webp",
"img/tablets/apple-ipad-air-4th-gen/green/03.webp"
],
@@ -707,22 +865,32 @@
"ram": "4GB",
"camera": "12MP",
"zoom": "Digital zoom up to 5x",
- "cell": ["Not applicable"]
+ "cell": [
+ "Not applicable"
+ ]
},
{
"id": "apple-ipad-air-4th-gen-64gb-green",
"category": "tablets",
"namespaceId": "apple-ipad-air-4th-gen",
"name": "Apple iPad Air (4th Gen) 64GB Green",
- "capacityAvailable": ["64GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB"
+ ],
"capacity": "64GB",
"priceRegular": 599,
"priceDiscount": 549,
- "colorsAvailable": ["rose gold", "silver", "green", "sky blue"],
+ "colorsAvailable": [
+ "rose gold",
+ "silver",
+ "green",
+ "sky blue"
+ ],
"color": "green",
"images": [
"img/tablets/apple-ipad-air-4th-gen/green/00.webp",
- "img/tablets/apple-ipad-air-4th-gen/green/01.webp",
+ "img/tablets/apple-ipad-air-4th-gen/green/04.webp",
"img/tablets/apple-ipad-air-4th-gen/green/02.webp",
"img/tablets/apple-ipad-air-4th-gen/green/03.webp"
],
@@ -755,18 +923,28 @@
"ram": "4GB",
"camera": "12MP",
"zoom": "Digital zoom up to 5x",
- "cell": ["Not applicable"]
+ "cell": [
+ "Not applicable"
+ ]
},
{
"id": "apple-ipad-air-4th-gen-64gb-sky-blue",
"category": "tablets",
"namespaceId": "apple-ipad-air-4th-gen",
"name": "Apple iPad Air (4th Gen) 64GB Sky Blue",
- "capacityAvailable": ["64GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB"
+ ],
"capacity": "64GB",
"priceRegular": 599,
"priceDiscount": 549,
- "colorsAvailable": ["rose gold", "silver", "green", "sky blue"],
+ "colorsAvailable": [
+ "rose gold",
+ "silver",
+ "green",
+ "sky blue"
+ ],
"color": "sky blue",
"images": [
"img/tablets/apple-ipad-air-4th-gen/sky-blue/00.webp",
@@ -803,18 +981,28 @@
"ram": "4GB",
"camera": "12MP",
"zoom": "Digital zoom up to 5x",
- "cell": ["Not applicable"]
+ "cell": [
+ "Not applicable"
+ ]
},
{
"id": "apple-ipad-air-4th-gen-256gb-sky-blue",
"category": "tablets",
"namespaceId": "apple-ipad-air-4th-gen",
"name": "Apple iPad Air (4th Gen) 256GB Sky Blue",
- "capacityAvailable": ["64GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB"
+ ],
"capacity": "256GB",
"priceRegular": 749,
"priceDiscount": 699,
- "colorsAvailable": ["rose gold", "silver", "green", "sky blue"],
+ "colorsAvailable": [
+ "rose gold",
+ "silver",
+ "green",
+ "sky blue"
+ ],
"color": "sky blue",
"images": [
"img/tablets/apple-ipad-air-4th-gen/sky-blue/00.webp",
@@ -851,18 +1039,27 @@
"ram": "4GB",
"camera": "12MP",
"zoom": "Digital zoom up to 5x",
- "cell": ["Not applicable"]
+ "cell": [
+ "Not applicable"
+ ]
},
{
"id": "apple-ipad-mini-6th-gen-64gb-spacegray",
"category": "tablets",
"namespaceId": "apple-ipad-mini-6th-gen",
"name": "Apple iPad Mini (6th Gen) 64GB Space Gray",
- "capacityAvailable": ["64GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB"
+ ],
"capacity": "64GB",
"priceRegular": 499,
"priceDiscount": 469,
- "colorsAvailable": ["spacegray", "starlight", "pink"],
+ "colorsAvailable": [
+ "spacegray",
+ "starlight",
+ "pink"
+ ],
"color": "spacegray",
"images": [
"img/tablets/apple-ipad-mini-6th-gen/spacegray/00.webp",
@@ -898,18 +1095,27 @@
"ram": "4GB",
"camera": "12MP",
"zoom": "Digital zoom up to 5x",
- "cell": ["Not applicable"]
+ "cell": [
+ "Not applicable"
+ ]
},
{
"id": "apple-ipad-mini-6th-gen-256gb-spacegray",
"category": "tablets",
"namespaceId": "apple-ipad-mini-6th-gen",
"name": "Apple iPad Mini (6th Gen) 256GB Space Gray",
- "capacityAvailable": ["64GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB"
+ ],
"capacity": "256GB",
"priceRegular": 649,
"priceDiscount": 599,
- "colorsAvailable": ["spacegray", "starlight", "pink"],
+ "colorsAvailable": [
+ "spacegray",
+ "starlight",
+ "pink"
+ ],
"color": "spacegray",
"images": [
"img/tablets/apple-ipad-mini-6th-gen/spacegray/00.webp",
@@ -945,18 +1151,27 @@
"ram": "4GB",
"camera": "12MP",
"zoom": "Digital zoom up to 5x",
- "cell": ["Not applicable"]
+ "cell": [
+ "Not applicable"
+ ]
},
{
"id": "apple-ipad-mini-6th-gen-256gb-starlight",
"category": "tablets",
"namespaceId": "apple-ipad-mini-6th-gen",
"name": "Apple iPad Mini (6th Gen) 256GB Starlight",
- "capacityAvailable": ["64GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB"
+ ],
"capacity": "256GB",
"priceRegular": 649,
"priceDiscount": 599,
- "colorsAvailable": ["spacegray", "starlight", "pink"],
+ "colorsAvailable": [
+ "spacegray",
+ "starlight",
+ "pink"
+ ],
"color": "starlight",
"images": [
"img/tablets/apple-ipad-mini-6th-gen/starlight/00.webp",
@@ -992,18 +1207,27 @@
"ram": "4GB",
"camera": "12MP",
"zoom": "Digital zoom up to 5x",
- "cell": ["Not applicable"]
+ "cell": [
+ "Not applicable"
+ ]
},
{
"id": "apple-ipad-mini-6th-gen-64gb-starlight",
"category": "tablets",
"namespaceId": "apple-ipad-mini-6th-gen",
"name": "Apple iPad Mini (6th Gen) 64GB Starlight",
- "capacityAvailable": ["64GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB"
+ ],
"capacity": "64GB",
"priceRegular": 499,
"priceDiscount": 469,
- "colorsAvailable": ["spacegray", "starlight", "pink"],
+ "colorsAvailable": [
+ "spacegray",
+ "starlight",
+ "pink"
+ ],
"color": "starlight",
"images": [
"img/tablets/apple-ipad-mini-6th-gen/starlight/00.webp",
@@ -1039,18 +1263,27 @@
"ram": "4GB",
"camera": "12MP",
"zoom": "Digital zoom up to 5x",
- "cell": ["Not applicable"]
+ "cell": [
+ "Not applicable"
+ ]
},
{
"id": "apple-ipad-mini-6th-gen-64gb-pink",
"category": "tablets",
"namespaceId": "apple-ipad-mini-6th-gen",
"name": "Apple iPad Mini (6th Gen) 64GB Pink",
- "capacityAvailable": ["64GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB"
+ ],
"capacity": "64GB",
"priceRegular": 499,
"priceDiscount": 469,
- "colorsAvailable": ["spacegray", "starlight", "pink"],
+ "colorsAvailable": [
+ "spacegray",
+ "starlight",
+ "pink"
+ ],
"color": "pink",
"images": [
"img/tablets/apple-ipad-mini-6th-gen/pink/00.webp",
@@ -1086,18 +1319,27 @@
"ram": "4GB",
"camera": "12MP",
"zoom": "Digital zoom up to 5x",
- "cell": ["Not applicable"]
+ "cell": [
+ "Not applicable"
+ ]
},
{
"id": "apple-ipad-mini-6th-gen-256gb-pink",
"category": "tablets",
"namespaceId": "apple-ipad-mini-6th-gen",
"name": "Apple iPad Mini (6th Gen) 256GB Pink",
- "capacityAvailable": ["64GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB"
+ ],
"capacity": "256GB",
"priceRegular": 649,
"priceDiscount": 619,
- "colorsAvailable": ["spacegray", "starlight", "pink"],
+ "colorsAvailable": [
+ "spacegray",
+ "starlight",
+ "pink"
+ ],
"color": "pink",
"images": [
"img/tablets/apple-ipad-mini-6th-gen/pink/00.webp",
@@ -1133,18 +1375,27 @@
"ram": "4GB",
"camera": "12MP",
"zoom": "Digital zoom up to 5x",
- "cell": ["Not applicable"]
+ "cell": [
+ "Not applicable"
+ ]
},
{
"id": "apple-ipad-10-2-2020-128gb-gold",
"category": "tablets",
"namespaceId": "apple-ipad-10-2-2020",
"name": "Apple iPad 10.2 (2020) 128GB Gold",
- "capacityAvailable": ["32GB", "128GB"],
+ "capacityAvailable": [
+ "32GB",
+ "128GB"
+ ],
"capacity": "128GB",
"priceRegular": 429,
"priceDiscount": 399,
- "colorsAvailable": ["gold", "silver", "spacegray"],
+ "colorsAvailable": [
+ "gold",
+ "silver",
+ "spacegray"
+ ],
"color": "gold",
"images": [
"img/tablets/apple-ipad-10-2-2020/gold/00.webp",
@@ -1181,18 +1432,27 @@
"ram": "3GB",
"camera": "8MP",
"zoom": "Digital zoom up to 5x",
- "cell": ["Not applicable"]
+ "cell": [
+ "Not applicable"
+ ]
},
{
"id": "apple-ipad-10-2-2020-32gb-gold",
"category": "tablets",
"namespaceId": "apple-ipad-10-2-2020",
"name": "Apple iPad 10.2 (2020) 32GB Gold",
- "capacityAvailable": ["32GB", "128GB"],
+ "capacityAvailable": [
+ "32GB",
+ "128GB"
+ ],
"capacity": "32GB",
"priceRegular": 329,
"priceDiscount": 299,
- "colorsAvailable": ["gold", "silver", "spacegray"],
+ "colorsAvailable": [
+ "gold",
+ "silver",
+ "spacegray"
+ ],
"color": "gold",
"images": [
"img/tablets/apple-ipad-10-2-2020/gold/00.webp",
@@ -1229,18 +1489,27 @@
"ram": "3GB",
"camera": "8MP",
"zoom": "Digital zoom up to 5x",
- "cell": ["Not applicable"]
+ "cell": [
+ "Not applicable"
+ ]
},
{
"id": "apple-ipad-10-2-2020-32gb-silver",
"category": "tablets",
"namespaceId": "apple-ipad-10-2-2020",
"name": "Apple iPad 10.2 (2020) 32GB Silver",
- "capacityAvailable": ["32GB", "128GB"],
+ "capacityAvailable": [
+ "32GB",
+ "128GB"
+ ],
"capacity": "32GB",
"priceRegular": 329,
"priceDiscount": 299,
- "colorsAvailable": ["gold", "silver", "spacegray"],
+ "colorsAvailable": [
+ "gold",
+ "silver",
+ "spacegray"
+ ],
"color": "silver",
"images": [
"img/tablets/apple-ipad-10-2-2020/silver/00.webp",
@@ -1277,18 +1546,27 @@
"ram": "3GB",
"camera": "8MP",
"zoom": "Digital zoom up to 5x",
- "cell": ["Not applicable"]
+ "cell": [
+ "Not applicable"
+ ]
},
{
"id": "apple-ipad-10-2-2020-128gb-silver",
"category": "tablets",
"namespaceId": "apple-ipad-10-2-2020",
"name": "Apple iPad 10.2 (2020) 128GB Silver",
- "capacityAvailable": ["32GB", "128GB"],
+ "capacityAvailable": [
+ "32GB",
+ "128GB"
+ ],
"capacity": "128GB",
"priceRegular": 429,
"priceDiscount": 399,
- "colorsAvailable": ["gold", "silver", "spacegray"],
+ "colorsAvailable": [
+ "gold",
+ "silver",
+ "spacegray"
+ ],
"color": "silver",
"images": [
"img/tablets/apple-ipad-10-2-2020/silver/00.webp",
@@ -1325,18 +1603,27 @@
"ram": "3GB",
"camera": "8MP",
"zoom": "Digital zoom up to 5x",
- "cell": ["Not applicable"]
+ "cell": [
+ "Not applicable"
+ ]
},
{
"id": "apple-ipad-10-2-2020-128gb-spacegray",
"category": "tablets",
"namespaceId": "apple-ipad-10-2-2020",
"name": "Apple iPad 10.2 (2020) 128GB Space Gray",
- "capacityAvailable": ["32GB", "128GB"],
+ "capacityAvailable": [
+ "32GB",
+ "128GB"
+ ],
"capacity": "128GB",
"priceRegular": 429,
"priceDiscount": 399,
- "colorsAvailable": ["gold", "silver", "spacegray"],
+ "colorsAvailable": [
+ "gold",
+ "silver",
+ "spacegray"
+ ],
"color": "spacegray",
"images": [
"img/tablets/apple-ipad-10-2-2020/spacegray/00.webp",
@@ -1373,18 +1660,27 @@
"ram": "3GB",
"camera": "8MP",
"zoom": "Digital zoom up to 5x",
- "cell": ["Not applicable"]
+ "cell": [
+ "Not applicable"
+ ]
},
{
"id": "apple-ipad-10-2-2020-32gb-spacegray",
"category": "tablets",
"namespaceId": "apple-ipad-10-2-2020",
"name": "Apple iPad 10.2 (2020) 32GB Space Gray",
- "capacityAvailable": ["32GB", "128GB"],
+ "capacityAvailable": [
+ "32GB",
+ "128GB"
+ ],
"capacity": "32GB",
"priceRegular": 329,
"priceDiscount": 299,
- "colorsAvailable": ["gold", "silver", "spacegray"],
+ "colorsAvailable": [
+ "gold",
+ "silver",
+ "spacegray"
+ ],
"color": "spacegray",
"images": [
"img/tablets/apple-ipad-10-2-2020/spacegray/00.webp",
@@ -1421,18 +1717,27 @@
"ram": "3GB",
"camera": "8MP",
"zoom": "Digital zoom up to 5x",
- "cell": ["Not applicable"]
+ "cell": [
+ "Not applicable"
+ ]
},
{
"id": "apple-ipad-mini-5th-gen-256gb-silver",
"category": "tablets",
"namespaceId": "apple-ipad-mini-5th-gen",
"name": "Apple iPad Mini (5th Gen) 256GB Silver",
- "capacityAvailable": ["64GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB"
+ ],
"capacity": "256GB",
"priceRegular": 549,
"priceDiscount": 499,
- "colorsAvailable": ["silver", "spacegray", "gold"],
+ "colorsAvailable": [
+ "silver",
+ "spacegray",
+ "gold"
+ ],
"color": "silver",
"images": [
"img/tablets/apple-ipad-mini-5th-gen/silver/00.webp",
@@ -1467,18 +1772,27 @@
"ram": "3GB",
"camera": "8MP",
"zoom": "Digital zoom up to 5x",
- "cell": ["Not applicable"]
+ "cell": [
+ "Not applicable"
+ ]
},
{
"id": "apple-ipad-mini-5th-gen-64gb-silver",
"category": "tablets",
"namespaceId": "apple-ipad-mini-5th-gen",
"name": "Apple iPad Mini (5th Gen) 64GB Silver",
- "capacityAvailable": ["64GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB"
+ ],
"capacity": "64GB",
"priceRegular": 549,
"priceDiscount": 499,
- "colorsAvailable": ["silver", "spacegray", "gold"],
+ "colorsAvailable": [
+ "silver",
+ "spacegray",
+ "gold"
+ ],
"color": "silver",
"images": [
"img/tablets/apple-ipad-mini-5th-gen/silver/00.webp",
@@ -1513,18 +1827,27 @@
"ram": "3GB",
"camera": "8MP",
"zoom": "Digital zoom up to 5x",
- "cell": ["Not applicable"]
+ "cell": [
+ "Not applicable"
+ ]
},
{
"id": "apple-ipad-mini-5th-gen-64gb-spacegray",
"category": "tablets",
"namespaceId": "apple-ipad-mini-5th-gen",
"name": "Apple iPad Mini (5th Gen) 64GB Space Gray",
- "capacityAvailable": ["64GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB"
+ ],
"capacity": "64GB",
"priceRegular": 549,
"priceDiscount": 499,
- "colorsAvailable": ["silver", "spacegray", "gold"],
+ "colorsAvailable": [
+ "silver",
+ "spacegray",
+ "gold"
+ ],
"color": "spacegray",
"images": [
"img/tablets/apple-ipad-mini-5th-gen/spacegray/00.webp",
@@ -1559,18 +1882,27 @@
"ram": "3GB",
"camera": "8MP",
"zoom": "Digital zoom up to 5x",
- "cell": ["Not applicable"]
+ "cell": [
+ "Not applicable"
+ ]
},
{
"id": "apple-ipad-mini-5th-gen-256gb-spacegray",
"category": "tablets",
"namespaceId": "apple-ipad-mini-5th-gen",
"name": "Apple iPad Mini (5th Gen) 256GB Space Gray",
- "capacityAvailable": ["64GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB"
+ ],
"capacity": "256GB",
"priceRegular": 549,
"priceDiscount": 499,
- "colorsAvailable": ["silver", "spacegray", "gold"],
+ "colorsAvailable": [
+ "silver",
+ "spacegray",
+ "gold"
+ ],
"color": "spacegray",
"images": [
"img/tablets/apple-ipad-mini-5th-gen/spacegray/00.webp",
@@ -1605,18 +1937,27 @@
"ram": "3GB",
"camera": "8MP",
"zoom": "Digital zoom up to 5x",
- "cell": ["Not applicable"]
+ "cell": [
+ "Not applicable"
+ ]
},
{
"id": "apple-ipad-mini-5th-gen-256gb-gold",
"category": "tablets",
"namespaceId": "apple-ipad-mini-5th-gen",
"name": "Apple iPad Mini (5th Gen) 256GB Gold",
- "capacityAvailable": ["64GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB"
+ ],
"capacity": "256GB",
"priceRegular": 549,
"priceDiscount": 499,
- "colorsAvailable": ["silver", "spacegray", "gold"],
+ "colorsAvailable": [
+ "silver",
+ "spacegray",
+ "gold"
+ ],
"color": "gold",
"images": [
"img/tablets/apple-ipad-mini-5th-gen/gold/00.webp",
@@ -1651,18 +1992,27 @@
"ram": "3GB",
"camera": "8MP",
"zoom": "Digital zoom up to 5x",
- "cell": ["Not applicable"]
+ "cell": [
+ "Not applicable"
+ ]
},
{
"id": "apple-ipad-mini-5th-gen-64gb-gold",
"category": "tablets",
"namespaceId": "apple-ipad-mini-5th-gen",
"name": "Apple iPad Mini (5th Gen) 64GB Gold",
- "capacityAvailable": ["64GB", "256GB"],
+ "capacityAvailable": [
+ "64GB",
+ "256GB"
+ ],
"capacity": "64GB",
"priceRegular": 549,
"priceDiscount": 499,
- "colorsAvailable": ["silver", "spacegray", "gold"],
+ "colorsAvailable": [
+ "silver",
+ "spacegray",
+ "gold"
+ ],
"color": "gold",
"images": [
"img/tablets/apple-ipad-mini-5th-gen/gold/00.webp",
@@ -1697,6 +2047,8 @@
"ram": "3GB",
"camera": "8MP",
"zoom": "Digital zoom up to 5x",
- "cell": ["Not applicable"]
+ "cell": [
+ "Not applicable"
+ ]
}
]
diff --git a/public/img/banner-iphone-14.png b/public/img/banner-iphone-14.png
new file mode 100644
index 00000000000..0acf02aaf7b
Binary files /dev/null and b/public/img/banner-iphone-14.png differ
diff --git a/public/img/cart-is-empty.png b/public/img/cart-is-empty.png
deleted file mode 100644
index bacf3367194..00000000000
Binary files a/public/img/cart-is-empty.png and /dev/null differ
diff --git a/public/img/category-accessories.png b/public/img/category-accessories.png
index 67c5bfdb35b..0d433acf506 100644
Binary files a/public/img/category-accessories.png and b/public/img/category-accessories.png differ
diff --git a/public/img/category-phones2.png b/public/img/category-phones2.png
new file mode 100644
index 00000000000..e8d4eec47f6
Binary files /dev/null and b/public/img/category-phones2.png differ
diff --git a/public/img/icons/arrow-down.svg b/public/img/icons/arrow-down.svg
new file mode 100644
index 00000000000..8210eedddb2
--- /dev/null
+++ b/public/img/icons/arrow-down.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/public/img/icons/arrow-left.svg b/public/img/icons/arrow-left.svg
new file mode 100644
index 00000000000..7fdaf670996
--- /dev/null
+++ b/public/img/icons/arrow-left.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/public/img/icons/arrow-right.svg b/public/img/icons/arrow-right.svg
new file mode 100644
index 00000000000..1ba4dd38acf
--- /dev/null
+++ b/public/img/icons/arrow-right.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/public/img/icons/arrow-up.svg b/public/img/icons/arrow-up.svg
new file mode 100644
index 00000000000..2e6bc3952ab
--- /dev/null
+++ b/public/img/icons/arrow-up.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/public/img/icons/cart.svg b/public/img/icons/cart.svg
new file mode 100644
index 00000000000..661ac67ad46
--- /dev/null
+++ b/public/img/icons/cart.svg
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/public/img/icons/close.svg b/public/img/icons/close.svg
new file mode 100644
index 00000000000..7b0e804dde7
--- /dev/null
+++ b/public/img/icons/close.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/public/img/icons/favourites-filled.svg b/public/img/icons/favourites-filled.svg
new file mode 100644
index 00000000000..7461f2a4a7e
--- /dev/null
+++ b/public/img/icons/favourites-filled.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/public/img/icons/favourites.svg b/public/img/icons/favourites.svg
new file mode 100644
index 00000000000..0ceebdf3949
--- /dev/null
+++ b/public/img/icons/favourites.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/public/img/icons/home.svg b/public/img/icons/home.svg
new file mode 100644
index 00000000000..28c0fedbd18
--- /dev/null
+++ b/public/img/icons/home.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/public/img/icons/logo-flame.png b/public/img/icons/logo-flame.png
new file mode 100644
index 00000000000..c7b2f96dc33
Binary files /dev/null and b/public/img/icons/logo-flame.png differ
diff --git a/public/img/icons/logo.svg b/public/img/icons/logo.svg
new file mode 100644
index 00000000000..9b6c0879512
--- /dev/null
+++ b/public/img/icons/logo.svg
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/public/img/icons/remove.svg b/public/img/icons/remove.svg
new file mode 100644
index 00000000000..fc9186890bd
--- /dev/null
+++ b/public/img/icons/remove.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/public/img/icons/search.svg b/public/img/icons/search.svg
new file mode 100644
index 00000000000..801f11a5482
--- /dev/null
+++ b/public/img/icons/search.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/public/img/picthree.bdd2e0fc.png b/public/img/picthree.bdd2e0fc.png
deleted file mode 100644
index 28b5c4c99a6..00000000000
Binary files a/public/img/picthree.bdd2e0fc.png and /dev/null differ
diff --git a/src/App.scss b/src/App.scss
index 71bc413aade..f05b974101e 100644
--- a/src/App.scss
+++ b/src/App.scss
@@ -1 +1,71 @@
-// not empty
+@use 'styles/variables' as *;
+@use 'styles/base';
+
+.App {
+ display: flex;
+ flex-direction: column;
+ min-height: 100vh;
+
+ &__main {
+ flex: 1;
+ padding-top: 24px;
+ padding-bottom: 56px;
+
+ @include on-tablet {
+ padding-top: 32px;
+ padding-bottom: 64px;
+ }
+ }
+}
+
+// Page-level shared styles
+.page__title {
+ font-size: 32px;
+ font-weight: 700;
+ line-height: 41px;
+ letter-spacing: -0.01em;
+ margin-bottom: 8px;
+ color: $color-primary;
+
+ @include on-tablet {
+ font-size: 48px;
+ line-height: 56px;
+ }
+}
+
+.page__subtitle {
+ font-size: 14px;
+ font-weight: 600;
+ line-height: 21px;
+ color: $color-secondary;
+ margin-bottom: 24px;
+
+ @include on-tablet {
+ margin-bottom: 40px;
+ }
+}
+
+.section {
+ margin-bottom: 56px;
+
+ @include on-tablet {
+ margin-bottom: 64px;
+ }
+
+ @include on-desktop {
+ margin-bottom: 80px;
+ }
+
+ &__title {
+ font-size: 22px;
+ font-weight: 700;
+ line-height: 31px;
+ color: $color-primary;
+ margin-bottom: 24px;
+
+ @include on-desktop {
+ font-size: 32px;
+ line-height: 41px;
+ }
+ }
+}
diff --git a/src/App.tsx b/src/App.tsx
index 372e4b42066..be62257a592 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -1,7 +1,53 @@
+import { Outlet, Route, Routes } from 'react-router-dom';
+import { Header } from './components/Header';
+import { Footer } from './components/Footer';
+import { NotFoundPage } from './modules/NotFoundPage';
+import { HomePage } from './modules/HomePage';
+import { PhonesPage } from './modules/PhonesPage';
+import { TabletsPage } from './modules/TabletsPage';
+import { AccessoriesPage } from './modules/AccessoriesPage';
+import { ProductDetailsPage } from './modules/ProductDetailsPage';
+import { FavoritesPage } from './modules/FavoritesPage';
+import { CartPage } from './modules/CartPage';
+import { CartProvider } from './context/CartContext';
+import { FavoritesProvider } from './context/FavoritesContext';
+import { ThemeProvider } from './context/ThemeContext';
import './App.scss';
-export const App = () => (
+/* -------- Layout -------- */
+
+const Layout = () => (
-
Product Catalog
+
+
+
+ Product Catalog
+
+
+
+
);
+
+/* -------- App -------- */
+
+export const App = () => (
+
+
+
+
+ }>
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+
+
+
+
+
+);
diff --git a/src/components/BackButton/BackButton.module.scss b/src/components/BackButton/BackButton.module.scss
new file mode 100644
index 00000000000..5ccd2328f46
--- /dev/null
+++ b/src/components/BackButton/BackButton.module.scss
@@ -0,0 +1,28 @@
+@use '../../styles/variables' as *;
+
+.back {
+ display: inline-flex;
+ align-items: center;
+ gap: 4px;
+ padding: 0;
+ margin-bottom: 16px;
+ font-family: $font-family;
+ font-size: 12px;
+ font-weight: 600;
+ line-height: 15px;
+ color: $color-secondary;
+ background: none;
+ border: none;
+ cursor: pointer;
+ transition: color 0.3s;
+
+ &:hover {
+ color: $color-primary;
+ }
+
+ img {
+ width: 16px;
+ height: 16px;
+ opacity: 0.5;
+ }
+}
diff --git a/src/components/BackButton/BackButton.tsx b/src/components/BackButton/BackButton.tsx
new file mode 100644
index 00000000000..8be45e2a89c
--- /dev/null
+++ b/src/components/BackButton/BackButton.tsx
@@ -0,0 +1,18 @@
+import { useNavigate } from 'react-router-dom';
+import styles from './BackButton.module.scss';
+
+export const BackButton = () => {
+ const navigate = useNavigate();
+
+ return (
+ navigate(-1)}
+ data-cy="backButton"
+ >
+
+ Back
+
+ );
+};
diff --git a/src/components/BackButton/index.ts b/src/components/BackButton/index.ts
new file mode 100644
index 00000000000..e1c3083d57e
--- /dev/null
+++ b/src/components/BackButton/index.ts
@@ -0,0 +1 @@
+export { BackButton } from './BackButton';
diff --git a/src/components/Breadcrumbs/Breadcrumbs.module.scss b/src/components/Breadcrumbs/Breadcrumbs.module.scss
new file mode 100644
index 00000000000..4ac8c4b7933
--- /dev/null
+++ b/src/components/Breadcrumbs/Breadcrumbs.module.scss
@@ -0,0 +1,53 @@
+@use '../../styles/variables' as *;
+
+.breadcrumbs {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ margin-bottom: 16px;
+
+ @include on-tablet {
+ margin-bottom: 24px;
+ }
+
+ &__home {
+ display: flex;
+ align-items: center;
+
+ img {
+ width: 16px;
+ height: 16px;
+ }
+ }
+
+ &__item {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ }
+
+ &__separator {
+ width: 16px;
+ height: 16px;
+ opacity: 0.5;
+ }
+
+ &__link {
+ font-size: 12px;
+ font-weight: 600;
+ line-height: 15px;
+ color: $color-secondary;
+ transition: color 0.3s;
+
+ &:hover {
+ color: $color-primary;
+ }
+ }
+
+ &__current {
+ font-size: 12px;
+ font-weight: 600;
+ line-height: 15px;
+ color: $color-primary;
+ }
+}
diff --git a/src/components/Breadcrumbs/Breadcrumbs.tsx b/src/components/Breadcrumbs/Breadcrumbs.tsx
new file mode 100644
index 00000000000..4302e2290f1
--- /dev/null
+++ b/src/components/Breadcrumbs/Breadcrumbs.tsx
@@ -0,0 +1,37 @@
+import { Link } from 'react-router-dom';
+import styles from './Breadcrumbs.module.scss';
+
+type Crumb = {
+ label: string;
+ to?: string;
+};
+
+type Props = {
+ items: Crumb[];
+};
+
+export const Breadcrumbs: React.FC = ({ items }) => (
+
+
+
+
+
+ {items.map(({ label, to }) => (
+
+
+
+ {to ? (
+
+ {label}
+
+ ) : (
+ {label}
+ )}
+
+ ))}
+
+);
diff --git a/src/components/Breadcrumbs/index.ts b/src/components/Breadcrumbs/index.ts
new file mode 100644
index 00000000000..28140a257ff
--- /dev/null
+++ b/src/components/Breadcrumbs/index.ts
@@ -0,0 +1 @@
+export { Breadcrumbs } from './Breadcrumbs';
diff --git a/src/components/Dropdown/Dropdown.module.scss b/src/components/Dropdown/Dropdown.module.scss
new file mode 100644
index 00000000000..d4d1c5fa3f5
--- /dev/null
+++ b/src/components/Dropdown/Dropdown.module.scss
@@ -0,0 +1,70 @@
+@use '../../styles/variables' as *;
+
+.dropdown {
+ display: flex;
+ flex-direction: column;
+ gap: 4px;
+
+ &__label {
+ font-size: 12px;
+ font-weight: 600;
+ line-height: 15px;
+ color: $color-secondary;
+ }
+
+ &__select {
+ width: 136px;
+ height: 40px;
+ padding: 0 32px 0 12px;
+ font-family: $font-family;
+ font-size: 14px;
+ font-weight: 700;
+ line-height: 21px;
+ color: $color-primary;
+ background-color: $color-hover-and-bg;
+ border: 1px solid $color-icons;
+ border-radius: 8px;
+ cursor: pointer;
+ appearance: none;
+ background-image: url('/img/icons/arrow-down.svg');
+ background-repeat: no-repeat;
+ background-position: right 8px center;
+ background-size: 16px;
+ transition:
+ border-color 0.3s,
+ box-shadow 0.3s;
+
+ &:hover {
+ border-color: $color-secondary;
+ }
+
+ &:focus {
+ outline: none;
+ border-color: var(--color-focus-border);
+ }
+
+ // Style native options
+ option {
+ font-family: $font-family;
+ font-size: 14px;
+ font-weight: 600;
+ line-height: 21px;
+ color: $color-secondary;
+ background-color: $color-white;
+
+ &:checked {
+ color: $color-primary;
+ font-weight: 700;
+ background-color: $color-hover-and-bg;
+ }
+ }
+
+ @include on-tablet {
+ width: 187px;
+ }
+
+ @include on-desktop {
+ width: 176px;
+ }
+ }
+}
diff --git a/src/components/Dropdown/Dropdown.tsx b/src/components/Dropdown/Dropdown.tsx
new file mode 100644
index 00000000000..93e86b455db
--- /dev/null
+++ b/src/components/Dropdown/Dropdown.tsx
@@ -0,0 +1,30 @@
+import styles from './Dropdown.module.scss';
+
+type Props = {
+ label: string;
+ value: string;
+ options: { value: string; label: string }[];
+ onChange: (value: string) => void;
+};
+
+export const Dropdown: React.FC = ({
+ label,
+ value,
+ options,
+ onChange,
+}) => (
+
+ {label}
+ onChange(e.target.value)}
+ >
+ {options.map(option => (
+
+ {option.label}
+
+ ))}
+
+
+);
diff --git a/src/components/Dropdown/index.ts b/src/components/Dropdown/index.ts
new file mode 100644
index 00000000000..c0ad316fc26
--- /dev/null
+++ b/src/components/Dropdown/index.ts
@@ -0,0 +1 @@
+export { Dropdown } from './Dropdown';
diff --git a/src/components/Footer/Footer.module.scss b/src/components/Footer/Footer.module.scss
new file mode 100644
index 00000000000..7c43e2a23de
--- /dev/null
+++ b/src/components/Footer/Footer.module.scss
@@ -0,0 +1,152 @@
+@use '../../styles/variables' as *;
+
+.footer {
+ border-top: 1px solid $color-elements;
+ margin-top: auto;
+
+ &__content {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 32px;
+ padding: 32px 16px;
+ max-width: $content-max-width;
+ margin: 0 auto;
+
+ @include on-tablet {
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-between;
+ padding: 32px 24px;
+ }
+
+ @include on-desktop {
+ padding: 32px 152px;
+ }
+ }
+
+ // Logo section — flex: 1 on desktop
+ &__logoWrapper {
+ flex-shrink: 0;
+
+ @include on-tablet {
+ flex: 1;
+ }
+ }
+
+ &__logo {
+ display: inline-flex;
+ }
+
+ &__logoContainer {
+ position: relative;
+ width: 89px;
+ height: 32px;
+ overflow: hidden;
+ }
+
+ &__logoText {
+ display: block;
+ width: 100%;
+ height: 100%;
+ }
+
+ &__logoFlame {
+ position: absolute;
+ top: 0;
+ left: 50%;
+ width: 14%;
+ height: 52%;
+ object-fit: contain;
+ }
+
+ // Navigation links — flex: 1 on desktop, distributed
+ &__nav {
+ width: 100%;
+
+ @include on-tablet {
+ flex: 1;
+ }
+ }
+
+ &__links {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 16px;
+
+ @include on-tablet {
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-between;
+ }
+ }
+
+ &__link {
+ font-size: 12px;
+ font-weight: 700;
+ line-height: 11px;
+ letter-spacing: 0.04em;
+ text-transform: uppercase;
+ color: $color-secondary;
+ transition: color 0.3s;
+
+ &:hover {
+ color: $color-primary;
+ }
+ }
+
+ // Back to top — flex: 1 on desktop, right-aligned
+ &__backToTop {
+ width: 100%;
+ display: flex;
+ justify-content: center;
+
+ @include on-tablet {
+ flex: 1;
+ justify-content: flex-end;
+ }
+ }
+
+ &__backToTopBtn {
+ display: flex;
+ align-items: center;
+ gap: 16px;
+ cursor: pointer;
+ background: none;
+ border: none;
+ padding: 0;
+ }
+
+ &__backToTopText {
+ font-size: 12px;
+ font-weight: 600;
+ line-height: 1;
+ color: $color-secondary;
+ white-space: nowrap;
+ transition: color 0.3s;
+ }
+
+ &__backToTopBtn:hover &__backToTopText {
+ color: $color-primary;
+ }
+
+ &__backToTopIcon {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 32px;
+ height: 32px;
+ border: 1px solid $color-icons;
+ transition: border-color 0.3s;
+
+ img {
+ width: 16px;
+ height: 16px;
+ }
+ }
+
+ &__backToTopBtn:hover &__backToTopIcon {
+ border-color: $color-primary;
+ }
+}
diff --git a/src/components/Footer/Footer.tsx b/src/components/Footer/Footer.tsx
new file mode 100644
index 00000000000..f39171592ac
--- /dev/null
+++ b/src/components/Footer/Footer.tsx
@@ -0,0 +1,84 @@
+import { Link } from 'react-router-dom';
+import styles from './Footer.module.scss';
+
+export const Footer = () => {
+ const scrollToTop = () => {
+ window.scrollTo({
+ top: 0,
+ behavior: 'smooth',
+ });
+ };
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Back to top
+
+
+
+
+
+
+
+ );
+};
diff --git a/src/components/Footer/index.ts b/src/components/Footer/index.ts
new file mode 100644
index 00000000000..65e2506faf5
--- /dev/null
+++ b/src/components/Footer/index.ts
@@ -0,0 +1 @@
+export { Footer } from './Footer';
diff --git a/src/components/Header/Header.module.scss b/src/components/Header/Header.module.scss
new file mode 100644
index 00000000000..79e275709c9
--- /dev/null
+++ b/src/components/Header/Header.module.scss
@@ -0,0 +1,440 @@
+@use '../../styles/variables' as *;
+
+.header {
+ position: sticky;
+ top: 0;
+ z-index: 100;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ background-color: $color-white;
+ border-bottom: 1px solid $color-elements;
+ height: 48px;
+
+ @include on-tablet {
+ height: 64px;
+ }
+
+ &__left {
+ display: flex;
+ align-items: center;
+ height: 100%;
+ }
+
+ &__logo {
+ display: flex;
+ align-items: center;
+ padding: 0 16px;
+ height: 100%;
+
+ @include on-tablet {
+ padding: 0 24px;
+ }
+ }
+
+ &__logoContainer {
+ position: relative;
+ width: 64px;
+ height: 22px;
+ overflow: hidden;
+
+ @include on-tablet {
+ width: 80px;
+ height: 28px;
+ }
+ }
+
+ &__logoText {
+ display: block;
+ width: 100%;
+ height: 100%;
+ }
+
+ &__logoFlame {
+ position: absolute;
+ top: 0;
+ left: 50%;
+ width: 14%;
+ height: 52%;
+ object-fit: contain;
+ }
+
+ &__right {
+ display: flex;
+ align-items: center;
+ height: 100%;
+ }
+
+ // Search
+ &__searchBtn {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 0;
+ background: none;
+ border: none;
+ cursor: pointer;
+ }
+
+ // Theme Toggle
+ &__themeToggle {
+ display: none;
+ align-items: center;
+ justify-content: center;
+ height: 100%;
+ padding: 0 8px;
+ border-left: 1px solid $color-elements;
+ transition: border-color 0.3s;
+
+ @include on-tablet {
+ display: flex;
+ padding: 0 12px;
+ }
+ }
+
+ &__searchIcon {
+ width: 16px;
+ height: 16px;
+ opacity: 0.5;
+ transition: opacity 0.3s;
+
+ &:hover {
+ opacity: 1;
+ }
+ }
+
+ &__search {
+ display: none;
+
+ @include on-tablet {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ height: 100%;
+ padding: 0 16px;
+ border-left: 1px solid $color-elements;
+ transition: border-color 0.3s;
+ }
+
+ &:hover {
+ .header__searchIcon {
+ opacity: 1;
+ }
+ }
+
+ &:focus-within {
+ border-left-color: $color-primary;
+ box-shadow: inset 0 -3px 0 $color-primary;
+
+ .header__searchIcon {
+ opacity: 1;
+ }
+ }
+ }
+
+ &__searchInput {
+ border: none;
+ outline: none;
+ font-family: $font-family;
+ font-size: 14px;
+ font-weight: 600;
+ line-height: 21px;
+ color: $color-primary;
+ background: transparent;
+ width: 160px;
+ transition: border-color 0.3s;
+
+ @include on-desktop {
+ width: 200px;
+ }
+
+ &::placeholder {
+ color: $color-secondary;
+ font-weight: 600;
+ transition: color 0.3s;
+ }
+
+ &:focus::placeholder {
+ color: $color-icons;
+ }
+ }
+
+ &__searchClear {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 16px;
+ height: 16px;
+ padding: 0;
+ background: none;
+ border: none;
+ cursor: pointer;
+ opacity: 0.5;
+ transition: opacity 0.3s;
+
+ &:hover {
+ opacity: 1;
+ }
+
+ img {
+ width: 16px;
+ height: 16px;
+ }
+ }
+
+ // Icon buttons (favorites, cart) — hidden on mobile per Figma
+ &__icon {
+ display: none;
+ align-items: center;
+ justify-content: center;
+ height: 100%;
+ width: 48px;
+ border-left: 1px solid $color-elements;
+ position: relative;
+ transition: box-shadow 0.3s;
+
+ @include on-tablet {
+ display: flex;
+ width: 64px;
+ }
+
+ &:hover {
+ box-shadow: inset 0 -3px 0 $color-primary;
+ }
+
+ &--active {
+ box-shadow: inset 0 -3px 0 $color-primary;
+ }
+
+ img {
+ width: 16px;
+ height: 16px;
+ }
+ }
+
+ &__iconWrap {
+ position: relative;
+ display: inline-flex;
+ }
+
+ &__badge {
+ position: absolute;
+ top: -6px;
+ right: -10px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ min-width: 16px;
+ height: 16px;
+ padding: 0 3px;
+ font-size: 10px;
+ font-weight: 700;
+ line-height: 1;
+ text-align: center;
+ color: #fff;
+ background-color: $color-red;
+ border: 1px solid #fff;
+ border-radius: 50%;
+ box-sizing: border-box;
+ }
+
+ // Hamburger
+ &__burger {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ gap: 4px;
+ width: 48px;
+ height: 100%;
+ padding: 0;
+ background: none;
+ border: none;
+ border-left: 1px solid $color-elements;
+ cursor: pointer;
+
+ @include on-tablet {
+ display: none;
+ }
+ }
+
+ &__burgerLine {
+ display: block;
+ width: 16px;
+ height: 2px;
+ background-color: $color-primary;
+ border-radius: 1px;
+ transition: transform 0.3s;
+ }
+}
+
+// ================
+// Navigation
+// ================
+.nav {
+ display: none;
+
+ @include on-tablet {
+ display: flex;
+ align-items: center;
+ height: 100%;
+ }
+
+ &__list {
+ display: flex;
+ gap: 0;
+ height: 100%;
+ }
+
+ &__item {
+ display: flex;
+ align-items: center;
+ height: 100%;
+ }
+
+ &__link {
+ display: flex;
+ align-items: center;
+ height: 100%;
+ padding: 0 16px;
+ font-size: 12px;
+ font-weight: 700;
+ line-height: 11px;
+ letter-spacing: 0.04em;
+ text-transform: uppercase;
+ color: $color-secondary;
+ transition:
+ color 0.3s,
+ box-shadow 0.3s;
+
+ &:hover {
+ color: $color-primary;
+ box-shadow: inset 0 -3px 0 $color-primary;
+ }
+
+ &--active {
+ color: $color-primary;
+ box-shadow: inset 0 -3px 0 $color-primary;
+ }
+ }
+}
+
+// ================
+// Mobile menu overlay
+// ================
+.mobileMenu {
+ position: fixed;
+ inset: 0;
+ z-index: 200;
+ display: flex;
+ flex-direction: column;
+ background-color: $color-white;
+
+ @include on-tablet {
+ display: none;
+ }
+
+ &__header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ height: 48px;
+ border-bottom: 1px solid $color-elements;
+ }
+
+ &__close {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 48px;
+ height: 100%;
+ padding: 0;
+ background: none;
+ border: none;
+ border-left: 1px solid $color-elements;
+ cursor: pointer;
+
+ img {
+ width: 16px;
+ height: 16px;
+ }
+ }
+
+ &__nav {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 16px;
+ padding-top: 24px;
+ flex: 1;
+ }
+
+ &__link {
+ font-size: 12px;
+ font-weight: 700;
+ line-height: 11px;
+ letter-spacing: 0.04em;
+ text-transform: uppercase;
+ color: $color-secondary;
+ padding: 8px 0;
+ border-bottom: 3px solid transparent;
+ transition:
+ color 0.3s,
+ border-color 0.3s;
+
+ &:hover {
+ color: $color-primary;
+ }
+
+ &--active {
+ color: $color-primary;
+ border-bottom-color: $color-primary;
+ }
+ }
+
+ &__bottom {
+ display: flex;
+ height: 64px;
+ border-top: 1px solid $color-elements;
+ }
+
+ &__themeToggle {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ flex: 1;
+ border-right: 1px solid $color-elements;
+ }
+
+ &__icon {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ flex: 1;
+ position: relative;
+ border-right: 1px solid $color-elements;
+ transition: box-shadow 0.3s;
+
+ &:last-child {
+ border-right: none;
+ }
+
+ &:hover {
+ box-shadow: inset 0 -3px 0 $color-primary;
+ }
+
+ &--active {
+ box-shadow: inset 0 -3px 0 $color-primary;
+ }
+
+ img {
+ width: 16px;
+ height: 16px;
+ }
+ }
+
+ &__iconWrap {
+ position: relative;
+ display: inline-flex;
+ }
+}
diff --git a/src/components/Header/Header.tsx b/src/components/Header/Header.tsx
new file mode 100644
index 00000000000..4ac1d3d6048
--- /dev/null
+++ b/src/components/Header/Header.tsx
@@ -0,0 +1,299 @@
+import { useEffect, useState, useRef, useCallback } from 'react';
+import { NavLink, Link, useLocation, useSearchParams } from 'react-router-dom';
+import classNames from 'classnames';
+import { useCart } from '../../context/CartContext';
+import { useFavorites } from '../../context/FavoritesContext';
+import { ThemeToggle } from '../ThemeToggle';
+import styles from './Header.module.scss';
+
+const DEBOUNCE_DELAY = 300;
+
+const getLinkClass = ({ isActive }: { isActive: boolean }) =>
+ classNames(styles.nav__link, {
+ [styles['nav__link--active']]: isActive,
+ });
+
+const getMobileLinkClass = ({ isActive }: { isActive: boolean }) =>
+ classNames(styles.mobileMenu__link, {
+ [styles['mobileMenu__link--active']]: isActive,
+ });
+
+export const Header = () => {
+ const location = useLocation();
+ const { totalItems } = useCart();
+ const { totalFavorites } = useFavorites();
+ const [searchParams, setSearchParams] = useSearchParams();
+ const [isMenuOpen, setIsMenuOpen] = useState(false);
+
+ const searchPages = ['/phones', '/tablets', '/accessories', '/favorites'];
+ const showSearch = searchPages.includes(location.pathname);
+
+ const currentQuery = searchParams.get('query') || '';
+ const [inputValue, setInputValue] = useState(currentQuery);
+ const timerRef = useRef | null>(null);
+ const inputRef = useRef(null);
+
+ const handleSearchIconClick = () => {
+ inputRef.current?.focus();
+ };
+
+ useEffect(() => {
+ setInputValue(currentQuery);
+ }, [currentQuery]);
+
+ useEffect(() => {
+ setIsMenuOpen(false);
+ }, [location.pathname]);
+
+ const applySearch = useCallback(
+ (value: string) => {
+ const params = new URLSearchParams(searchParams);
+
+ if (value.trim()) {
+ params.set('query', value.trim());
+ } else {
+ params.delete('query');
+ }
+
+ params.set('page', '1');
+ setSearchParams(params);
+ },
+ [searchParams, setSearchParams],
+ );
+
+ const handleSearchChange = (e: React.ChangeEvent) => {
+ const { value } = e.target;
+
+ setInputValue(value);
+
+ if (timerRef.current) {
+ clearTimeout(timerRef.current);
+ }
+
+ timerRef.current = setTimeout(() => {
+ applySearch(value);
+ }, DEBOUNCE_DELAY);
+ };
+
+ const handleClearSearch = () => {
+ setInputValue('');
+ applySearch('');
+ };
+
+ const toggleMenu = () => setIsMenuOpen(prev => !prev);
+
+ const getIconClass = ({ isActive }: { isActive: boolean }) =>
+ classNames(styles.header__icon, {
+ [styles['header__icon--active']]: isActive,
+ });
+
+ const getMobileIconClass = ({ isActive }: { isActive: boolean }) =>
+ classNames(styles.mobileMenu__icon, {
+ [styles['mobileMenu__icon--active']]: isActive,
+ });
+
+ const pageName = location.pathname.slice(1) || 'products';
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Home
+
+
+
+
+
+ Phones
+
+
+
+
+
+ Tablets
+
+
+
+
+
+ Accessories
+
+
+
+
+
+
+
+ {showSearch && (
+
+
+
+
+
+ {inputValue && (
+
+
+
+ )}
+
+ )}
+
+
+
+
+
+
+
+
+ {totalFavorites > 0 && (
+ {totalFavorites}
+ )}
+
+
+
+
+
+
+ {totalItems > 0 && (
+ {totalItems}
+ )}
+
+
+
+
+
+
+
+
+
+
+
+ {isMenuOpen && (
+
+
+
setIsMenuOpen(false)}
+ >
+
+
+
+
+
+
+
setIsMenuOpen(false)}
+ aria-label="Close menu"
+ >
+
+
+
+
+
+
+ Home
+
+
+ Phones
+
+
+ Tablets
+
+
+ Accessories
+
+
+
+
+
+
+
+
+
setIsMenuOpen(false)}
+ >
+
+
+ {totalFavorites > 0 && (
+ {totalFavorites}
+ )}
+
+
+
+
setIsMenuOpen(false)}
+ >
+
+
+ {totalItems > 0 && (
+ {totalItems}
+ )}
+
+
+
+
+ )}
+ >
+ );
+};
diff --git a/src/components/Header/index.ts b/src/components/Header/index.ts
new file mode 100644
index 00000000000..29429dc97e8
--- /dev/null
+++ b/src/components/Header/index.ts
@@ -0,0 +1 @@
+export { Header } from './Header';
diff --git a/src/components/Loader/Loader.module.scss b/src/components/Loader/Loader.module.scss
new file mode 100644
index 00000000000..f46084c1bdd
--- /dev/null
+++ b/src/components/Loader/Loader.module.scss
@@ -0,0 +1,23 @@
+@use '../../styles/variables' as *;
+
+.loader {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ padding: 40px 0;
+
+ &__content {
+ width: 40px;
+ height: 40px;
+ border: 4px solid $color-elements;
+ border-top-color: $color-button;
+ border-radius: 50%;
+ animation: spin 0.8s linear infinite;
+ }
+}
+
+@keyframes spin {
+ to {
+ transform: rotate(360deg);
+ }
+}
diff --git a/src/components/Loader/Loader.tsx b/src/components/Loader/Loader.tsx
new file mode 100644
index 00000000000..38d7117151d
--- /dev/null
+++ b/src/components/Loader/Loader.tsx
@@ -0,0 +1,7 @@
+import styles from './Loader.module.scss';
+
+export const Loader = () => (
+
+);
diff --git a/src/components/Loader/index.ts b/src/components/Loader/index.ts
new file mode 100644
index 00000000000..d7027885251
--- /dev/null
+++ b/src/components/Loader/index.ts
@@ -0,0 +1 @@
+export { Loader } from './Loader';
diff --git a/src/components/Pagination/Pagination.module.scss b/src/components/Pagination/Pagination.module.scss
new file mode 100644
index 00000000000..e3d7d02f645
--- /dev/null
+++ b/src/components/Pagination/Pagination.module.scss
@@ -0,0 +1,74 @@
+@use '../../styles/variables' as *;
+
+.pagination {
+ display: flex;
+ justify-content: center;
+ gap: 8px;
+ list-style: none;
+ margin-top: 24px;
+
+ @include on-tablet {
+ margin-top: 40px;
+ }
+
+ &__page {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 32px;
+ height: 32px;
+ font-family: $font-family;
+ font-size: 14px;
+ font-weight: 600;
+ line-height: 21px;
+ color: $color-primary;
+ background-color: transparent;
+ border: 1px solid $color-elements;
+ cursor: pointer;
+ transition:
+ border-color 0.3s,
+ background-color 0.3s,
+ color 0.3s;
+
+ &:hover {
+ border-color: $color-primary;
+ }
+
+ &--active {
+ color: $color-button-text;
+ background-color: $color-button;
+ border-color: $color-button;
+ cursor: default;
+
+ &:hover {
+ border-color: $color-button;
+ }
+ }
+ }
+
+ &__arrow {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 32px;
+ height: 32px;
+ background-color: transparent;
+ border: 1px solid $color-elements;
+ cursor: pointer;
+ transition: border-color 0.3s;
+
+ &:hover:not(:disabled) {
+ border-color: $color-primary;
+ }
+
+ &--disabled {
+ opacity: 0.5;
+ cursor: not-allowed;
+ }
+
+ img {
+ width: 16px;
+ height: 16px;
+ }
+ }
+}
diff --git a/src/components/Pagination/Pagination.tsx b/src/components/Pagination/Pagination.tsx
new file mode 100644
index 00000000000..de1ccba782b
--- /dev/null
+++ b/src/components/Pagination/Pagination.tsx
@@ -0,0 +1,92 @@
+import classNames from 'classnames';
+import styles from './Pagination.module.scss';
+
+const VISIBLE_PAGES = 4;
+
+type Props = {
+ total: number;
+ perPage: number;
+ currentPage: number;
+ onPageChange: (page: number) => void;
+};
+
+export const Pagination: React.FC = ({
+ total,
+ perPage,
+ currentPage,
+ onPageChange,
+}) => {
+ const totalPages = Math.ceil(total / perPage);
+
+ if (totalPages <= 1) {
+ return null;
+ }
+
+ // Calculate the visible window of pages
+ let start = Math.max(1, currentPage - 1);
+ const end = Math.min(totalPages, start + VISIBLE_PAGES - 1);
+
+ start = Math.max(1, end - VISIBLE_PAGES + 1);
+
+ const pages = Array.from({ length: end - start + 1 }, (_, i) => start + i);
+
+ const handlePrev = () => {
+ if (currentPage > 1) {
+ onPageChange(currentPage - 1);
+ }
+ };
+
+ const handleNext = () => {
+ if (currentPage < totalPages) {
+ onPageChange(currentPage + 1);
+ }
+ };
+
+ return (
+
+
+
+
+
+
+
+ {pages.map(page => (
+
+ onPageChange(page)}
+ >
+ {page}
+
+
+ ))}
+
+
+
+
+
+
+
+ );
+};
diff --git a/src/components/Pagination/index.ts b/src/components/Pagination/index.ts
new file mode 100644
index 00000000000..0a1fd4dad6c
--- /dev/null
+++ b/src/components/Pagination/index.ts
@@ -0,0 +1 @@
+export { Pagination } from './Pagination';
diff --git a/src/components/PicturesSlider/PicturesSlider.module.scss b/src/components/PicturesSlider/PicturesSlider.module.scss
new file mode 100644
index 00000000000..d5f203f655c
--- /dev/null
+++ b/src/components/PicturesSlider/PicturesSlider.module.scss
@@ -0,0 +1,104 @@
+@use '../../styles/variables' as *;
+
+.slider {
+ margin-bottom: 56px;
+
+ @include on-tablet {
+ margin-bottom: 64px;
+ }
+
+ @include on-desktop {
+ margin-bottom: 80px;
+ }
+
+ &__container {
+ display: flex;
+ align-items: center;
+ gap: 16px;
+ }
+
+ &__button {
+ display: none;
+ align-items: center;
+ justify-content: center;
+ width: 32px;
+ height: 400px;
+ border: 1px solid $color-icons;
+ background-color: $color-surface;
+ flex-shrink: 0;
+ cursor: pointer;
+ transition:
+ border-color 0.3s,
+ box-shadow 0.3s;
+
+ @include on-tablet {
+ display: flex;
+ }
+
+ &:hover {
+ border-color: $color-primary;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+ }
+
+ img {
+ width: 16px;
+ height: 16px;
+ }
+ }
+
+ &__viewport {
+ width: 100%;
+ overflow: hidden;
+ border-radius: 0;
+ }
+
+ &__track {
+ display: flex;
+ transition: transform 0.5s ease-in-out;
+ }
+
+ &__slide {
+ min-width: 100%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
+
+ &__image {
+ width: 100%;
+ height: 200px;
+ object-fit: cover;
+
+ @include on-tablet {
+ height: 320px;
+ }
+
+ @include on-desktop {
+ height: 400px;
+ }
+ }
+
+ &__dots {
+ display: flex;
+ justify-content: center;
+ gap: 14px;
+ margin-top: 18px;
+ }
+
+ &__dot {
+ width: 14px;
+ height: 4px;
+ border: none;
+ background-color: $color-elements;
+ cursor: pointer;
+ transition: background-color 0.3s;
+
+ &:hover {
+ background-color: $color-icons;
+ }
+
+ &--active {
+ background-color: $color-primary;
+ }
+ }
+}
diff --git a/src/components/PicturesSlider/PicturesSlider.tsx b/src/components/PicturesSlider/PicturesSlider.tsx
new file mode 100644
index 00000000000..af876d374c6
--- /dev/null
+++ b/src/components/PicturesSlider/PicturesSlider.tsx
@@ -0,0 +1,102 @@
+import { useState, useEffect, useCallback } from 'react';
+import styles from './PicturesSlider.module.scss';
+
+const bannerImages = [
+ {
+ id: 1,
+ src: 'img/banner-iphone-14.png',
+ alt: 'Phone 14 Pro',
+ },
+ {
+ id: 2,
+ src: 'img/banner-phones.png',
+ alt: 'Phones banner',
+ },
+ {
+ id: 3,
+ src: 'img/banner-tablets.png',
+ alt: 'Tablets banner',
+ },
+ {
+ id: 4,
+ src: 'img/banner-accessories.png',
+ alt: 'Accessories banner',
+ },
+];
+
+export const PicturesSlider = () => {
+ const [currentIndex, setCurrentIndex] = useState(0);
+
+ const goToNext = useCallback(() => {
+ setCurrentIndex(prev => (prev === bannerImages.length - 1 ? 0 : prev + 1));
+ }, []);
+
+ const goToPrev = useCallback(() => {
+ setCurrentIndex(prev => (prev === 0 ? bannerImages.length - 1 : prev - 1));
+ }, []);
+
+ const goToSlide = (index: number) => {
+ setCurrentIndex(index);
+ };
+
+ useEffect(() => {
+ const interval = setInterval(goToNext, 5000);
+
+ return () => clearInterval(interval);
+ }, [goToNext]);
+
+ return (
+
+
+
+
+
+
+
+
+ {bannerImages.map(image => (
+
+
+
+ ))}
+
+
+
+
+
+
+
+
+
+ {bannerImages.map((image, index) => (
+ goToSlide(index)}
+ aria-label={`Go to slide ${index + 1}`}
+ />
+ ))}
+
+
+ );
+};
diff --git a/src/components/PicturesSlider/index.ts b/src/components/PicturesSlider/index.ts
new file mode 100644
index 00000000000..3d16f0bbb89
--- /dev/null
+++ b/src/components/PicturesSlider/index.ts
@@ -0,0 +1 @@
+export { PicturesSlider } from './PicturesSlider';
diff --git a/src/components/ProductCard/ProductCard.module.scss b/src/components/ProductCard/ProductCard.module.scss
new file mode 100644
index 00000000000..6102e08f97a
--- /dev/null
+++ b/src/components/ProductCard/ProductCard.module.scss
@@ -0,0 +1,173 @@
+@use '../../styles/variables' as *;
+
+.card {
+ display: flex;
+ flex-direction: column;
+ padding: 32px;
+ border: 1px solid $color-elements;
+ background-color: $color-surface;
+ width: 100%;
+ min-width: 212px;
+ max-width: 272px;
+ flex-shrink: 0;
+ transition: box-shadow 0.3s;
+
+ &:hover {
+ box-shadow: 0 2px 16px rgba(0, 0, 0, 0.1);
+ }
+
+ &__imageLink {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ height: 196px;
+ margin-bottom: 8px;
+ }
+
+ &__image {
+ max-width: 100%;
+ max-height: 196px;
+ object-fit: contain;
+ transition: transform 0.3s;
+
+ &:hover {
+ transform: scale(1.1);
+ }
+ }
+
+ &__title {
+ font-size: 14px;
+ font-weight: 600;
+ line-height: 21px;
+ color: $color-primary;
+ margin-bottom: 8px;
+ min-height: 42px;
+ display: -webkit-box;
+ line-clamp: 2;
+ -webkit-line-clamp: 2;
+ -webkit-box-orient: vertical;
+ overflow: hidden;
+ transition: color 0.3s;
+
+ &:hover {
+ color: $color-accent;
+ }
+ }
+
+ &__prices {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ margin-bottom: 8px;
+ }
+
+ &__price {
+ font-size: 22px;
+ font-weight: 700;
+ line-height: 31px;
+ color: $color-primary;
+ }
+
+ &__fullPrice {
+ font-size: 22px;
+ font-weight: 600;
+ line-height: 28px;
+ color: $color-secondary;
+ text-decoration: line-through;
+ }
+
+ &__divider {
+ width: 100%;
+ height: 1px;
+ background-color: $color-elements;
+ margin-bottom: 8px;
+ }
+
+ &__specs {
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+ margin-bottom: 16px;
+ }
+
+ &__spec {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ }
+
+ &__specName {
+ font-size: 12px;
+ font-weight: 600;
+ line-height: 15px;
+ color: $color-secondary;
+ }
+
+ &__specValue {
+ font-size: 12px;
+ font-weight: 700;
+ line-height: 15px;
+ color: $color-primary;
+ }
+
+ &__actions {
+ display: flex;
+ gap: 8px;
+ margin-top: auto;
+ }
+
+ &__addToCart {
+ flex: 1;
+ height: 40px;
+ font-size: 14px;
+ font-weight: 600;
+ line-height: 21px;
+ color: $color-button-text;
+ background-color: $color-button;
+ border: none;
+ cursor: pointer;
+ transition:
+ background-color 0.3s,
+ box-shadow 0.3s;
+
+ &:hover {
+ box-shadow: 0 3px 13px $color-button-shadow;
+ }
+
+ &--active {
+ color: $color-green;
+ background-color: $color-hover-and-bg;
+ border: 1px solid $color-elements;
+
+ &:hover {
+ box-shadow: none;
+ border-color: $color-primary;
+ }
+ }
+ }
+
+ &__favourite {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 40px;
+ height: 40px;
+ border: 1px solid $color-icons;
+ background-color: $color-hover-and-bg;
+ cursor: pointer;
+ transition: border-color 0.3s;
+
+ &:hover {
+ border-color: $color-primary;
+ }
+
+ &--active {
+ border-color: $color-elements;
+ }
+
+ img {
+ width: 16px;
+ height: 16px;
+ }
+ }
+}
diff --git a/src/components/ProductCard/ProductCard.tsx b/src/components/ProductCard/ProductCard.tsx
new file mode 100644
index 00000000000..d3634bb2d6f
--- /dev/null
+++ b/src/components/ProductCard/ProductCard.tsx
@@ -0,0 +1,105 @@
+import { Link } from 'react-router-dom';
+import classNames from 'classnames';
+import { Product } from '../../types/Product';
+import { useCart } from '../../context/CartContext';
+import { useFavorites } from '../../context/FavoritesContext';
+import styles from './ProductCard.module.scss';
+
+type Props = {
+ product: Product;
+ hasDiscount?: boolean;
+};
+
+export const ProductCard: React.FC = ({
+ product,
+ hasDiscount: hasDiscountProp,
+}) => {
+ const { itemId, name, fullPrice, price, screen, capacity, ram } = product;
+ const hasDiscount = hasDiscountProp ?? fullPrice > price;
+ const displayedPrice = hasDiscount ? price : fullPrice;
+
+ const { addToCart, isInCart } = useCart();
+ const { toggleFavorite, isFavorite } = useFavorites();
+
+ const inCart = isInCart(product.id);
+ const favorited = isFavorite(product.id);
+
+ const handleAddToCart = () => {
+ addToCart(product);
+ };
+
+ const handleToggleFav = () => {
+ toggleFavorite(product);
+ };
+
+ return (
+
+
+
+
+
+
+ {name}
+
+
+
+ ${displayedPrice}
+ {hasDiscount && (
+ ${fullPrice}
+ )}
+
+
+
+
+
+
+ Screen
+ {screen}
+
+
+
+ Capacity
+ {capacity}
+
+
+
+ RAM
+ {ram}
+
+
+
+
+
+ {inCart ? 'Added to cart' : 'Add to cart'}
+
+
+
+
+
+
+
+ );
+};
diff --git a/src/components/ProductCard/index.ts b/src/components/ProductCard/index.ts
new file mode 100644
index 00000000000..c4f2778191c
--- /dev/null
+++ b/src/components/ProductCard/index.ts
@@ -0,0 +1 @@
+export { ProductCard } from './ProductCard';
diff --git a/src/components/ProductsSlider/ProductsSlider.module.scss b/src/components/ProductsSlider/ProductsSlider.module.scss
new file mode 100644
index 00000000000..e238a8622e8
--- /dev/null
+++ b/src/components/ProductsSlider/ProductsSlider.module.scss
@@ -0,0 +1,82 @@
+@use '../../styles/variables' as *;
+
+.productsSlider {
+ margin-bottom: 56px;
+
+ @include on-tablet {
+ margin-bottom: 64px;
+ }
+
+ @include on-desktop {
+ margin-bottom: 80px;
+ }
+
+ &__header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 24px;
+ }
+
+ &__title {
+ font-size: 22px;
+ font-weight: 700;
+ line-height: 31px;
+ color: $color-primary;
+
+ @include on-desktop {
+ font-size: 32px;
+ line-height: 41px;
+ letter-spacing: -0.01em;
+ }
+ }
+
+ &__buttons {
+ display: flex;
+ gap: 16px;
+ }
+
+ &__button {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 32px;
+ height: 32px;
+ border: 1px solid $color-icons;
+ background-color: $color-surface;
+ cursor: pointer;
+ transition:
+ border-color 0.3s,
+ opacity 0.3s;
+
+ &:hover:not(:disabled) {
+ border-color: $color-primary;
+ }
+
+ &--disabled {
+ opacity: 0.5;
+ cursor: not-allowed;
+ }
+
+ img {
+ width: 16px;
+ height: 16px;
+ }
+ }
+
+ &__viewport {
+ overflow: hidden;
+ }
+
+ &__track {
+ display: flex;
+ gap: 16px;
+ transition: transform 0.5s ease;
+
+ // Cards inside slider keep fixed width
+ > * {
+ width: 272px;
+ max-width: 272px;
+ }
+ }
+}
diff --git a/src/components/ProductsSlider/ProductsSlider.tsx b/src/components/ProductsSlider/ProductsSlider.tsx
new file mode 100644
index 00000000000..19023e6baac
--- /dev/null
+++ b/src/components/ProductsSlider/ProductsSlider.tsx
@@ -0,0 +1,86 @@
+import { useState, useRef } from 'react';
+import { Product } from '../../types/Product';
+import { ProductCard } from '../ProductCard';
+import styles from './ProductsSlider.module.scss';
+
+type Props = {
+ title: string;
+ products: Product[];
+ hasDiscount?: boolean;
+};
+
+const CARD_WIDTH = 272;
+const GAP = 16;
+
+export const ProductsSlider: React.FC = ({
+ title,
+ products,
+ hasDiscount,
+}) => {
+ const [scrollPosition, setScrollPosition] = useState(0);
+ const trackRef = useRef(null);
+
+ const step = CARD_WIDTH + GAP;
+ const maxScroll = Math.max(0, products.length * step - step * 4);
+
+ const handlePrev = () => {
+ setScrollPosition(prev => Math.max(0, prev - step));
+ };
+
+ const handleNext = () => {
+ setScrollPosition(prev => Math.min(maxScroll, prev + step));
+ };
+
+ const isPrevDisabled = scrollPosition <= 0;
+ const isNextDisabled = scrollPosition >= maxScroll;
+
+ return (
+
+
+
{title}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {products.map(product => (
+
+ ))}
+
+
+
+ );
+};
diff --git a/src/components/ProductsSlider/index.ts b/src/components/ProductsSlider/index.ts
new file mode 100644
index 00000000000..0a5bb986628
--- /dev/null
+++ b/src/components/ProductsSlider/index.ts
@@ -0,0 +1 @@
+export { ProductsSlider } from './ProductsSlider';
diff --git a/src/components/ThemeToggle/ThemeToggle.module.scss b/src/components/ThemeToggle/ThemeToggle.module.scss
new file mode 100644
index 00000000000..3836d935899
--- /dev/null
+++ b/src/components/ThemeToggle/ThemeToggle.module.scss
@@ -0,0 +1,55 @@
+@use '../../styles/variables' as *;
+
+.toggle {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 32px;
+ height: 32px;
+ padding: 0;
+ border: none;
+ background: none;
+ cursor: pointer;
+ border-radius: 50%;
+ transition:
+ background-color 0.3s,
+ transform 0.3s;
+ color: $color-primary;
+
+ &:hover {
+ background-color: $color-hover-and-bg;
+ transform: rotate(15deg);
+ }
+
+ &:active {
+ transform: scale(0.9);
+ }
+}
+
+.toggle__icon {
+ position: relative;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 16px;
+ height: 16px;
+}
+
+.toggle__sun,
+.toggle__moon {
+ position: absolute;
+ inset: 0;
+ width: 16px;
+ height: 16px;
+ transition:
+ opacity 0.4s ease,
+ transform 0.4s ease;
+ opacity: 0;
+ transform: rotate(-90deg) scale(0.5);
+}
+
+.toggle__sun--visible,
+.toggle__moon--visible {
+ opacity: 1;
+ transform: rotate(0deg) scale(1);
+}
diff --git a/src/components/ThemeToggle/ThemeToggle.tsx b/src/components/ThemeToggle/ThemeToggle.tsx
new file mode 100644
index 00000000000..d0e65472e11
--- /dev/null
+++ b/src/components/ThemeToggle/ThemeToggle.tsx
@@ -0,0 +1,65 @@
+import classNames from 'classnames';
+import { useTheme } from '../../context/ThemeContext';
+import styles from './ThemeToggle.module.scss';
+
+export const ThemeToggle = () => {
+ const { theme, toggleTheme } = useTheme();
+ const isDark = theme === 'dark';
+
+ return (
+
+
+ {/* Sun icon — visible in dark mode */}
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* Moon icon — visible in light mode */}
+
+
+
+
+
+ );
+};
diff --git a/src/components/ThemeToggle/index.ts b/src/components/ThemeToggle/index.ts
new file mode 100644
index 00000000000..0f27a513f02
--- /dev/null
+++ b/src/components/ThemeToggle/index.ts
@@ -0,0 +1 @@
+export { ThemeToggle } from './ThemeToggle';
diff --git a/src/context/CartContext.tsx b/src/context/CartContext.tsx
new file mode 100644
index 00000000000..e76e2043e9e
--- /dev/null
+++ b/src/context/CartContext.tsx
@@ -0,0 +1,147 @@
+import React, { createContext, useContext, useReducer, useEffect } from 'react';
+import { Product } from '../types/Product';
+import { CartItem } from '../types/CartItem';
+
+/* ---------- helpers ---------- */
+
+const STORAGE_KEY = 'cart';
+
+function loadCart(): CartItem[] {
+ try {
+ const raw = localStorage.getItem(STORAGE_KEY);
+
+ return raw ? JSON.parse(raw) : [];
+ } catch {
+ return [];
+ }
+}
+
+function saveCart(items: CartItem[]) {
+ localStorage.setItem(STORAGE_KEY, JSON.stringify(items));
+}
+
+/* ---------- actions ---------- */
+
+type Action =
+ | { type: 'ADD'; product: Product }
+ | { type: 'REMOVE'; productId: number }
+ | { type: 'INCREMENT'; productId: number }
+ | { type: 'DECREMENT'; productId: number }
+ | { type: 'CLEAR' };
+
+function cartReducer(state: CartItem[], action: Action): CartItem[] {
+ switch (action.type) {
+ case 'ADD': {
+ const exists = state.find(i => i.product.id === action.product.id);
+
+ if (exists) {
+ return state;
+ }
+
+ return [
+ ...state,
+ { id: action.product.id, quantity: 1, product: action.product },
+ ];
+ }
+
+ case 'REMOVE':
+ return state.filter(i => i.product.id !== action.productId);
+
+ case 'INCREMENT':
+ return state.map(i =>
+ i.product.id === action.productId
+ ? { ...i, quantity: i.quantity + 1 }
+ : i,
+ );
+
+ case 'DECREMENT':
+ return state.map(i =>
+ i.product.id === action.productId && i.quantity > 1
+ ? { ...i, quantity: i.quantity - 1 }
+ : i,
+ );
+
+ case 'CLEAR':
+ return [];
+
+ default:
+ return state;
+ }
+}
+
+/* ---------- context ---------- */
+
+interface CartContextType {
+ items: CartItem[];
+ addToCart: (product: Product) => void;
+ removeFromCart: (productId: number) => void;
+ increment: (productId: number) => void;
+ decrement: (productId: number) => void;
+ clearCart: () => void;
+ isInCart: (productId: number) => boolean;
+ totalItems: number;
+ totalPrice: number;
+}
+
+const CartContext = createContext({
+ items: [],
+ addToCart: () => {},
+ removeFromCart: () => {},
+ increment: () => {},
+ decrement: () => {},
+ clearCart: () => {},
+ isInCart: () => false,
+ totalItems: 0,
+ totalPrice: 0,
+});
+
+export const useCart = () => useContext(CartContext);
+
+/* ---------- provider ---------- */
+
+export const CartProvider: React.FC<{ children: React.ReactNode }> = ({
+ children,
+}) => {
+ const [items, dispatch] = useReducer(cartReducer, [], loadCart);
+
+ useEffect(() => {
+ saveCart(items);
+ }, [items]);
+
+ const addToCart = (product: Product) => dispatch({ type: 'ADD', product });
+
+ const removeFromCart = (productId: number) =>
+ dispatch({ type: 'REMOVE', productId });
+
+ const increment = (productId: number) =>
+ dispatch({ type: 'INCREMENT', productId });
+
+ const decrement = (productId: number) =>
+ dispatch({ type: 'DECREMENT', productId });
+
+ const clearCart = () => dispatch({ type: 'CLEAR' });
+
+ const isInCart = (productId: number) =>
+ items.some(i => i.product.id === productId);
+
+ const totalItems = items.reduce((sum, i) => sum + i.quantity, 0);
+
+ const totalPrice = items.reduce(
+ (sum, i) => sum + i.product.price * i.quantity,
+ 0,
+ );
+
+ const value: CartContextType = {
+ items,
+ addToCart,
+ removeFromCart,
+ increment,
+ decrement,
+ clearCart,
+ isInCart,
+ totalItems,
+ totalPrice,
+ };
+
+ return {children} ;
+};
diff --git a/src/context/FavoritesContext.tsx b/src/context/FavoritesContext.tsx
new file mode 100644
index 00000000000..e99f8a65d71
--- /dev/null
+++ b/src/context/FavoritesContext.tsx
@@ -0,0 +1,86 @@
+import React, {
+ createContext,
+ useContext,
+ useState,
+ useEffect,
+ useCallback,
+} from 'react';
+import { Product } from '../types/Product';
+
+/* ---------- helpers ---------- */
+
+const STORAGE_KEY = 'favorites';
+
+function loadFavorites(): Product[] {
+ try {
+ const raw = localStorage.getItem(STORAGE_KEY);
+
+ return raw ? JSON.parse(raw) : [];
+ } catch {
+ return [];
+ }
+}
+
+function saveFavorites(items: Product[]) {
+ localStorage.setItem(STORAGE_KEY, JSON.stringify(items));
+}
+
+/* ---------- context ---------- */
+
+interface FavoritesContextType {
+ favorites: Product[];
+ toggleFavorite: (product: Product) => void;
+ isFavorite: (productId: number) => boolean;
+ totalFavorites: number;
+}
+
+const FavoritesContext = createContext({
+ favorites: [],
+ toggleFavorite: () => {},
+ isFavorite: () => false,
+ totalFavorites: 0,
+});
+
+export const useFavorites = () => useContext(FavoritesContext);
+
+/* ---------- provider ---------- */
+
+export const FavoritesProvider: React.FC<{ children: React.ReactNode }> = ({
+ children,
+}) => {
+ const [favorites, setFavorites] = useState(loadFavorites);
+
+ useEffect(() => {
+ saveFavorites(favorites);
+ }, [favorites]);
+
+ const toggleFavorite = useCallback((product: Product) => {
+ setFavorites(prev => {
+ const exists = prev.some(p => p.id === product.id);
+
+ if (exists) {
+ return prev.filter(p => p.id !== product.id);
+ }
+
+ return [...prev, product];
+ });
+ }, []);
+
+ const isFavorite = useCallback(
+ (productId: number) => favorites.some(p => p.id === productId),
+ [favorites],
+ );
+
+ const value: FavoritesContextType = {
+ favorites,
+ toggleFavorite,
+ isFavorite,
+ totalFavorites: favorites.length,
+ };
+
+ return (
+
+ {children}
+
+ );
+};
diff --git a/src/context/ThemeContext.tsx b/src/context/ThemeContext.tsx
new file mode 100644
index 00000000000..a9c8ed9777d
--- /dev/null
+++ b/src/context/ThemeContext.tsx
@@ -0,0 +1,56 @@
+import React, { createContext, useContext, useState, useEffect } from 'react';
+
+type Theme = 'light' | 'dark';
+
+interface ThemeContextType {
+ theme: Theme;
+ toggleTheme: () => void;
+}
+
+const STORAGE_KEY = 'theme';
+
+function getInitialTheme(): Theme {
+ try {
+ const stored = localStorage.getItem(STORAGE_KEY);
+
+ if (stored === 'light' || stored === 'dark') {
+ return stored;
+ }
+ } catch {
+ /* empty */
+ }
+
+ if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
+ return 'dark';
+ }
+
+ return 'light';
+}
+
+const ThemeContext = createContext({
+ theme: 'light',
+ toggleTheme: () => {},
+});
+
+export const useTheme = () => useContext(ThemeContext);
+
+export const ThemeProvider: React.FC<{ children: React.ReactNode }> = ({
+ children,
+}) => {
+ const [theme, setTheme] = useState(getInitialTheme);
+
+ useEffect(() => {
+ document.documentElement.setAttribute('data-theme', theme);
+ localStorage.setItem(STORAGE_KEY, theme);
+ }, [theme]);
+
+ const toggleTheme = () => {
+ setTheme(prev => (prev === 'light' ? 'dark' : 'light'));
+ };
+
+ return (
+
+ {children}
+
+ );
+};
diff --git a/src/index.tsx b/src/index.tsx
index 50470f1508d..35a704d1003 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -1,4 +1,9 @@
import { createRoot } from 'react-dom/client';
+import { HashRouter as Router } from 'react-router-dom';
import { App } from './App';
-createRoot(document.getElementById('root') as HTMLElement).render( );
+createRoot(document.getElementById('root') as HTMLElement).render(
+
+
+ ,
+);
diff --git a/src/modules/AccessoriesPage/AccessoriesPage.tsx b/src/modules/AccessoriesPage/AccessoriesPage.tsx
new file mode 100644
index 00000000000..ea6a3d08643
--- /dev/null
+++ b/src/modules/AccessoriesPage/AccessoriesPage.tsx
@@ -0,0 +1,5 @@
+import { ProductsPage } from '../ProductsPage';
+
+export const AccessoriesPage = () => (
+
+);
diff --git a/src/modules/AccessoriesPage/index.ts b/src/modules/AccessoriesPage/index.ts
new file mode 100644
index 00000000000..83dcf696d14
--- /dev/null
+++ b/src/modules/AccessoriesPage/index.ts
@@ -0,0 +1 @@
+export { AccessoriesPage } from './AccessoriesPage';
diff --git a/src/modules/CartPage/CartPage.module.scss b/src/modules/CartPage/CartPage.module.scss
new file mode 100644
index 00000000000..d46504ee345
--- /dev/null
+++ b/src/modules/CartPage/CartPage.module.scss
@@ -0,0 +1,249 @@
+@use '../../styles/variables' as *;
+
+.cart {
+ &__empty {
+ padding: 40px;
+ text-align: center;
+ font-size: 16px;
+ color: $color-secondary;
+ }
+
+ &__content {
+ display: flex;
+ flex-direction: column;
+ gap: 32px;
+ margin-top: 32px;
+
+ @include on-desktop {
+ flex-direction: row;
+ gap: 40px;
+ }
+ }
+
+ &__list {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ gap: 16px;
+ }
+
+ // Cart Item — matches Figma "Cart item" component
+ &__item {
+ display: flex;
+ flex-direction: column;
+ gap: 16px;
+ padding: 16px;
+ border: 1px solid $color-elements;
+ background-color: $color-surface;
+
+ @include on-tablet {
+ flex-direction: row;
+ align-items: center;
+ gap: 24px;
+ padding: 24px;
+ }
+ }
+
+ // Mobile: first row (close + image + name)
+ &__itemTop {
+ display: flex;
+ align-items: center;
+ gap: 16px;
+ width: 100%;
+
+ @include on-tablet {
+ display: contents;
+ }
+ }
+
+ // Mobile: second row (counter + price)
+ &__itemBottom {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ width: 100%;
+
+ @include on-tablet {
+ display: contents;
+ }
+ }
+
+ // Close (remove) button
+ &__remove {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 16px;
+ height: 16px;
+ flex-shrink: 0;
+ padding: 0;
+ background: none;
+ border: none;
+ cursor: pointer;
+ opacity: 0.5;
+ transition: opacity 0.3s;
+
+ &:hover {
+ opacity: 1;
+ }
+
+ img {
+ width: 16px;
+ height: 16px;
+ }
+ }
+
+ // Product image
+ &__imageLink {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 80px;
+ height: 80px;
+ flex-shrink: 0;
+ }
+
+ &__image {
+ max-width: 100%;
+ max-height: 100%;
+ object-fit: contain;
+ }
+
+ // Product name
+ &__name {
+ flex: 1;
+ font-size: 14px;
+ font-weight: 500;
+ line-height: 21px;
+ color: $color-primary;
+ min-width: 0;
+ transition: color 0.3s;
+
+ &:hover {
+ color: $color-accent;
+ }
+ }
+
+ // Counter (– count +)
+ &__counter {
+ display: flex;
+ align-items: center;
+ gap: 0;
+ flex-shrink: 0;
+ }
+
+ &__counterBtn {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 32px;
+ height: 32px;
+ font-size: 16px;
+ font-weight: 600;
+ color: $color-primary;
+ background: transparent;
+ border: 1px solid $color-icons;
+ cursor: pointer;
+ transition: border-color 0.3s;
+
+ &:hover:not(:disabled) {
+ border-color: $color-primary;
+ }
+
+ &--disabled {
+ color: $color-elements;
+ border-color: $color-elements;
+ cursor: not-allowed;
+ }
+ }
+
+ &__quantity {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 32px;
+ height: 32px;
+ font-size: 14px;
+ font-weight: 500;
+ line-height: 21px;
+ color: $color-primary;
+ text-align: center;
+ }
+
+ // Price
+ &__price {
+ font-size: 22px;
+ font-weight: 800;
+ line-height: 1.4;
+ color: $color-primary;
+ white-space: nowrap;
+ text-align: right;
+
+ @include on-tablet {
+ width: 80px;
+ flex-shrink: 0;
+ }
+ }
+
+ // ================
+ // Summary section
+ // ================
+ &__summary {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ padding: 24px;
+ border: 1px solid $color-elements;
+ width: 100%;
+
+ @include on-desktop {
+ width: 368px;
+ flex-shrink: 0;
+ align-self: flex-start;
+ }
+ }
+
+ &__totalPrice {
+ font-size: 32px;
+ font-weight: 700;
+ line-height: 41px;
+ letter-spacing: -0.01em;
+ color: $color-primary;
+ text-align: center;
+ margin-bottom: 8px;
+ }
+
+ &__totalLabel {
+ font-size: 14px;
+ font-weight: 600;
+ line-height: 21px;
+ color: $color-secondary;
+ text-align: center;
+ margin-bottom: 16px;
+ }
+
+ &__summaryDivider {
+ width: 100%;
+ height: 1px;
+ background-color: $color-elements;
+ margin-bottom: 16px;
+ }
+
+ &__checkout {
+ width: 100%;
+ height: 48px;
+ font-family: $font-family;
+ font-size: 14px;
+ font-weight: 600;
+ line-height: 21px;
+ color: $color-button-text;
+ background-color: $color-button;
+ border: none;
+ cursor: pointer;
+ transition: box-shadow 0.3s;
+
+ &:hover {
+ box-shadow: 0 3px 13px $color-button-shadow;
+ }
+ }
+}
diff --git a/src/modules/CartPage/CartPage.tsx b/src/modules/CartPage/CartPage.tsx
new file mode 100644
index 00000000000..e75c078891f
--- /dev/null
+++ b/src/modules/CartPage/CartPage.tsx
@@ -0,0 +1,131 @@
+import { Link } from 'react-router-dom';
+import classNames from 'classnames';
+import { BackButton } from '../../components/BackButton';
+import { useCart } from '../../context/CartContext';
+import styles from './CartPage.module.scss';
+
+export const CartPage = () => {
+ const {
+ items,
+ removeFromCart,
+ increment,
+ decrement,
+ clearCart,
+ totalItems,
+ totalPrice,
+ } = useCart();
+
+ const handleCheckout = () => {
+ // eslint-disable-next-line no-alert
+ if (
+ window.confirm(
+ 'Checkout is not implemented yet. Do you want to clear the Cart?',
+ )
+ ) {
+ clearCart();
+ }
+ };
+
+ return (
+
+
+
+
Cart
+
+ {items.length === 0 ? (
+
Your cart is empty
+ ) : (
+
+
+ {items.map(({ product, quantity }) => (
+
+
+
removeFromCart(product.id)}
+ aria-label="Remove"
+ data-cy="cartDeleteButton"
+ >
+
+
+
+
+
+
+
+
+ {product.name}
+
+
+
+
+
+ decrement(product.id)}
+ aria-label="Decrease quantity"
+ >
+ −
+
+
+
+ {quantity}
+
+
+ increment(product.id)}
+ aria-label="Increase quantity"
+ >
+ +
+
+
+
+
+ ${product.price * quantity}
+
+
+
+ ))}
+
+
+
+
${totalPrice}
+
+ {`Total for ${totalItems} item${totalItems !== 1 ? 's' : ''}`}
+
+
+
+
+
+ Checkout
+
+
+
+ )}
+
+ );
+};
diff --git a/src/modules/CartPage/index.ts b/src/modules/CartPage/index.ts
new file mode 100644
index 00000000000..203fb0ea4bd
--- /dev/null
+++ b/src/modules/CartPage/index.ts
@@ -0,0 +1 @@
+export { CartPage } from './CartPage';
diff --git a/src/modules/FavoritesPage/FavoritesPage.module.scss b/src/modules/FavoritesPage/FavoritesPage.module.scss
new file mode 100644
index 00000000000..82dbfb403bc
--- /dev/null
+++ b/src/modules/FavoritesPage/FavoritesPage.module.scss
@@ -0,0 +1,25 @@
+@use '../../styles/variables' as *;
+
+.favPage {
+ &__grid {
+ display: grid;
+ grid-template-columns: 1fr;
+ gap: 16px;
+ justify-items: center;
+
+ @include on-tablet {
+ grid-template-columns: repeat(2, 1fr);
+ }
+
+ @include on-desktop {
+ grid-template-columns: repeat(4, 1fr);
+ }
+ }
+
+ &__empty {
+ padding: 40px;
+ text-align: center;
+ font-size: 16px;
+ color: $color-secondary;
+ }
+}
diff --git a/src/modules/FavoritesPage/FavoritesPage.tsx b/src/modules/FavoritesPage/FavoritesPage.tsx
new file mode 100644
index 00000000000..cf9071ae68b
--- /dev/null
+++ b/src/modules/FavoritesPage/FavoritesPage.tsx
@@ -0,0 +1,40 @@
+import { useSearchParams } from 'react-router-dom';
+import { Breadcrumbs } from '../../components/Breadcrumbs';
+import { ProductCard } from '../../components/ProductCard';
+import { useFavorites } from '../../context/FavoritesContext';
+import styles from './FavoritesPage.module.scss';
+
+export const FavoritesPage = () => {
+ const { favorites, totalFavorites } = useFavorites();
+ const [searchParams] = useSearchParams();
+ const query = searchParams.get('query') || '';
+
+ const normalizedQuery = query.toLowerCase().trim();
+
+ const filtered = query
+ ? favorites.filter(p => p.name.toLowerCase().includes(normalizedQuery))
+ : favorites;
+
+ return (
+
+
+
+
Favourites
+
{totalFavorites} items
+
+ {filtered.length === 0 ? (
+
+ {query
+ ? `No search results for "${query}"`
+ : "You don't have any favourites yet"}
+
+ ) : (
+
+ {filtered.map(product => (
+
+ ))}
+
+ )}
+
+ );
+};
diff --git a/src/modules/FavoritesPage/index.ts b/src/modules/FavoritesPage/index.ts
new file mode 100644
index 00000000000..cc5cab74bca
--- /dev/null
+++ b/src/modules/FavoritesPage/index.ts
@@ -0,0 +1 @@
+export { FavoritesPage } from './FavoritesPage';
diff --git a/src/modules/HomePage/HomePage.module.scss b/src/modules/HomePage/HomePage.module.scss
new file mode 100644
index 00000000000..316be3610b0
--- /dev/null
+++ b/src/modules/HomePage/HomePage.module.scss
@@ -0,0 +1,172 @@
+@use '../../styles/variables' as *;
+
+.homePage {
+ padding-top: 8px;
+
+ @include on-tablet {
+ padding-top: 16px;
+ }
+
+ &__title {
+ font-size: 32px;
+ font-weight: 700;
+ line-height: 41px;
+ letter-spacing: -0.01em;
+ margin-bottom: 24px;
+ color: $color-primary;
+
+ @include on-tablet {
+ font-size: 48px;
+ line-height: 56px;
+ margin-bottom: 32px;
+ }
+ }
+}
+
+.error {
+ font-size: 18px;
+ color: $color-red;
+ margin-bottom: 16px;
+
+ &__button {
+ padding: 8px 24px;
+ font-size: 14px;
+ font-weight: 600;
+ color: $color-button-text;
+ background-color: $color-button;
+ border: none;
+ cursor: pointer;
+ transition: filter 0.3s;
+
+ &:hover {
+ filter: brightness(1.3);
+ }
+ }
+}
+
+.categories {
+ margin-bottom: 56px;
+
+ @include on-tablet {
+ margin-bottom: 64px;
+ }
+
+ @include on-desktop {
+ margin-bottom: 80px;
+ }
+
+ &__title {
+ font-size: 22px;
+ font-weight: 700;
+ line-height: 31px;
+ letter-spacing: -0.32px;
+ color: $color-primary;
+ margin-bottom: 24px;
+
+ @include on-desktop {
+ font-size: 32px;
+ line-height: 41px;
+ margin-bottom: 40px;
+ }
+ }
+
+ &__grid {
+ display: grid;
+ grid-template-columns: 1fr;
+ gap: 32px;
+
+ @include on-tablet {
+ grid-template-columns: repeat(3, 1fr);
+ gap: 16px;
+ }
+ }
+}
+
+.category {
+ display: flex;
+ flex-direction: column;
+ text-decoration: none;
+
+ &__image {
+ display: block;
+ width: 100%;
+ aspect-ratio: 1 / 1;
+ overflow: hidden;
+ margin-bottom: 24px;
+ position: relative;
+
+ @include on-desktop {
+ aspect-ratio: 1 / 1;
+ }
+
+ &--phones {
+ background-color: #6d6474;
+ }
+
+ &--tablets {
+ background-color: #8d8d92;
+ }
+
+ &--accessories {
+ background-color: #973d5f;
+ }
+ }
+
+ &__img {
+ position: absolute;
+ max-width: none;
+ object-fit: cover;
+ transition: transform 0.3s;
+
+ &:hover {
+ transform: scale(1.05);
+ }
+ }
+
+ // Mobile Phones (1st) - proportional: 386x457 at offset (49, 40) in 368 container
+ &:nth-child(1) &__img {
+ left: 13.32%;
+ top: 10.87%;
+ width: 104.89%;
+ height: 124.18%;
+ }
+
+ // Tablets (2nd) - proportional: 546x546 at offset (22, 20) in 368 container
+ &:nth-child(2) &__img {
+ left: 5.98%;
+ top: 5.43%;
+ width: 148.37%;
+ height: 148.37%;
+ }
+
+ // Accessories (3rd) - proportional: 1472x880 at offset (-368, -458) in 368 container
+ &:nth-child(3) &__img {
+ left: -100%;
+ top: -124.46%;
+ width: 400%;
+ height: 239.13%;
+ }
+
+ &__name {
+ font-size: 20px;
+ font-weight: 700;
+ line-height: normal;
+ color: $color-primary;
+ margin-bottom: 4px;
+
+ @include on-desktop {
+ font-weight: 600;
+ }
+ }
+
+ &__count {
+ font-size: 14px;
+ font-weight: 600;
+ line-height: 21px;
+ color: $color-secondary;
+
+ @include on-desktop {
+ font-weight: 500;
+ }
+ }
+}
diff --git a/src/modules/HomePage/HomePage.tsx b/src/modules/HomePage/HomePage.tsx
new file mode 100644
index 00000000000..f8c3e4c25c8
--- /dev/null
+++ b/src/modules/HomePage/HomePage.tsx
@@ -0,0 +1,123 @@
+import { useState, useEffect } from 'react';
+import { Link } from 'react-router-dom';
+import { Product } from '../../types/Product';
+import { getProducts } from '../../utils/api';
+import { PicturesSlider } from '../../components/PicturesSlider';
+import { ProductsSlider } from '../../components/ProductsSlider';
+import { Loader } from '../../components/Loader';
+import styles from './HomePage.module.scss';
+
+export const HomePage = () => {
+ const [products, setProducts] = useState([]);
+ const [isLoading, setIsLoading] = useState(true);
+ const [error, setError] = useState('');
+
+ useEffect(() => {
+ setIsLoading(true);
+
+ getProducts()
+ .then(setProducts)
+ .catch(() => setError('Something went wrong'))
+ .finally(() => setIsLoading(false));
+ }, []);
+
+ const hotPrices = [...products]
+ .filter(p => p.fullPrice > p.price)
+ .sort((a, b) => b.fullPrice - b.price - (a.fullPrice - a.price));
+
+ const brandNew = [...products].sort((a, b) => b.year - a.year);
+
+ const phonesCount = products.filter(p => p.category === 'phones').length;
+ const tabletsCount = products.filter(p => p.category === 'tablets').length;
+ const accessoriesCount = products.filter(
+ p => p.category === 'accessories',
+ ).length;
+
+ if (isLoading) {
+ return ;
+ }
+
+ if (error) {
+ return (
+
+
{error}
+
window.location.reload()}
+ className={styles.error__button}
+ >
+ Reload
+
+
+ );
+ }
+
+ return (
+
+
+
+ Welcome to Nice Gadgets store!
+
+
+
+
+
+
+ Shop by category
+
+
+
+
+
+
+
Mobile phones
+
{phonesCount} models
+
+
+
+
+
+
+
Tablets
+
{tabletsCount} models
+
+
+
+
+
+
+
Accessories
+
+ {accessoriesCount} models
+
+
+
+
+
+
+
+
+ );
+};
diff --git a/src/modules/HomePage/index.ts b/src/modules/HomePage/index.ts
new file mode 100644
index 00000000000..0799f479a25
--- /dev/null
+++ b/src/modules/HomePage/index.ts
@@ -0,0 +1 @@
+export { HomePage } from './HomePage';
diff --git a/src/modules/NotFoundPage/NotFoundPage.module.scss b/src/modules/NotFoundPage/NotFoundPage.module.scss
new file mode 100644
index 00000000000..1a4c25af43e
--- /dev/null
+++ b/src/modules/NotFoundPage/NotFoundPage.module.scss
@@ -0,0 +1,41 @@
+@use '../../styles/variables' as *;
+
+.notFound {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ gap: 24px;
+ padding: 40px 16px;
+ min-height: 50vh;
+
+ &__title {
+ font-size: 32px;
+ font-weight: 700;
+ line-height: 41px;
+ color: $color-primary;
+
+ @include on-tablet {
+ font-size: 48px;
+ line-height: 56px;
+ }
+ }
+
+ &__image {
+ max-width: 300px;
+ width: 100%;
+ }
+
+ &__link {
+ font-size: 14px;
+ font-weight: 600;
+ color: $color-accent;
+ border-bottom: 1px solid $color-accent;
+ transition: color 0.3s;
+
+ &:hover {
+ color: $color-primary;
+ border-color: $color-primary;
+ }
+ }
+}
diff --git a/src/modules/NotFoundPage/NotFoundPage.tsx b/src/modules/NotFoundPage/NotFoundPage.tsx
new file mode 100644
index 00000000000..be6a9f9cb54
--- /dev/null
+++ b/src/modules/NotFoundPage/NotFoundPage.tsx
@@ -0,0 +1,16 @@
+import { Link } from 'react-router-dom';
+import styles from './NotFoundPage.module.scss';
+
+export const NotFoundPage = () => (
+
+
Page not found
+
+
+ Go to Home page
+
+
+);
diff --git a/src/modules/NotFoundPage/index.ts b/src/modules/NotFoundPage/index.ts
new file mode 100644
index 00000000000..642c600088e
--- /dev/null
+++ b/src/modules/NotFoundPage/index.ts
@@ -0,0 +1 @@
+export { NotFoundPage } from './NotFoundPage';
diff --git a/src/modules/PhonesPage/PhonesPage.tsx b/src/modules/PhonesPage/PhonesPage.tsx
new file mode 100644
index 00000000000..8cb5cba3598
--- /dev/null
+++ b/src/modules/PhonesPage/PhonesPage.tsx
@@ -0,0 +1,5 @@
+import { ProductsPage } from '../ProductsPage';
+
+export const PhonesPage = () => (
+
+);
diff --git a/src/modules/PhonesPage/index.ts b/src/modules/PhonesPage/index.ts
new file mode 100644
index 00000000000..6054067fc66
--- /dev/null
+++ b/src/modules/PhonesPage/index.ts
@@ -0,0 +1 @@
+export { PhonesPage } from './PhonesPage';
diff --git a/src/modules/ProductDetailsPage/ProductDetailsPage.module.scss b/src/modules/ProductDetailsPage/ProductDetailsPage.module.scss
new file mode 100644
index 00000000000..5b23822da5f
--- /dev/null
+++ b/src/modules/ProductDetailsPage/ProductDetailsPage.module.scss
@@ -0,0 +1,398 @@
+@use '../../styles/variables' as *;
+
+.details {
+ &__title {
+ font-size: 22px;
+ font-weight: 700;
+ line-height: 31px;
+ color: $color-primary;
+ margin-bottom: 32px;
+
+ @include on-tablet {
+ font-size: 32px;
+ line-height: 41px;
+ letter-spacing: -0.01em;
+ margin-bottom: 40px;
+ }
+ }
+
+ // ---------- Main (gallery + controls) ----------
+
+ &__main {
+ display: flex;
+ flex-direction: column;
+ gap: 40px;
+ margin-bottom: 56px;
+
+ @include on-tablet {
+ flex-direction: row;
+ gap: 64px;
+ margin-bottom: 64px;
+ }
+ }
+
+ // Gallery
+ &__gallery {
+ display: flex;
+ flex-direction: column-reverse;
+ gap: 16px;
+
+ @include on-tablet {
+ flex-direction: row;
+ flex: 1;
+ }
+
+ @include on-desktop {
+ gap: 16px;
+ }
+ }
+
+ &__mainImage {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 100%;
+ aspect-ratio: 1;
+ overflow: hidden;
+
+ @include on-desktop {
+ width: 464px;
+ height: 464px;
+ }
+ }
+
+ &__mainImg {
+ max-width: 100%;
+ max-height: 100%;
+ object-fit: contain;
+ }
+
+ &__thumbs {
+ display: flex;
+ gap: 8px;
+
+ @include on-tablet {
+ flex-direction: column;
+ }
+ }
+
+ &__thumb {
+ width: 52px;
+ height: 52px;
+ padding: 4px;
+ border: 1px solid $color-elements;
+ background: $color-surface;
+ cursor: pointer;
+ transition: border-color 0.3s;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+
+ @include on-desktop {
+ width: 80px;
+ height: 80px;
+ padding: 8px;
+ }
+
+ &:hover {
+ border-color: $color-secondary;
+ }
+
+ &--active {
+ border-color: $color-primary;
+ }
+
+ img {
+ max-width: 100%;
+ max-height: 100%;
+ object-fit: contain;
+ }
+ }
+
+ // Controls
+ &__controls {
+ width: 100%;
+
+ @include on-tablet {
+ width: 320px;
+ flex-shrink: 0;
+ }
+ }
+
+ &__section {
+ margin-bottom: 24px;
+ }
+
+ &__sectionLabel {
+ font-size: 12px;
+ font-weight: 600;
+ line-height: 15px;
+ color: $color-secondary;
+ margin-bottom: 8px;
+ }
+
+ &__divider {
+ width: 100%;
+ height: 1px;
+ background-color: $color-elements;
+ margin-bottom: 24px;
+ }
+
+ // Colors
+ &__colors {
+ display: flex;
+ gap: 8px;
+ }
+
+ &__colorCircle {
+ width: 32px;
+ height: 32px;
+ border-radius: 50%;
+ border: 2px solid $color-elements;
+ cursor: pointer;
+ transition: border-color 0.3s;
+ outline: 2px solid transparent;
+ outline-offset: 2px;
+
+ &:hover {
+ outline-color: $color-icons;
+ }
+
+ &--active {
+ outline-color: $color-primary;
+ }
+ }
+
+ // Capacity
+ &__capacities {
+ display: flex;
+ gap: 8px;
+ }
+
+ &__capButton {
+ padding: 7px 8px;
+ font-family: $font-family;
+ font-size: 14px;
+ font-weight: 600;
+ line-height: 21px;
+ color: $color-primary;
+ border: 1px solid $color-icons;
+ background-color: transparent;
+ cursor: pointer;
+ text-align: center;
+ transition:
+ background-color 0.3s,
+ color 0.3s,
+ border-color 0.3s;
+
+ &:hover {
+ border-color: $color-primary;
+ }
+
+ &--active {
+ color: $color-button-text;
+ background-color: $color-button;
+ border-color: $color-button;
+ cursor: default;
+ }
+ }
+
+ // Price
+ &__priceRow {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ margin-bottom: 16px;
+ }
+
+ &__price {
+ font-size: 32px;
+ font-weight: 700;
+ line-height: 41px;
+ letter-spacing: -0.01em;
+ color: $color-primary;
+ }
+
+ &__fullPrice {
+ font-size: 22px;
+ font-weight: 600;
+ line-height: 28px;
+ color: $color-secondary;
+ text-decoration: line-through;
+ }
+
+ // Action buttons
+ &__actions {
+ display: flex;
+ gap: 8px;
+ margin-bottom: 32px;
+ }
+
+ &__addToCart {
+ flex: 1;
+ height: 48px;
+ font-family: $font-family;
+ font-size: 14px;
+ font-weight: 600;
+ line-height: 21px;
+ color: $color-button-text;
+ background-color: $color-button;
+ border: none;
+ cursor: pointer;
+ transition:
+ background-color 0.3s,
+ box-shadow 0.3s;
+
+ &:hover {
+ box-shadow: 0 3px 13px $color-button-shadow;
+ }
+
+ &--active {
+ color: $color-green;
+ background-color: $color-hover-and-bg;
+ border: 1px solid $color-elements;
+
+ &:hover {
+ box-shadow: none;
+ border-color: $color-primary;
+ }
+ }
+ }
+
+ &__favButton {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 48px;
+ height: 48px;
+ border: 1px solid $color-icons;
+ background: $color-hover-and-bg;
+ cursor: pointer;
+ transition: border-color 0.3s;
+
+ &:hover {
+ border-color: $color-primary;
+ }
+
+ &--active {
+ border-color: $color-elements;
+ }
+
+ img {
+ width: 16px;
+ height: 16px;
+ }
+ }
+
+ // Short specs
+ &__shortSpecs {
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+ }
+
+ &__specRow {
+ display: flex;
+ justify-content: space-between;
+ }
+
+ &__specLabel {
+ font-size: 12px;
+ font-weight: 600;
+ line-height: 15px;
+ color: $color-secondary;
+ }
+
+ &__specValue {
+ font-size: 12px;
+ font-weight: 700;
+ line-height: 15px;
+ color: $color-primary;
+ text-align: right;
+ }
+
+ // ---------- Info (About + Tech specs) ----------
+
+ &__info {
+ display: flex;
+ flex-direction: column;
+ gap: 56px;
+ margin-bottom: 56px;
+
+ @include on-desktop {
+ flex-direction: row;
+ gap: 64px;
+ margin-bottom: 80px;
+ }
+ }
+
+ &__about {
+ flex: 1;
+ }
+
+ &__techSpecs {
+ @include on-desktop {
+ width: 512px;
+ flex-shrink: 0;
+ }
+ }
+
+ &__infoTitle {
+ font-size: 22px;
+ font-weight: 700;
+ line-height: 31px;
+ color: $color-primary;
+ margin-bottom: 16px;
+ }
+
+ &__infoDivider {
+ width: 100%;
+ height: 1px;
+ background-color: $color-elements;
+ margin-bottom: 32px;
+ }
+
+ &__aboutSection {
+ margin-bottom: 32px;
+
+ &:last-child {
+ margin-bottom: 0;
+ }
+ }
+
+ &__aboutSubtitle {
+ font-size: 16px;
+ font-weight: 600;
+ line-height: 20px;
+ color: $color-primary;
+ margin-bottom: 16px;
+ }
+
+ &__aboutText {
+ font-size: 14px;
+ font-weight: 400;
+ line-height: 21px;
+ color: $color-secondary;
+ margin-bottom: 16px;
+
+ &:last-child {
+ margin-bottom: 0;
+ }
+ }
+
+ &__techList {
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+ }
+
+ // ---------- Suggested ----------
+
+ &__suggested {
+ margin-bottom: 56px;
+
+ @include on-desktop {
+ margin-bottom: 80px;
+ }
+ }
+}
diff --git a/src/modules/ProductDetailsPage/ProductDetailsPage.tsx b/src/modules/ProductDetailsPage/ProductDetailsPage.tsx
new file mode 100644
index 00000000000..b3e6561e367
--- /dev/null
+++ b/src/modules/ProductDetailsPage/ProductDetailsPage.tsx
@@ -0,0 +1,346 @@
+import { useEffect, useState } from 'react';
+import { useParams, Link } from 'react-router-dom';
+import classNames from 'classnames';
+import { Breadcrumbs } from '../../components/Breadcrumbs';
+import { BackButton } from '../../components/BackButton';
+import { ProductsSlider } from '../../components/ProductsSlider';
+import { Loader } from '../../components/Loader';
+import { useCart } from '../../context/CartContext';
+import { useFavorites } from '../../context/FavoritesContext';
+import { ProductDetails } from '../../types/ProductDetails';
+import { Product } from '../../types/Product';
+import {
+ getProductDetails,
+ getProducts,
+ getSuggestedProducts,
+} from '../../utils/api';
+import styles from './ProductDetailsPage.module.scss';
+
+const CATEGORY_TITLES: Record = {
+ phones: 'Phones',
+ tablets: 'Tablets',
+ accessories: 'Accessories',
+};
+
+const COLOR_HEX: Record = {
+ black: '#1F2020',
+ white: '#F9F6EF',
+ red: '#BA0C2E',
+ blue: '#215E7C',
+ green: '#ADE1CD',
+ yellow: '#FFE681',
+ purple: '#D1CDDA',
+ pink: '#FAE0D8',
+ orange: '#F0D4B0',
+ gold: '#FCDBC1',
+ silver: '#F5F5F0',
+ coral: '#EE7762',
+ midnight: '#171E27',
+ starlight: '#FAF6F2',
+ rosegold: '#E6C7C2',
+ 'rose gold': '#E6C7C2',
+ graphite: '#41424C',
+ sierrablue: '#69ABCE',
+ spaceblack: '#403E3D',
+ spacegray: '#535150',
+ 'space gray': '#535150',
+ 'space black': '#403E3D',
+ midnightgreen: '#4E5851',
+ 'sky blue': '#276787',
+};
+
+export const ProductDetailsPage = () => {
+ const { productId = '' } = useParams();
+ const [details, setDetails] = useState(null);
+ const [product, setProduct] = useState(null);
+ const [suggested, setSuggested] = useState([]);
+ const [isLoading, setIsLoading] = useState(true);
+ const [selectedImage, setSelectedImage] = useState(0);
+ const { addToCart, isInCart } = useCart();
+ const { toggleFavorite, isFavorite } = useFavorites();
+
+ useEffect(() => {
+ setIsLoading(true);
+ setSelectedImage(0);
+
+ Promise.all([
+ getProductDetails(productId),
+ getProducts(),
+ getSuggestedProducts(),
+ ])
+ .then(([det, allProducts, sug]) => {
+ setDetails(det);
+
+ const found = allProducts.find(p => p.itemId === productId) || null;
+
+ setProduct(found);
+ setSuggested(sug.slice(0, 12));
+ })
+ .finally(() => setIsLoading(false));
+ }, [productId]);
+
+ if (isLoading) {
+ return (
+
+
+
+ );
+ }
+
+ if (!details || !product) {
+ return (
+
+
Product was not found
+
+ );
+ }
+
+ const {
+ name,
+ images,
+ colorsAvailable,
+ color,
+ capacityAvailable,
+ capacity,
+ priceRegular,
+ priceDiscount,
+ screen,
+ resolution,
+ processor,
+ ram,
+ description,
+ camera,
+ zoom,
+ cell,
+ namespaceId,
+ category,
+ } = details;
+
+ const inCart = isInCart(product.id);
+ const favorited = isFavorite(product.id);
+
+ const buildLink = (newColor?: string, newCapacity?: string) => {
+ const c = (newColor || color).toLowerCase().replace(/\s+/g, '-');
+ const cap = (newCapacity || capacity).toLowerCase().replace(/\s+/g, '-');
+
+ return `/product/${namespaceId}-${cap}-${c}`;
+ };
+
+ const categoryTitle = CATEGORY_TITLES[category] || category;
+
+ return (
+
+
+
+
+
+
{name}
+
+
+ {/* ---- Image gallery ---- */}
+
+
+
+
+
+
+ {images.map((img, i) => (
+
setSelectedImage(i)}
+ >
+
+
+ ))}
+
+
+
+ {/* ---- Controls ---- */}
+
+ {/* Colors */}
+
+
Available colors
+
+ {colorsAvailable.map(c => (
+
+ ))}
+
+
+
+
+
+ {/* Capacity */}
+
+
Select capacity
+
+ {capacityAvailable.map(cap => (
+
+ {cap}
+
+ ))}
+
+
+
+
+
+ {/* Price */}
+
+ ${priceDiscount}
+ {priceRegular > priceDiscount && (
+ ${priceRegular}
+ )}
+
+
+ {/* Action buttons */}
+
+
addToCart(product)}
+ >
+ {inCart ? 'Added to cart' : 'Add to cart'}
+
+
+
toggleFavorite(product)}
+ aria-label="Toggle favourites"
+ >
+
+
+
+
+ {/* Short specs */}
+
+
+ Screen
+ {screen}
+
+
+ Resolution
+ {resolution}
+
+
+ Processor
+ {processor}
+
+
+ RAM
+ {ram}
+
+
+
+
+
+ {/* ---- About + Tech specs ---- */}
+
+
+
About
+
+
+ {description.map(section => (
+
+
{section.title}
+ {section.text.map(paragraph => (
+
+ {paragraph}
+
+ ))}
+
+ ))}
+
+
+
+
Tech specs
+
+
+
+
+ Screen
+ {screen}
+
+
+ Resolution
+ {resolution}
+
+
+ Processor
+ {processor}
+
+
+ RAM
+ {ram}
+
+
+ Built in memory
+ {capacity}
+
+ {camera && (
+
+ Camera
+ {camera}
+
+ )}
+ {zoom && (
+
+ Zoom
+ {zoom}
+
+ )}
+
+ Cell
+
+ {cell.join(', ')}
+
+
+
+
+
+
+ {/* ---- You may also like ---- */}
+
+
+ );
+};
diff --git a/src/modules/ProductDetailsPage/index.ts b/src/modules/ProductDetailsPage/index.ts
new file mode 100644
index 00000000000..ec50c119343
--- /dev/null
+++ b/src/modules/ProductDetailsPage/index.ts
@@ -0,0 +1 @@
+export { ProductDetailsPage } from './ProductDetailsPage';
diff --git a/src/modules/ProductsPage/ProductsPage.module.scss b/src/modules/ProductsPage/ProductsPage.module.scss
new file mode 100644
index 00000000000..aa3bbc29c6a
--- /dev/null
+++ b/src/modules/ProductsPage/ProductsPage.module.scss
@@ -0,0 +1,62 @@
+@use '../../styles/variables' as *;
+
+.productsPage {
+ &__filters {
+ display: flex;
+ gap: 16px;
+ margin-bottom: 24px;
+ }
+
+ &__grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(212px, 272px));
+ gap: 16px;
+ justify-content: center;
+
+ @include on-tablet {
+ grid-template-columns: repeat(3, 1fr);
+ justify-items: center;
+ }
+
+ @include on-desktop {
+ grid-template-columns: repeat(4, 1fr);
+ justify-items: center;
+ }
+ }
+
+ &__error {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 16px;
+ padding: 40px;
+
+ p {
+ font-size: 16px;
+ color: $color-secondary;
+ }
+ }
+
+ &__reload {
+ padding: 8px 24px;
+ font-family: $font-family;
+ font-size: 14px;
+ font-weight: 600;
+ color: $color-button-text;
+ background-color: $color-button;
+ border: none;
+ cursor: pointer;
+ transition: box-shadow 0.3s;
+
+ &:hover {
+ box-shadow: 0 3px 13px $color-button-shadow;
+ }
+ }
+
+ &__empty {
+ padding: 40px;
+ text-align: center;
+ font-size: 16px;
+ color: $color-secondary;
+ }
+}
diff --git a/src/modules/ProductsPage/ProductsPage.tsx b/src/modules/ProductsPage/ProductsPage.tsx
new file mode 100644
index 00000000000..18c933277b6
--- /dev/null
+++ b/src/modules/ProductsPage/ProductsPage.tsx
@@ -0,0 +1,161 @@
+import { useEffect, useState, useMemo } from 'react';
+import { useSearchParams } from 'react-router-dom';
+import { Breadcrumbs } from '../../components/Breadcrumbs';
+import { Dropdown } from '../../components/Dropdown';
+import { Pagination } from '../../components/Pagination';
+import { ProductCard } from '../../components/ProductCard';
+import { Loader } from '../../components/Loader';
+import { Product } from '../../types/Product';
+import { getProducts } from '../../utils/api';
+import styles from './ProductsPage.module.scss';
+
+const SORT_OPTIONS = [
+ { value: 'age', label: 'Newest' },
+ { value: 'name', label: 'Alphabetically' },
+ { value: 'price', label: 'Cheapest' },
+];
+
+const PER_PAGE_OPTIONS = [
+ { value: '4', label: '4' },
+ { value: '8', label: '8' },
+ { value: '16', label: '16' },
+ { value: 'all', label: 'All' },
+];
+
+type Props = {
+ category: string;
+ title: string;
+};
+
+function sortProducts(products: Product[], sortBy: string): Product[] {
+ const sorted = [...products];
+
+ switch (sortBy) {
+ case 'age':
+ return sorted.sort((a, b) => b.year - a.year);
+ case 'name':
+ return sorted.sort((a, b) => a.name.localeCompare(b.name));
+ case 'price':
+ return sorted.sort((a, b) => a.price - b.price);
+ default:
+ return sorted;
+ }
+}
+
+export const ProductsPage: React.FC = ({ category, title }) => {
+ const [products, setProducts] = useState([]);
+ const [isLoading, setIsLoading] = useState(true);
+ const [isError, setIsError] = useState(false);
+ const [searchParams, setSearchParams] = useSearchParams();
+
+ const sort = searchParams.get('sort') || 'age';
+ const perPage = searchParams.get('perPage') || '16';
+ const page = +(searchParams.get('page') || '1');
+ const query = searchParams.get('query') || '';
+
+ useEffect(() => {
+ setIsLoading(true);
+ setIsError(false);
+
+ getProducts()
+ .then(all => {
+ setProducts(all.filter(p => p.category === category));
+ })
+ .catch(() => setIsError(true))
+ .finally(() => setIsLoading(false));
+ }, [category]);
+
+ const filtered = useMemo(() => {
+ if (!query) {
+ return products;
+ }
+
+ const q = query.toLowerCase().trim();
+
+ return products.filter(p => p.name.toLowerCase().includes(q));
+ }, [products, query]);
+
+ const sorted = useMemo(() => sortProducts(filtered, sort), [filtered, sort]);
+
+ const itemsPerPage = perPage === 'all' ? sorted.length : +perPage;
+ const start = (page - 1) * itemsPerPage;
+ const visible = sorted.slice(start, start + itemsPerPage);
+
+ const updateParams = (key: string, value: string) => {
+ const params = new URLSearchParams(searchParams);
+
+ params.set(key, value);
+
+ if (key !== 'page') {
+ params.set('page', '1');
+ }
+
+ setSearchParams(params);
+ };
+
+ return (
+
+
+
+
{title}
+
{filtered.length} models
+
+ {isLoading &&
}
+
+ {isError && !isLoading && (
+
+
Something went wrong. Please try again.
+
window.location.reload()}
+ >
+ Reload
+
+
+ )}
+
+ {!isLoading && !isError && filtered.length === 0 && (
+
+ {query
+ ? `No search results for "${query}"`
+ : `There are no ${category} yet`}
+
+ )}
+
+ {!isLoading && !isError && filtered.length > 0 && (
+ <>
+
+ updateParams('sort', v)}
+ />
+ updateParams('perPage', v)}
+ />
+
+
+
+ {visible.map(product => (
+
+ ))}
+
+
+ {perPage !== 'all' && (
+
updateParams('page', String(p))}
+ />
+ )}
+ >
+ )}
+
+ );
+};
diff --git a/src/modules/ProductsPage/index.ts b/src/modules/ProductsPage/index.ts
new file mode 100644
index 00000000000..0569c38ebe0
--- /dev/null
+++ b/src/modules/ProductsPage/index.ts
@@ -0,0 +1 @@
+export { ProductsPage } from './ProductsPage';
diff --git a/src/modules/TabletsPage/TabletsPage.tsx b/src/modules/TabletsPage/TabletsPage.tsx
new file mode 100644
index 00000000000..5b949a29507
--- /dev/null
+++ b/src/modules/TabletsPage/TabletsPage.tsx
@@ -0,0 +1,5 @@
+import { ProductsPage } from '../ProductsPage';
+
+export const TabletsPage = () => (
+
+);
diff --git a/src/modules/TabletsPage/index.ts b/src/modules/TabletsPage/index.ts
new file mode 100644
index 00000000000..5f5d7eb9d62
--- /dev/null
+++ b/src/modules/TabletsPage/index.ts
@@ -0,0 +1 @@
+export { TabletsPage } from './TabletsPage';
diff --git a/src/styles/_base.scss b/src/styles/_base.scss
new file mode 100644
index 00000000000..f39a3fc5abf
--- /dev/null
+++ b/src/styles/_base.scss
@@ -0,0 +1,123 @@
+@use 'variables' as *;
+
+// ========================
+// Theme CSS Custom Properties
+// ========================
+:root {
+ --color-primary: #313237;
+ --color-secondary: #89939a;
+ --color-icons: #b4bdc3;
+ --color-elements: #e2e6e9;
+ --color-hover-and-bg: #fafbfc;
+ --color-white: #fff;
+ --color-green: #27ae60;
+ --color-red: #eb5757;
+ --color-accent: #4219d0;
+ --color-surface: #fff;
+ --color-button: #313237;
+ --color-button-text: #fff;
+ --color-button-shadow: rgba(23, 32, 49, 0.4);
+ --color-focus-border: #313237;
+ --fill-0: #313237;
+ --icon-invert: 0;
+}
+
+[data-theme='dark'] {
+ --color-primary: #f1f2f9;
+ --color-secondary: #75767f;
+ --color-icons: #4a4d58;
+ --color-elements: #3b3e4a;
+ --color-hover-and-bg: #323542;
+ --color-white: #0f1121;
+ --color-green: #27ae60;
+ --color-red: #eb5757;
+ --color-accent: #905bff;
+ --color-surface: #161827;
+ --color-button: #905bff;
+ --color-button-text: #fff;
+ --color-button-shadow: rgba(144, 91, 255, 0.4);
+ --color-focus-border: #905bff;
+ --fill-0: #f1f2f9;
+ --icon-invert: 1;
+}
+
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+ margin: 0;
+ padding: 0;
+}
+
+html {
+ scroll-behavior: smooth;
+}
+
+body {
+ font-family: $font-family;
+ font-size: 14px;
+ line-height: 21px;
+ font-weight: 600;
+ color: var(--color-primary);
+ background-color: var(--color-white);
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ transition:
+ background-color 0.3s ease,
+ color 0.3s ease;
+}
+
+a {
+ text-decoration: none;
+ color: inherit;
+}
+
+ul {
+ list-style: none;
+}
+
+button {
+ border: none;
+ background: none;
+ cursor: pointer;
+ font-family: inherit;
+}
+
+img {
+ display: block;
+ max-width: 100%;
+}
+
+// Dark mode SVG icon inversion (after img to satisfy specificity order)
+[data-theme='dark'] img[src$='.svg']:not([data-no-invert]) {
+ filter: invert(1) brightness(2);
+ transition: filter 0.3s;
+}
+
+[data-theme='dark'] img:not([src$='.svg']) {
+ filter: none;
+}
+
+input,
+select {
+ font-family: inherit;
+}
+
+// Utility classes
+.container {
+ max-width: $content-max-width;
+ margin: 0 auto;
+
+ @include content-padding-inline;
+}
+
+.visually-hidden {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ margin: -1px;
+ padding: 0;
+ overflow: hidden;
+ clip: rect(0, 0, 0, 0);
+ border: 0;
+}
diff --git a/src/styles/_variables.scss b/src/styles/_variables.scss
new file mode 100644
index 00000000000..684f05ec727
--- /dev/null
+++ b/src/styles/_variables.scss
@@ -0,0 +1,81 @@
+@font-face {
+ font-family: Mont;
+ src: url('/fonts/Mont-Regular.otf') format('opentype');
+ font-weight: 400;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: Mont;
+ src: url('/fonts/Mont-SemiBold.otf') format('opentype');
+ font-weight: 600;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: Mont;
+ src: url('/fonts/Mont-Bold.otf') format('opentype');
+ font-weight: 700;
+ font-style: normal;
+ font-display: swap;
+}
+
+// ========================
+// Design tokens (Figma Original)
+// ========================
+// Original static values (for SCSS functions that can't use var())
+$color-primary-static: #313237;
+
+// Themed colors — reference CSS custom properties defined in _base.scss
+$color-primary: var(--color-primary);
+$color-secondary: var(--color-secondary);
+$color-icons: var(--color-icons);
+$color-elements: var(--color-elements);
+$color-hover-and-bg: var(--color-hover-and-bg);
+$color-white: var(--color-white);
+$color-green: var(--color-green);
+$color-red: var(--color-red);
+$color-accent: var(--color-accent);
+$color-surface: var(--color-surface);
+$color-button: var(--color-button);
+$color-button-text: var(--color-button-text);
+$color-button-shadow: var(--color-button-shadow);
+
+// Typography
+$font-family: Mont, Arial, sans-serif;
+
+// Breakpoints
+$tablet: 640px;
+$desktop: 1200px;
+
+// Grid
+$content-max-width: 1136px;
+
+// ========================
+// Mixins
+// ========================
+@mixin on-tablet {
+ @media (min-width: $tablet) {
+ @content;
+ }
+}
+
+@mixin on-desktop {
+ @media (min-width: $desktop) {
+ @content;
+ }
+}
+
+@mixin content-padding-inline {
+ padding-inline: 16px;
+
+ @include on-tablet {
+ padding-inline: 24px;
+ }
+
+ @include on-desktop {
+ padding-inline: 48px;
+ }
+}
diff --git a/src/types/CartItem.ts b/src/types/CartItem.ts
new file mode 100644
index 00000000000..d58f0dc05d9
--- /dev/null
+++ b/src/types/CartItem.ts
@@ -0,0 +1,7 @@
+import { Product } from './Product';
+
+export interface CartItem {
+ id: number;
+ quantity: number;
+ product: Product;
+}
diff --git a/src/types/Product.ts b/src/types/Product.ts
new file mode 100644
index 00000000000..052d1dceead
--- /dev/null
+++ b/src/types/Product.ts
@@ -0,0 +1,14 @@
+export interface Product {
+ id: number;
+ category: string;
+ itemId: string;
+ name: string;
+ fullPrice: number;
+ price: number;
+ screen: string;
+ capacity: string;
+ color: string;
+ ram: string;
+ year: number;
+ image: string;
+}
diff --git a/src/types/ProductDetails.ts b/src/types/ProductDetails.ts
new file mode 100644
index 00000000000..17096538c59
--- /dev/null
+++ b/src/types/ProductDetails.ts
@@ -0,0 +1,26 @@
+export interface Description {
+ title: string;
+ text: string[];
+}
+
+export interface ProductDetails {
+ id: string;
+ category: string;
+ namespaceId: string;
+ name: string;
+ capacityAvailable: string[];
+ capacity: string;
+ priceRegular: number;
+ priceDiscount: number;
+ colorsAvailable: string[];
+ color: string;
+ images: string[];
+ description: Description[];
+ screen: string;
+ resolution: string;
+ processor: string;
+ ram: string;
+ camera?: string;
+ zoom?: string;
+ cell: string[];
+}
diff --git a/src/utils/api.ts b/src/utils/api.ts
new file mode 100644
index 00000000000..90c5dd8ebbc
--- /dev/null
+++ b/src/utils/api.ts
@@ -0,0 +1,55 @@
+// This is a helper to simulate a delay for loading states
+const BASE_URL = '';
+
+function wait(delay: number): Promise {
+ return new Promise(resolve => {
+ setTimeout(resolve, delay);
+ });
+}
+
+async function request(url: string): Promise {
+ await wait(300);
+
+ const response = await fetch(BASE_URL + url);
+
+ if (!response.ok) {
+ throw new Error(`${response.status} ${response.statusText}`);
+ }
+
+ return response.json();
+}
+
+export const getProducts = () =>
+ request('api/products.json');
+export const getPhones = () =>
+ request(
+ 'api/phones.json',
+ );
+export const getTablets = () =>
+ request(
+ 'api/tablets.json',
+ );
+export const getAccessories = () =>
+ request(
+ 'api/accessories.json',
+ );
+
+export const getProductDetails = async (
+ productId: string,
+): Promise => {
+ const [phones, tablets, accessories] = await Promise.all([
+ getPhones(),
+ getTablets(),
+ getAccessories(),
+ ]);
+
+ const allDetails = [...phones, ...tablets, ...accessories];
+
+ return allDetails.find(item => item.id === productId) || null;
+};
+
+export const getSuggestedProducts = async () => {
+ const products = await getProducts();
+
+ return [...products].sort(() => Math.random() - 0.5);
+};