# نمونه کدهای فرانت‌اند

## React Components

### 1. HomeFeatures Component

```jsx
import React, { useEffect, useState } from 'react';
import * as Icons from 'lucide-react';

const HomeFeatures = () => {
  const [features, setFeatures] = useState([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetch('/api/home-features')
      .then(res => res.json())
      .then(data => {
        setFeatures(data.data);
        setLoading(false);
      });
  }, []);

  if (loading) return <div>در حال بارگذاری...</div>;

  return (
    <div className="container mx-auto py-12">
      <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
        {features.map((feature) => {
          // دریافت آیکون به صورت داینامیک
          const IconComponent = Icons[feature.icon] || Icons.Box;
          
          return (
            <div
              key={feature.id}
              className="p-6 rounded-lg text-center transition-transform hover:scale-105"
              style={{
                backgroundColor: feature.bg_color,
                color: feature.text_color,
              }}
            >
              <IconComponent
                size={48}
                style={{ color: feature.icon_color }}
                className="mx-auto mb-4"
              />
              <h3 className="text-lg font-bold mb-2">{feature.title}</h3>
              <p className="text-sm opacity-90">{feature.description}</p>
            </div>
          );
        })}
      </div>
    </div>
  );
};

export default HomeFeatures;
```

### 2. ProductShowcases Component

```jsx
import React, { useEffect, useState } from 'react';
import { Swiper, SwiperSlide } from 'swiper/react';
import { Navigation, Pagination } from 'swiper/modules';
import 'swiper/css';
import 'swiper/css/navigation';
import 'swiper/css/pagination';

const ProductCard = ({ product }) => (
  <div className="border rounded-lg overflow-hidden hover:shadow-lg transition-shadow">
    <img
      src={product.primary_image?.url || '/placeholder.jpg'}
      alt={product.name}
      className="w-full h-48 object-cover"
    />
    <div className="p-4">
      <h4 className="font-semibold mb-2 truncate">{product.name}</h4>
      <div className="flex items-center gap-2">
        {product.discount_price ? (
          <>
            <span className="text-red-600 font-bold">
              {Number(product.discount_price).toLocaleString()} تومان
            </span>
            <span className="text-gray-400 line-through text-sm">
              {Number(product.price).toLocaleString()}
            </span>
          </>
        ) : (
          <span className="font-bold">
            {Number(product.price).toLocaleString()} تومان
          </span>
        )}
      </div>
    </div>
  </div>
);

const ProductShowcases = () => {
  const [showcases, setShowcases] = useState([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetch('/api/product-showcases')
      .then(res => res.json())
      .then(data => {
        setShowcases(data.data);
        setLoading(false);
      });
  }, []);

  if (loading) return <div>در حال بارگذاری...</div>;

  return (
    <div className="space-y-12">
      {showcases.map((showcase) => (
        <section
          key={showcase.id}
          className="py-8"
          style={{ backgroundColor: showcase.bg_color }}
        >
          <div className="container mx-auto px-4">
            <div className="text-center mb-8">
              <h2
                className="text-3xl font-bold mb-2"
                style={{ color: showcase.title_color }}
              >
                {showcase.title}
              </h2>
              {showcase.subtitle && (
                <p className="text-gray-600">{showcase.subtitle}</p>
              )}
            </div>

            {/* نمایش شبکه‌ای */}
            {showcase.display_type === 'grid' && (
              <div className="grid grid-cols-1 md:grid-cols-3 lg:grid-cols-4 gap-6">
                {showcase.products.map((product) => (
                  <ProductCard key={product.id} product={product} />
                ))}
              </div>
            )}

            {/* نمایش اسلایدر */}
            {showcase.display_type === 'carousel' && (
              <Swiper
                modules={[Navigation, Pagination]}
                spaceBetween={20}
                slidesPerView={1}
                navigation
                pagination={{ clickable: true }}
                breakpoints={{
                  640: { slidesPerView: 2 },
                  768: { slidesPerView: 3 },
                  1024: { slidesPerView: 4 },
                }}
              >
                {showcase.products.map((product) => (
                  <SwiperSlide key={product.id}>
                    <ProductCard product={product} />
                  </SwiperSlide>
                ))}
              </Swiper>
            )}

            {/* نمایش لیستی */}
            {showcase.display_type === 'list' && (
              <div className="space-y-4">
                {showcase.products.map((product) => (
                  <div
                    key={product.id}
                    className="flex gap-4 border rounded-lg p-4 hover:shadow-md transition-shadow"
                  >
                    <img
                      src={product.primary_image?.url || '/placeholder.jpg'}
                      alt={product.name}
                      className="w-24 h-24 object-cover rounded"
                    />
                    <div className="flex-1">
                      <h4 className="font-semibold mb-2">{product.name}</h4>
                      <p className="text-sm text-gray-600 mb-2">
                        {product.category?.name}
                      </p>
                      <div className="flex items-center gap-2">
                        {product.discount_price ? (
                          <>
                            <span className="text-red-600 font-bold">
                              {Number(product.discount_price).toLocaleString()} تومان
                            </span>
                            <span className="text-gray-400 line-through text-sm">
                              {Number(product.price).toLocaleString()}
                            </span>
                          </>
                        ) : (
                          <span className="font-bold">
                            {Number(product.price).toLocaleString()} تومان
                          </span>
                        )}
                      </div>
                    </div>
                  </div>
                ))}
              </div>
            )}
          </div>
        </section>
      ))}
    </div>
  );
};

export default ProductShowcases;
```

### 3. صفحه اصلی کامل (HomePage)

```jsx
import React from 'react';
import Banners from './components/Banners';
import HomeFeatures from './components/HomeFeatures';
import ProductShowcases from './components/ProductShowcases';
import Categories from './components/Categories';

const HomePage = () => {
  return (
    <div className="min-h-screen bg-gray-50">
      {/* بنر اصلی */}
      <Banners />

      {/* ویژگی‌ها */}
      <HomeFeatures />

      {/* ویترین محصولات */}
      <ProductShowcases />

      {/* دسته‌بندی‌ها */}
      <Categories />
    </div>
  );
};

export default HomePage;
```

---

## Admin Panel Components

### 1. HomeFeatures Management

```jsx
import React, { useState, useEffect } from 'react';
import * as Icons from 'lucide-react';

const HomeFeaturesList = () => {
  const [features, setFeatures] = useState([]);
  const [editingFeature, setEditingFeature] = useState(null);
  const [showForm, setShowForm] = useState(false);

  useEffect(() => {
    loadFeatures();
  }, []);

  const loadFeatures = async () => {
    const res = await fetch('/api/admin/home-features', {
      headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` }
    });
    const data = await res.json();
    setFeatures(data.data);
  };

  const handleDelete = async (id) => {
    if (!confirm('آیا مطمئن هستید؟')) return;
    
    await fetch(`/api/admin/home-features/${id}`, {
      method: 'DELETE',
      headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` }
    });
    
    loadFeatures();
  };

  const handleSubmit = async (formData) => {
    const url = editingFeature
      ? `/api/admin/home-features/${editingFeature.id}`
      : '/api/admin/home-features';
    
    const method = editingFeature ? 'PUT' : 'POST';

    await fetch(url, {
      method,
      headers: {
        'Authorization': `Bearer ${localStorage.getItem('token')}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(formData)
    });

    setShowForm(false);
    setEditingFeature(null);
    loadFeatures();
  };

  return (
    <div className="p-6">
      <div className="flex justify-between items-center mb-6">
        <h2 className="text-2xl font-bold">مدیریت ویژگی‌های صفحه اصلی</h2>
        <button
          onClick={() => {
            setEditingFeature(null);
            setShowForm(true);
          }}
          className="bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700"
        >
          افزودن ویژگی جدید
        </button>
      </div>

      <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
        {features.map((feature) => {
          const IconComponent = Icons[feature.icon] || Icons.Box;
          
          return (
            <div
              key={feature.id}
              className="border rounded-lg overflow-hidden"
            >
              <div
                className="p-6 text-center"
                style={{
                  backgroundColor: feature.bg_color,
                  color: feature.text_color
                }}
              >
                <IconComponent
                  size={48}
                  style={{ color: feature.icon_color }}
                  className="mx-auto mb-4"
                />
                <h3 className="text-lg font-bold mb-2">{feature.title}</h3>
                <p className="text-sm opacity-90">{feature.description}</p>
              </div>
              
              <div className="p-4 bg-white border-t flex justify-between items-center">
                <span className={`text-sm ${feature.is_active ? 'text-green-600' : 'text-red-600'}`}>
                  {feature.is_active ? 'فعال' : 'غیرفعال'}
                </span>
                <div className="flex gap-2">
                  <button
                    onClick={() => {
                      setEditingFeature(feature);
                      setShowForm(true);
                    }}
                    className="text-blue-600 hover:text-blue-800"
                  >
                    ویرایش
                  </button>
                  <button
                    onClick={() => handleDelete(feature.id)}
                    className="text-red-600 hover:text-red-800"
                  >
                    حذف
                  </button>
                </div>
              </div>
            </div>
          );
        })}
      </div>

      {showForm && (
        <FeatureForm
          feature={editingFeature}
          onSubmit={handleSubmit}
          onCancel={() => {
            setShowForm(false);
            setEditingFeature(null);
          }}
        />
      )}
    </div>
  );
};

const FeatureForm = ({ feature, onSubmit, onCancel }) => {
  const [formData, setFormData] = useState(feature || {
    title: '',
    description: '',
    icon: 'Box',
    bg_color: '#F5F5F5',
    icon_color: '#1976D2',
    text_color: '#212121',
    sort_order: 0,
    is_active: true
  });

  const iconOptions = [
    'Truck', 'Headphones', 'ShieldCheck', 'CreditCard',
    'Gift', 'Award', 'Zap', 'Heart', 'Star', 'Package',
    'Phone', 'MessageCircle', 'Lock', 'RefreshCw'
  ];

  return (
    <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center p-4">
      <div className="bg-white rounded-lg p-6 max-w-2xl w-full max-h-[90vh] overflow-y-auto">
        <h3 className="text-xl font-bold mb-4">
          {feature ? 'ویرایش ویژگی' : 'افزودن ویژگی جدید'}
        </h3>

        <div className="space-y-4">
          <div>
            <label className="block mb-2">عنوان</label>
            <input
              type="text"
              value={formData.title}
              onChange={(e) => setFormData({ ...formData, title: e.target.value })}
              className="w-full border rounded px-3 py-2"
            />
          </div>

          <div>
            <label className="block mb-2">توضیحات</label>
            <textarea
              value={formData.description}
              onChange={(e) => setFormData({ ...formData, description: e.target.value })}
              className="w-full border rounded px-3 py-2"
              rows="3"
            />
          </div>

          <div>
            <label className="block mb-2">آیکون</label>
            <select
              value={formData.icon}
              onChange={(e) => setFormData({ ...formData, icon: e.target.value })}
              className="w-full border rounded px-3 py-2"
            >
              {iconOptions.map(icon => (
                <option key={icon} value={icon}>{icon}</option>
              ))}
            </select>
          </div>

          <div className="grid grid-cols-3 gap-4">
            <div>
              <label className="block mb-2">رنگ پس‌زمینه</label>
              <input
                type="color"
                value={formData.bg_color}
                onChange={(e) => setFormData({ ...formData, bg_color: e.target.value })}
                className="w-full h-10 border rounded"
              />
            </div>

            <div>
              <label className="block mb-2">رنگ آیکون</label>
              <input
                type="color"
                value={formData.icon_color}
                onChange={(e) => setFormData({ ...formData, icon_color: e.target.value })}
                className="w-full h-10 border rounded"
              />
            </div>

            <div>
              <label className="block mb-2">رنگ متن</label>
              <input
                type="color"
                value={formData.text_color}
                onChange={(e) => setFormData({ ...formData, text_color: e.target.value })}
                className="w-full h-10 border rounded"
              />
            </div>
          </div>

          <div className="flex items-center">
            <input
              type="checkbox"
              checked={formData.is_active}
              onChange={(e) => setFormData({ ...formData, is_active: e.target.checked })}
              className="mr-2"
            />
            <label>فعال</label>
          </div>
        </div>

        <div className="flex gap-2 mt-6">
          <button
            onClick={() => onSubmit(formData)}
            className="bg-blue-600 text-white px-6 py-2 rounded hover:bg-blue-700"
          >
            ذخیره
          </button>
          <button
            onClick={onCancel}
            className="bg-gray-300 text-gray-700 px-6 py-2 rounded hover:bg-gray-400"
          >
            انصراف
          </button>
        </div>
      </div>
    </div>
  );
};

export default HomeFeaturesList;
```

### 2. Auto Showcase Creator

```jsx
import React, { useState, useEffect } from 'react';
import * as Icons from 'lucide-react';

const AutoShowcaseCreator = () => {
  const [showcaseTypes, setShowcaseTypes] = useState([]);
  const [selectedType, setSelectedType] = useState(null);
  const [preview, setPreview] = useState(null);
  const [formData, setFormData] = useState({
    title: '',
    subtitle: '',
    display_type: 'grid',
    products_limit: 10,
    is_active: true
  });

  useEffect(() => {
    loadShowcaseTypes();
  }, []);

  const loadShowcaseTypes = async () => {
    const res = await fetch('/api/admin/auto-showcases/types', {
      headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` }
    });
    const data = await res.json();
    setShowcaseTypes(data.data);
  };

  const handlePreview = async (type) => {
    const res = await fetch('/api/admin/auto-showcases/preview', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${localStorage.getItem('token')}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ type, limit: formData.products_limit })
    });
    const data = await res.json();
    setPreview(data.data);
  };

  const handleCreate = async () => {
    await fetch('/api/admin/auto-showcases/create', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${localStorage.getItem('token')}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        type: selectedType.type,
        ...formData
      })
    });

    alert('ویترین با موفقیت ایجاد شد');
    setSelectedType(null);
    setPreview(null);
  };

  return (
    <div className="p-6">
      <h2 className="text-2xl font-bold mb-6">ساخت ویترین خودکار</h2>

      {!selectedType ? (
        <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
          {showcaseTypes.map((type) => {
            const IconComponent = Icons[type.icon] || Icons.Box;
            
            return (
              <div
                key={type.type}
                onClick={() => {
                  setSelectedType(type);
                  setFormData({ ...formData, title: type.title });
                  handlePreview(type.type);
                }}
                className="border rounded-lg p-6 cursor-pointer hover:shadow-lg transition-shadow"
              >
                <IconComponent size={48} className="text-blue-600 mb-4" />
                <h3 className="text-lg font-bold mb-2">{type.title}</h3>
                <p className="text-sm text-gray-600">{type.description}</p>
              </div>
            );
          })}
        </div>
      ) : (
        <div className="space-y-6">
          <button
            onClick={() => {
              setSelectedType(null);
              setPreview(null);
            }}
            className="text-blue-600 hover:text-blue-800"
          >
            ← بازگشت
          </button>

          <div className="bg-white border rounded-lg p-6">
            <h3 className="text-xl font-bold mb-4">{selectedType.title}</h3>

            <div className="space-y-4">
              <div>
                <label className="block mb-2">عنوان ویترین</label>
                <input
                  type="text"
                  value={formData.title}
                  onChange={(e) => setFormData({ ...formData, title: e.target.value })}
                  className="w-full border rounded px-3 py-2"
                />
              </div>

              <div>
                <label className="block mb-2">زیرعنوان</label>
                <input
                  type="text"
                  value={formData.subtitle}
                  onChange={(e) => setFormData({ ...formData, subtitle: e.target.value })}
                  className="w-full border rounded px-3 py-2"
                />
              </div>

              <div className="grid grid-cols-2 gap-4">
                <div>
                  <label className="block mb-2">نوع نمایش</label>
                  <select
                    value={formData.display_type}
                    onChange={(e) => setFormData({ ...formData, display_type: e.target.value })}
                    className="w-full border rounded px-3 py-2"
                  >
                    <option value="grid">شبکه‌ای</option>
                    <option value="carousel">اسلایدر</option>
                    <option value="list">لیستی</option>
                  </select>
                </div>

                <div>
                  <label className="block mb-2">تعداد محصولات</label>
                  <input
                    type="number"
                    min="1"
                    max="50"
                    value={formData.products_limit}
                    onChange={(e) => {
                      setFormData({ ...formData, products_limit: parseInt(e.target.value) });
                      handlePreview(selectedType.type);
                    }}
                    className="w-full border rounded px-3 py-2"
                  />
                </div>
              </div>
            </div>

            <button
              onClick={handleCreate}
              className="mt-6 bg-blue-600 text-white px-6 py-2 rounded hover:bg-blue-700"
            >
              ایجاد ویترین
            </button>
          </div>

          {preview && (
            <div className="bg-white border rounded-lg p-6">
              <h4 className="font-bold mb-4">پیش‌نمایش محصولات ({preview.length})</h4>
              <div className="grid grid-cols-2 md:grid-cols-4 gap-4">
                {preview.slice(0, 8).map((product) => (
                  <div key={product.id} className="border rounded p-2">
                    <div className="text-sm truncate">{product.name}</div>
                    <div className="text-xs text-gray-600">
                      {Number(product.discount_price || product.price).toLocaleString()} تومان
                    </div>
                  </div>
                ))}
              </div>
            </div>
          )}
        </div>
      )}
    </div>
  );
};

export default AutoShowcaseCreator;
```

---

## نصب کتابخانه‌های مورد نیاز

```bash
# React Icons
npm install lucide-react

# Swiper (برای اسلایدر)
npm install swiper

# Tailwind CSS (اختیاری)
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
```
