Skip to content

Latest commit

 

History

History
1568 lines (1380 loc) · 42.2 KB

File metadata and controls

1568 lines (1380 loc) · 42.2 KB

📚 Kapsamlı Tutorial - React 19 Clapton Admin Template

Sıfırdan profesyonel admin paneli oluşturma rehberi

🎯 Bu Tutorial'da Öğrenecekleriniz

  • ✅ Template'i kurma ve yapılandırma
  • ✅ Komponentleri etkili kullanma
  • ✅ Kendi sayfalarınızı oluşturma
  • ✅ Tema ve stil özelleştirme
  • ✅ AI komponentlerini entegre etme
  • ✅ Gerçek veri ile çalışma
  • ✅ Production'a deploy etme

📋 Ön Hazırlık

Gerekli Araçlar

# Node.js versiyonunu kontrol edin
node --version  # 18.0.0 veya üzeri olmalı

# Package manager seçin
npm --version   # veya
yarn --version  # veya  
bun --version

Geliştirme Ortamı

  • VS Code (önerilen)
  • React Developer Tools (tarayıcı eklentisi)
  • Tailwind CSS IntelliSense (VS Code eklentisi)

🚀 Adım 1: Kurulum ve İlk Çalıştırma

Template'i İndirin

# 1. Repository'yi klonlayın
git clone https://github.com/sametuca/react19-clapton-admin-template-premium

# 2. Proje dizinine gidin
cd react19-clapton-admin-template

# 3. Bağımlılıkları yükleyin
npm install

# 4. Geliştirme sunucusunu başlatın
npm run dev

İlk Kontroller

  1. Tarayıcıda açın: http://localhost:8080
  2. Karşılama sayfasını görün: Modern React 19 karşılama ekranı
  3. Dashboard'a gidin: /dashboard - Ana yönetim paneli
  4. Komponentleri keşfedin: /showcase - Tüm komponentler

🏗️ Adım 2: Proje Yapısını Anlama

Klasör Yapısı Detayı

src/
├── components/          # Komponentler
│   ├── ui/             # Temel UI komponentleri
│   │   ├── button.tsx  # Buton komponenti
│   │   ├── card.tsx    # Kart komponenti
│   │   ├── ai/         # AI komponentleri
│   │   └── advanced/   # Gelişmiş komponentler
│   ├── AppSidebar.tsx  # Ana sidebar
│   └── ThemeSelector.tsx # Tema seçici
├── pages/              # Sayfa komponentleri
│   ├── Dashboard.tsx   # Ana dashboard
│   ├── Welcome.tsx     # Karşılama sayfası
│   ├── showcase/       # Komponent vitrin sayfaları
│   └── examples/       # Örnek sayfalar
├── contexts/           # React context'leri
│   ├── ThemeContext.tsx # Tema yönetimi
│   └── LanguageContext.tsx # Dil yönetimi
├── layouts/            # Layout komponentleri
│   └── AppLayout.tsx   # Ana layout
└── lib/                # Yardımcı fonksiyonlar
    └── utils.ts        # Genel yardımcılar

Önemli Dosyalar

  • App.tsx: Ana uygulama ve routing
  • main.tsx: Uygulama giriş noktası
  • index.css: Global CSS ve tema değişkenleri
  • tailwind.config.ts: Tailwind CSS yapılandırması

🎨 Adım 3: İlk Sayfanızı Oluşturun

Basit Bir Dashboard Sayfası

// src/pages/MyDashboard.tsx
import { Helmet } from "react-helmet-async";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { StatsCard } from "@/components/ui/stats-card";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Users, DollarSign, ShoppingCart, TrendingUp } from "lucide-react";

export default function MyDashboard() {
  // Örnek veri
  const stats = [
    {
      title: "Toplam Kullanıcı",
      value: 1247,
      change: 12.5,
      changeType: "positive" as const,
      icon: Users,
      description: "Bu ay"
    },
    {
      title: "Gelir",
      value: 45678,
      change: 8.2,
      changeType: "positive" as const,
      icon: DollarSign,
      description: "₺",
      prefix: "₺"
    },
    {
      title: "Siparişler",
      value: 892,
      change: -2.1,
      changeType: "negative" as const,
      icon: ShoppingCart,
      description: "Bekleyen"
    },
    {
      title: "Büyüme",
      value: 23.4,
      change: 15.7,
      changeType: "positive" as const,
      icon: TrendingUp,
      description: "%",
      decimals: 1
    }
  ];

  return (
    <>
      <Helmet>
        <title>Benim Dashboard'um - React19 Admin</title>
        <meta name="description" content="Özel dashboard sayfası" />
      </Helmet>

      <div className="space-y-8">
        {/* Başlık */}
        <div>
          <h1 className="text-3xl font-bold tracking-tight">
            Benim Dashboard'um
          </h1>
          <p className="text-muted-foreground mt-1">
            Özel dashboard sayfanız
          </p>
        </div>

        {/* İstatistik Kartları */}
        <div className="grid gap-6 md:grid-cols-2 lg:grid-cols-4">
          {stats.map((stat, index) => (
            <StatsCard
              key={index}
              title={stat.title}
              value={stat.value}
              change={stat.change}
              changeType={stat.changeType}
              icon={stat.icon}
              description={stat.description}
              prefix={stat.prefix}
              decimals={stat.decimals}
              gradient={true}
            />
          ))}
        </div>

        {/* İçerik Kartları */}
        <div className="grid gap-6 md:grid-cols-2">
          <Card>
            <CardHeader>
              <CardTitle>Son Aktiviteler</CardTitle>
            </CardHeader>
            <CardContent>
              <div className="space-y-4">
                {[1, 2, 3].map((item) => (
                  <div key={item} className="flex items-center gap-3 p-3 rounded-lg hover:bg-muted/50 transition-colors">
                    <div className="w-2 h-2 rounded-full bg-primary" />
                    <div>
                      <p className="font-medium">Aktivite {item}</p>
                      <p className="text-sm text-muted-foreground">
                        {item} dakika önce
                      </p>
                    </div>
                  </div>
                ))}
              </div>
            </CardContent>
          </Card>

          <Card>
            <CardHeader>
              <CardTitle>Hızlı İşlemler</CardTitle>
            </CardHeader>
            <CardContent className="space-y-3">
              <Button className="w-full justify-start">
                <Users className="h-4 w-4 mr-2" />
                Kullanıcı Ekle
              </Button>
              <Button variant="outline" className="w-full justify-start">
                <ShoppingCart className="h-4 w-4 mr-2" />
                Yeni Sipariş
              </Button>
              <Button variant="secondary" className="w-full justify-start">
                <TrendingUp className="h-4 w-4 mr-2" />
                Rapor Oluştur
              </Button>
            </CardContent>
          </Card>
        </div>
      </div>
    </>
  );
}

Route Ekleme

// src/App.tsx - Routes içine ekleyin
import MyDashboard from "./pages/MyDashboard";

<Route element={<AppLayout />}>
  {/* ... mevcut route'lar */}
  <Route path="/my-dashboard" element={<MyDashboard />} />
</Route>

Sidebar'a Menü Ekleme

// src/components/AppSidebar.tsx
const mainItems = [
  // ... mevcut öğeler
  { 
    title: "Benim Dashboard'um", 
    url: "/my-dashboard", 
    icon: LayoutDashboard, 
    badge: "Yeni" 
  },
];

📊 Adım 4: Veri Tablosu Oluşturma

Kullanıcı Listesi Sayfası

// src/pages/UserList.tsx
import { Helmet } from "react-helmet-async";
import { DataTable } from "@/components/ui/data-table";
import { Badge } from "@/components/ui/badge";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { Button } from "@/components/ui/button";
import { Edit, Trash2, Eye } from "lucide-react";

export default function UserList() {
  // Örnek kullanıcı verisi
  const users = [
    {
      id: 1,
      name: "Ahmet Yılmaz",
      email: "ahmet@example.com",
      role: "Admin",
      status: "active",
      joinDate: "2024-01-15",
      avatar: "/api/placeholder/40/40"
    },
    {
      id: 2,
      name: "Zeynep Kaya",
      email: "zeynep@example.com",
      role: "Editor",
      status: "active",
      joinDate: "2024-02-20",
      avatar: "/api/placeholder/40/40"
    },
    {
      id: 3,
      name: "Mehmet Demir",
      email: "mehmet@example.com",
      role: "User",
      status: "inactive",
      joinDate: "2024-03-10",
      avatar: "/api/placeholder/40/40"
    }
  ];

  // Tablo sütunları
  const columns = [
    {
      key: 'avatar' as keyof typeof users[0],
      title: 'Kullanıcı',
      render: (value: string, row: any) => (
        <div className="flex items-center gap-3">
          <Avatar className="h-10 w-10">
            <AvatarImage src={value} alt={row.name} />
            <AvatarFallback>
              {row.name.split(' ').map((n: string) => n[0]).join('')}
            </AvatarFallback>
          </Avatar>
          <div>
            <div className="font-medium">{row.name}</div>
            <div className="text-sm text-muted-foreground">{row.email}</div>
          </div>
        </div>
      )
    },
    {
      key: 'role' as keyof typeof users[0],
      title: 'Rol',
      render: (value: string) => (
        <Badge variant="outline">{value}</Badge>
      )
    },
    {
      key: 'status' as keyof typeof users[0],
      title: 'Durum',
      render: (value: string) => (
        <Badge variant={value === 'active' ? 'default' : 'secondary'}>
          {value === 'active' ? 'Aktif' : 'Pasif'}
        </Badge>
      )
    },
    {
      key: 'joinDate' as keyof typeof users[0],
      title: 'Katılım Tarihi',
      sortable: true
    },
    {
      key: 'id' as keyof typeof users[0],
      title: 'İşlemler',
      render: (value: number, row: any) => (
        <div className="flex items-center gap-2">
          <Button size="sm" variant="ghost">
            <Eye className="h-4 w-4" />
          </Button>
          <Button size="sm" variant="ghost">
            <Edit className="h-4 w-4" />
          </Button>
          <Button size="sm" variant="ghost">
            <Trash2 className="h-4 w-4" />
          </Button>
        </div>
      )
    }
  ];

  return (
    <>
      <Helmet>
        <title>Kullanıcı Listesi - React19 Admin</title>
        <meta name="description" content="Kullanıcı yönetimi sayfası" />
      </Helmet>

      <div className="space-y-6">
        <div>
          <h1 className="text-3xl font-bold">Kullanıcı Listesi</h1>
          <p className="text-muted-foreground">
            Tüm kullanıcıları görüntüleyin ve yönetin
          </p>
        </div>

        <DataTable
          data={users}
          columns={columns}
          title="Kullanıcı Yönetimi"
          searchable={true}
          filterable={true}
          exportable={true}
          pageSize={10}
        />
      </div>
    </>
  );
}

🤖 Adım 5: AI Komponentlerini Kullanma

AI Destekli Arama Sayfası

// src/pages/AISearchPage.tsx
import { Helmet } from "react-helmet-async";
import { AISearch } from "@/components/ui/ai/ai-search";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { Bot, Search, Sparkles } from "lucide-react";

export default function AISearchPage() {
  return (
    <>
      <Helmet>
        <title>AI Arama - React19 Admin</title>
        <meta name="description" content="AI destekli akıllı arama sistemi" />
      </Helmet>

      <div className="space-y-8">
        <div className="text-center space-y-4">
          <div className="flex items-center justify-center gap-3">
            <Bot className="h-8 w-8 text-primary" />
            <h1 className="text-3xl font-bold">AI Destekli Arama</h1>
            <Badge variant="secondary" className="bg-gradient-to-r from-purple-500 to-blue-500 text-white">
              <Sparkles className="h-3 w-3 mr-1" />
              AI Powered
            </Badge>
          </div>
          <p className="text-xl text-muted-foreground max-w-2xl mx-auto">
            Yapay zeka destekli akıllı arama sistemi ile istediğiniz her şeyi hızlıca bulun
          </p>
        </div>

        <Card className="max-w-4xl mx-auto">
          <CardHeader>
            <CardTitle className="flex items-center gap-2">
              <Search className="h-5 w-5" />
              Akıllı Arama Sistemi
            </CardTitle>
          </CardHeader>
          <CardContent>
            <AISearch />
            
            <div className="mt-8 grid gap-4 md:grid-cols-3">
              <div className="text-center p-4 rounded-lg bg-muted/50">
                <Search className="h-8 w-8 mx-auto mb-2 text-blue-500" />
                <h3 className="font-semibold mb-1">Semantik Arama</h3>
                <p className="text-sm text-muted-foreground">
                  Anlamsal arama ile daha iyi sonuçlar
                </p>
              </div>
              <div className="text-center p-4 rounded-lg bg-muted/50">
                <Sparkles className="h-8 w-8 mx-auto mb-2 text-purple-500" />
                <h3 className="font-semibold mb-1">Akıllı Öneriler</h3>
                <p className="text-sm text-muted-foreground">
                  AI destekli arama önerileri
                </p>
              </div>
              <div className="text-center p-4 rounded-lg bg-muted/50">
                <Bot className="h-8 w-8 mx-auto mb-2 text-green-500" />
                <h3 className="font-semibold mb-1">Otomatik Tamamlama</h3>
                <p className="text-sm text-muted-foreground">
                  Yazarken otomatik tamamlama
                </p>
              </div>
            </div>
          </CardContent>
        </Card>
      </div>
    </>
  );
}

AI Chat Entegrasyonu

// src/layouts/AppLayout.tsx - Layout'a AI Chat ekleyin
import { AIChat } from "@/components/ui/ai/ai-chat";

export default function AppLayout() {
  return (
    <div className="min-h-screen">
      {/* ... mevcut layout içeriği */}
      
      {/* AI Chat - Floating button olarak */}
      <AIChat />
    </div>
  );
}

📈 Adım 6: Analitik Sayfası Oluşturma

Gelişmiş Analitik Dashboard

// src/pages/AdvancedAnalytics.tsx
import { Helmet } from "react-helmet-async";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { StatsCard } from "@/components/ui/stats-card";
import { MetricChart } from "@/components/ui/metric-chart";
import { ActivityFeed } from "@/components/ui/activity-feed";
import { AIInsights } from "@/components/ui/ai/ai-insights";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { 
  BarChart3, 
  TrendingUp, 
  Users, 
  Eye, 
  Download,
  Filter,
  Calendar,
  Globe,
  Smartphone,
  Monitor
} from "lucide-react";

export default function AdvancedAnalytics() {
  const analyticsStats = [
    {
      title: "Toplam Ziyaretçi",
      value: 124847,
      change: 15.2,
      changeType: "positive" as const,
      icon: Users,
      description: "Bu ay"
    },
    {
      title: "Sayfa Görüntüleme",
      value: 892341,
      change: 8.7,
      changeType: "positive" as const,
      icon: Eye,
      description: "Toplam"
    },
    {
      title: "Dönüşüm Oranı",
      value: 3.24,
      change: 0.8,
      changeType: "positive" as const,
      icon: TrendingUp,
      description: "%",
      decimals: 2
    },
    {
      title: "Ortalama Süre",
      value: 4.32,
      change: -0.5,
      changeType: "negative" as const,
      icon: BarChart3,
      description: "dakika",
      decimals: 2
    }
  ];

  const chartData = [
    { label: "Ocak", value: 4500, color: "bg-blue-500" },
    { label: "Şubat", value: 5200, color: "bg-green-500" },
    { label: "Mart", value: 4800, color: "bg-purple-500" },
    { label: "Nisan", value: 6100, color: "bg-orange-500" },
    { label: "Mayıs", value: 6800, color: "bg-red-500" },
    { label: "Haziran", value: 7200, color: "bg-indigo-500" }
  ];

  const activities = [
    {
      id: "1",
      user: { name: "Sistem", initials: "SY" },
      action: "Yeni rapor oluşturuldu",
      target: "Aylık Analiz Raporu",
      time: "5 dakika önce",
      type: "success" as const,
      icon: BarChart3
    },
    {
      id: "2",
      user: { name: "Admin", initials: "AD" },
      action: "Veri güncellendi",
      target: "Kullanıcı İstatistikleri",
      time: "15 dakika önce",
      type: "info" as const,
      icon: Users
    }
  ];

  return (
    <>
      <Helmet>
        <title>Gelişmiş Analitik - React19 Admin</title>
        <meta name="description" content="AI destekli gelişmiş analitik dashboard" />
      </Helmet>

      <div className="space-y-8">
        {/* Başlık */}
        <div className="flex items-center justify-between">
          <div>
            <h1 className="text-3xl font-bold tracking-tight">
              Gelişmiş Analitik
            </h1>
            <p className="text-muted-foreground mt-1">
              AI destekli analitik ve raporlama
            </p>
          </div>
          <div className="flex items-center gap-2">
            <Button variant="outline" size="sm">
              <Filter className="h-4 w-4 mr-2" />
              Filtrele
            </Button>
            <Button size="sm">
              <Download className="h-4 w-4 mr-2" />
              Rapor Al
            </Button>
          </div>
        </div>

        {/* İstatistikler */}
        <div className="grid gap-6 md:grid-cols-2 lg:grid-cols-4">
          {analyticsStats.map((stat, index) => (
            <StatsCard
              key={index}
              title={stat.title}
              value={stat.value}
              change={stat.change}
              changeType={stat.changeType}
              icon={stat.icon}
              description={stat.description}
              decimals={stat.decimals}
              gradient={true}
            />
          ))}
        </div>

        {/* Grafikler ve Aktiviteler */}
        <div className="grid gap-8 lg:grid-cols-2">
          <MetricChart
            title="Aylık Performans"
            data={chartData}
            total={34400}
            change={15.3}
            changeType="positive"
          />
          
          <ActivityFeed 
            activities={activities}
            title="Sistem Aktiviteleri"
          />
        </div>

        {/* AI Insights */}
        <Card>
          <CardHeader>
            <CardTitle className="flex items-center gap-2">
              <Sparkles className="h-5 w-5 text-purple-500" />
              AI Analiz ve Öngörüler
            </CardTitle>
          </CardHeader>
          <CardContent>
            <AIInsights />
          </CardContent>
        </Card>
      </div>
    </>
  );
}

🎨 Adım 7: Tema Özelleştirme

Kendi Temanızı Oluşturun

// src/contexts/ThemeContext.tsx - themes objesine ekleyin
const themes = {
  // ... mevcut temalar
  myBrand: {
    name: 'Marka Teması',
    description: 'Şirket markasına özel tema',
    colors: {
      background: '0 0% 100%',
      foreground: '222.2 84% 4.9%',
      primary: '346.8 77.2% 49.8%',        // Marka kırmızısı
      'primary-foreground': '355.7 100% 97.3%',
      secondary: '220.9 39.3% 11%',
      'secondary-foreground': '210 40% 98%',
      accent: '346.8 77.2% 49.8%',
      'accent-foreground': '355.7 100% 97.3%',
      // ... diğer renkler
    },
    gradient: 'linear-gradient(135deg, #ff6b6b 0%, #ee5a24 25%, #ff9ff3 50%, #54a0ff 75%, #5f27cd 100%)'
  }
};

CSS Özelleştirme

/* src/index.css - Özel tema stilleri */
.theme-myBrand body {
  background: linear-gradient(135deg, #ff6b6b 0%, #ee5a24 25%, #ff9ff3 50%, #54a0ff 75%, #5f27cd 100%);
  background-attachment: fixed;
}

.theme-myBrand .glassmorphism-card {
  background: rgba(255, 107, 107, 0.08);
  backdrop-filter: blur(25px);
  border: 1px solid rgba(255, 107, 107, 0.3);
  box-shadow: 
    0 8px 32px 0 rgba(255, 107, 107, 0.3),
    inset 0 1px 0 rgba(255, 107, 107, 0.2);
}

.theme-myBrand .gradient-text-primary {
  background: linear-gradient(135deg, #ff6b6b 0%, #ee5a24 100%);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}

🔗 Adım 8: API Entegrasyonu

API Hook Oluşturma

// src/hooks/use-api.ts
import { useState, useEffect } from 'react';

interface ApiResponse<T> {
  data: T | null;
  loading: boolean;
  error: string | null;
  refetch: () => void;
}

export function useApi<T>(url: string): ApiResponse<T> {
  const [data, setData] = useState<T | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  const fetchData = async () => {
    try {
      setLoading(true);
      setError(null);
      
      const response = await fetch(url);
      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }
      
      const result = await response.json();
      setData(result);
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Bir hata oluştu');
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    fetchData();
  }, [url]);

  return { data, loading, error, refetch: fetchData };
}

API ile Veri Çekme

// src/pages/UsersFromAPI.tsx
import { useApi } from '@/hooks/use-api';
import { LoadingSpinner } from '@/components/ui/loading-spinner';
import { Alert, AlertDescription } from '@/components/ui/alert';

export default function UsersFromAPI() {
  const { data: users, loading, error, refetch } = useApi<User[]>('/api/users');

  if (loading) {
    return (
      <div className="flex justify-center py-12">
        <LoadingSpinner size="lg" text="Kullanıcılar yükleniyor..." />
      </div>
    );
  }

  if (error) {
    return (
      <Alert variant="destructive">
        <AlertDescription>
          Hata: {error}
          <Button onClick={refetch} className="ml-2" size="sm">
            Tekrar Dene
          </Button>
        </AlertDescription>
      </Alert>
    );
  }

  return (
    <div>
      <DataTable
        data={users || []}
        columns={userColumns}
        title="API'den Kullanıcılar"
        searchable={true}
        exportable={true}
      />
    </div>
  );
}

🎯 Adım 9: Form Oluşturma

React Hook Form ile Gelişmiş Form

// src/pages/UserForm.tsx
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import * as z from 'zod';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import { toast } from '@/hooks/use-toast';

const formSchema = z.object({
  name: z.string().min(2, 'Ad en az 2 karakter olmalı'),
  email: z.string().email('Geçerli bir e-posta adresi girin'),
  role: z.string().min(1, 'Rol seçimi zorunlu'),
  department: z.string().min(1, 'Departman seçimi zorunlu'),
});

type FormData = z.infer<typeof formSchema>;

export default function UserForm() {
  const form = useForm<FormData>({
    resolver: zodResolver(formSchema),
    defaultValues: {
      name: '',
      email: '',
      role: '',
      department: '',
    },
  });

  const onSubmit = async (data: FormData) => {
    try {
      // API çağrısı simülasyonu
      await new Promise(resolve => setTimeout(resolve, 1000));
      
      toast({
        title: "Başarılı!",
        description: "Kullanıcı başarıyla eklendi.",
      });
      
      form.reset();
    } catch (error) {
      toast({
        title: "Hata!",
        description: "Kullanıcı eklenirken bir hata oluştu.",
        variant: "destructive",
      });
    }
  };

  return (
    <Card className="max-w-2xl mx-auto">
      <CardHeader>
        <CardTitle>Yeni Kullanıcı Ekle</CardTitle>
      </CardHeader>
      <CardContent>
        <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6">
          <div className="grid gap-4 md:grid-cols-2">
            <div className="space-y-2">
              <Label htmlFor="name">Ad Soyad</Label>
              <Input
                id="name"
                {...form.register('name')}
                placeholder="Ahmet Yılmaz"
              />
              {form.formState.errors.name && (
                <p className="text-sm text-red-500">
                  {form.formState.errors.name.message}
                </p>
              )}
            </div>
            
            <div className="space-y-2">
              <Label htmlFor="email">E-posta</Label>
              <Input
                id="email"
                type="email"
                {...form.register('email')}
                placeholder="ahmet@example.com"
              />
              {form.formState.errors.email && (
                <p className="text-sm text-red-500">
                  {form.formState.errors.email.message}
                </p>
              )}
            </div>
          </div>

          <div className="grid gap-4 md:grid-cols-2">
            <div className="space-y-2">
              <Label>Rol</Label>
              <Select onValueChange={(value) => form.setValue('role', value)}>
                <SelectTrigger>
                  <SelectValue placeholder="Rol seçin" />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value="admin">Admin</SelectItem>
                  <SelectItem value="editor">Editör</SelectItem>
                  <SelectItem value="user">Kullanıcı</SelectItem>
                </SelectContent>
              </Select>
              {form.formState.errors.role && (
                <p className="text-sm text-red-500">
                  {form.formState.errors.role.message}
                </p>
              )}
            </div>
            
            <div className="space-y-2">
              <Label>Departman</Label>
              <Select onValueChange={(value) => form.setValue('department', value)}>
                <SelectTrigger>
                  <SelectValue placeholder="Departman seçin" />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value="it">Bilgi İşlem</SelectItem>
                  <SelectItem value="hr">İnsan Kaynakları</SelectItem>
                  <SelectItem value="sales">Satış</SelectItem>
                  <SelectItem value="marketing">Pazarlama</SelectItem>
                </SelectContent>
              </Select>
              {form.formState.errors.department && (
                <p className="text-sm text-red-500">
                  {form.formState.errors.department.message}
                </p>
              )}
            </div>
          </div>

          <div className="flex justify-end gap-4">
            <Button type="button" variant="outline" onClick={() => form.reset()}>
              Temizle
            </Button>
            <Button 
              type="submit" 
              disabled={form.formState.isSubmitting}
            >
              {form.formState.isSubmitting ? 'Kaydediliyor...' : 'Kaydet'}
            </Button>
          </div>
        </form>
      </CardContent>
    </Card>
  );
}

🚀 Adım 10: Production'a Hazırlık

Environment Variables

# .env.production
NODE_ENV=production
VITE_APP_NAME=Sizin Uygulama Adınız
VITE_API_URL=https://api.yourdomain.com
VITE_AUTH_DOMAIN=auth.yourdomain.com

Build Optimizasyonu

// vite.config.ts
export default defineConfig({
  build: {
    rollupOptions: {
      output: {
        manualChunks: {
          vendor: ['react', 'react-dom'],
          ui: ['@radix-ui/react-dialog', '@radix-ui/react-dropdown-menu'],
          charts: ['recharts'],
        },
      },
    },
  },
});

SEO Optimizasyonu

// Her sayfada Helmet kullanın
<Helmet>
  <title>Sayfa Başlığı - Uygulama Adı</title>
  <meta name="description" content="Sayfa açıklaması" />
  <meta property="og:title" content="Sayfa Başlığı" />
  <meta property="og:description" content="Sayfa açıklaması" />
  <link rel="canonical" href="https://yourdomain.com/page" />
</Helmet>

📱 Adım 11: Mobil Optimizasyon

Responsive Tasarım İpuçları

// Mobil-first yaklaşım
function ResponsiveCard() {
  return (
    <Card className="
      p-4              /* Mobil: küçük padding */
      md:p-6          /* Tablet: orta padding */
      lg:p-8          /* Desktop: büyük padding */
      
      text-sm         /* Mobil: küçük metin */
      md:text-base    /* Tablet: normal metin */
      lg:text-lg      /* Desktop: büyük metin */
    ">
      <CardContent className="
        space-y-2       /* Mobil: az boşluk */
        md:space-y-4   /* Tablet: orta boşluk */
        lg:space-y-6   /* Desktop: çok boşluk */
      ">
        {/* İçerik */}
      </CardContent>
    </Card>
  );
}

Mobil Menü Optimizasyonu

// src/components/AppSidebar.tsx - Mobil menü zaten mevcut
// Özelleştirmek için:
const [isMobileOpen, setIsMobileOpen] = useState(false);

// Mobil menü butonu
<Button
  variant="ghost"
  size="icon"
  onClick={() => setIsMobileOpen(!isMobileOpen)}
  className="lg:hidden"
>
  <Menu className="h-5 w-5" />
</Button>

🔒 Adım 12: Güvenlik ve Authentication

Auth Context Oluşturma

// src/contexts/AuthContext.tsx
import React, { createContext, useContext, useState } from 'react';

interface User {
  id: string;
  name: string;
  email: string;
  role: string;
}

interface AuthContextType {
  user: User | null;
  login: (email: string, password: string) => Promise<void>;
  logout: () => void;
  loading: boolean;
}

const AuthContext = createContext<AuthContextType | undefined>(undefined);

export function AuthProvider({ children }: { children: React.ReactNode }) {
  const [user, setUser] = useState<User | null>(null);
  const [loading, setLoading] = useState(false);

  const login = async (email: string, password: string) => {
    setLoading(true);
    try {
      // API çağrısı
      const response = await fetch('/api/login', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ email, password }),
      });
      
      const userData = await response.json();
      setUser(userData);
      
      // Token'ı localStorage'a kaydet
      localStorage.setItem('token', userData.token);
    } catch (error) {
      throw error;
    } finally {
      setLoading(false);
    }
  };

  const logout = () => {
    setUser(null);
    localStorage.removeItem('token');
  };

  return (
    <AuthContext.Provider value={{ user, login, logout, loading }}>
      {children}
    </AuthContext.Provider>
  );
}

export function useAuth() {
  const context = useContext(AuthContext);
  if (!context) {
    throw new Error('useAuth must be used within AuthProvider');
  }
  return context;
}

Protected Route

// src/components/ProtectedRoute.tsx
import { useAuth } from '@/contexts/AuthContext';
import { Navigate } from 'react-router-dom';
import { LoadingSpinner } from '@/components/ui/loading-spinner';

interface ProtectedRouteProps {
  children: React.ReactNode;
  requiredRole?: string;
}

export function ProtectedRoute({ children, requiredRole }: ProtectedRouteProps) {
  const { user, loading } = useAuth();

  if (loading) {
    return (
      <div className="flex justify-center items-center min-h-screen">
        <LoadingSpinner size="lg" text="Yetkilendirme kontrol ediliyor..." />
      </div>
    );
  }

  if (!user) {
    return <Navigate to="/login" replace />;
  }

  if (requiredRole && user.role !== requiredRole) {
    return <Navigate to="/unauthorized" replace />;
  }

  return <>{children}</>;
}

📊 Adım 13: Gerçek Veri ile Çalışma

API Service Oluşturma

// src/services/api.ts
const API_BASE_URL = import.meta.env.VITE_API_URL || 'http://localhost:3000/api';

class ApiService {
  private async request<T>(endpoint: string, options?: RequestInit): Promise<T> {
    const token = localStorage.getItem('token');
    
    const response = await fetch(`${API_BASE_URL}${endpoint}`, {
      headers: {
        'Content-Type': 'application/json',
        ...(token && { Authorization: `Bearer ${token}` }),
        ...options?.headers,
      },
      ...options,
    });

    if (!response.ok) {
      throw new Error(`API Error: ${response.status}`);
    }

    return response.json();
  }

  // Kullanıcı işlemleri
  async getUsers() {
    return this.request<User[]>('/users');
  }

  async createUser(userData: Partial<User>) {
    return this.request<User>('/users', {
      method: 'POST',
      body: JSON.stringify(userData),
    });
  }

  async updateUser(id: string, userData: Partial<User>) {
    return this.request<User>(`/users/${id}`, {
      method: 'PUT',
      body: JSON.stringify(userData),
    });
  }

  async deleteUser(id: string) {
    return this.request<void>(`/users/${id}`, {
      method: 'DELETE',
    });
  }

  // Dashboard istatistikleri
  async getDashboardStats() {
    return this.request<DashboardStats>('/dashboard/stats');
  }
}

export const apiService = new ApiService();

Gerçek Veri ile Dashboard

// src/pages/RealDataDashboard.tsx
import { useEffect, useState } from 'react';
import { apiService } from '@/services/api';
import { StatsCard } from '@/components/ui/stats-card';
import { LoadingSpinner } from '@/components/ui/loading-spinner';

export default function RealDataDashboard() {
  const [stats, setStats] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const fetchStats = async () => {
      try {
        const data = await apiService.getDashboardStats();
        setStats(data);
      } catch (error) {
        console.error('Stats yüklenemedi:', error);
      } finally {
        setLoading(false);
      }
    };

    fetchStats();
  }, []);

  if (loading) {
    return (
      <div className="flex justify-center py-12">
        <LoadingSpinner size="lg" text="Dashboard yükleniyor..." />
      </div>
    );
  }

  return (
    <div className="space-y-6">
      <h1 className="text-3xl font-bold">Gerçek Veri Dashboard</h1>
      
      {stats && (
        <div className="grid gap-6 md:grid-cols-2 lg:grid-cols-4">
          <StatsCard
            title="Toplam Kullanıcı"
            value={stats.totalUsers}
            change={stats.userGrowth}
            changeType="positive"
            icon={Users}
          />
          {/* ... diğer istatistikler */}
        </div>
      )}
    </div>
  );
}

🎨 Adım 14: Premium Komponentleri Kullanma

3D Kartlar

import { Card3D, ImageCard3D } from '@/components/ui/3d-card';

function Premium3DPage() {
  return (
    <div className="grid gap-8 md:grid-cols-3">
      <Card3D intensity={25} scale={1.1}>
        <Card className="h-64">
          <CardContent className="p-6">
            <h3 className="text-xl font-bold mb-2">3D Kart</h3>
            <p>Mouse ile üzerine gelin!</p>
          </CardContent>
        </Card>
      </Card3D>
      
      <ImageCard3D
        image="https://images.unsplash.com/photo-1551434678-e076c223a692?w=400&h=300&fit=crop"
        title="Premium Dashboard"
        description="Gelişmiş admin paneli"
        badge="Yeni"
      />
    </div>
  );
}

Glassmorphism Efektleri

import { GlassmorphismCard } from '@/components/ui/glassmorphism-card';

function GlassEffectsPage() {
  return (
    <div className="grid gap-6 md:grid-cols-3">
      <GlassmorphismCard
        title="Analytics"
        description="Gelişmiş analitik araçları"
        icon={BarChart3}
        variant="primary"
        blur="lg"
      >
        <div className="space-y-3">
          <div className="flex justify-between">
            <span>Performans</span>
            <span className="font-semibold">95%</span>
          </div>
          <Progress value={95} />
        </div>
      </GlassmorphismCard>
    </div>
  );
}

🚀 Adım 15: Deployment

Netlify Deployment

# 1. Build alın
npm run build

# 2. Netlify CLI yükleyin (opsiyonel)
npm i -g netlify-cli

# 3. Deploy edin
netlify deploy --prod --dir=dist

Environment Variables (Production)

# Netlify
netlify env:set VITE_API_URL https://api.yourdomain.com

🔧 Adım 16: Bakım ve Güncelleme

Dependency Güncellemeleri

# Güncel olmayan paketleri kontrol edin
npm outdated

# Güvenlik açıklarını kontrol edin
npm audit

# Paketleri güncelleyin
npm update

# Major güncellemeler için
npx npm-check-updates -u
npm install

Performance Monitoring

// src/utils/performance.ts
export function measurePerformance(name: string, fn: () => void) {
  const start = performance.now();
  fn();
  const end = performance.now();
  console.log(`${name} took ${end - start} milliseconds`);
}

// Kullanım
measurePerformance('Component Render', () => {
  // Komponent render işlemi
});

Error Boundary

// src/components/ErrorBoundary.tsx
import React from 'react';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
import { AlertTriangle } from 'lucide-react';

interface ErrorBoundaryState {
  hasError: boolean;
  error?: Error;
}

export class ErrorBoundary extends React.Component<
  React.PropsWithChildren<{}>,
  ErrorBoundaryState
> {
  constructor(props: React.PropsWithChildren<{}>) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError(error: Error): ErrorBoundaryState {
    return { hasError: true, error };
  }

  componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
    console.error('Error caught by boundary:', error, errorInfo);
  }

  render() {
    if (this.state.hasError) {
      return (
        <div className="min-h-screen flex items-center justify-center p-4">
          <Card className="max-w-md w-full">
            <CardHeader className="text-center">
              <AlertTriangle className="h-12 w-12 text-red-500 mx-auto mb-4" />
              <CardTitle>Bir Hata Oluştu</CardTitle>
            </CardHeader>
            <CardContent className="text-center space-y-4">
              <p className="text-muted-foreground">
                Beklenmeyen bir hata oluştu. Lütfen sayfayı yenileyin.
              </p>
              <Button onClick={() => window.location.reload()}>
                Sayfayı Yenile
              </Button>
            </CardContent>
          </Card>
        </div>
      );
    }

    return this.props.children;
  }
}

🎓 Adım 17: Best Practices

Kod Organizasyonu

// ✅ İyi: Tek sorumluluk prensibi
function UserCard({ user }: { user: User }) {
  return (
    <Card>
      <CardContent>
        <h3>{user.name}</h3>
        <p>{user.email}</p>
      </CardContent>
    </Card>
  );
}

// ✅ İyi: Custom hook kullanımı
function useUsers() {
  const [users, setUsers] = useState<User[]>([]);
  const [loading, setLoading] = useState(true);
  
  // ... logic
  
  return { users, loading, refetch };
}

// ✅ İyi: Type safety
interface UserListProps {
  users: User[];
  onUserSelect: (user: User) => void;
  loading?: boolean;
}

Performance Optimizasyonu

// ✅ Lazy loading
const HeavyComponent = lazy(() => import('./HeavyComponent'));

// ✅ Memoization
const ExpensiveComponent = memo(function ExpensiveComponent({ data }) {
  const processedData = useMemo(() => {
    return heavyProcessing(data);
  }, [data]);
  
  return <div>{processedData}</div>;
});

// ✅ Callback optimization
const MyComponent = ({ onSave }: { onSave: (data: any) => void }) => {
  const handleSave = useCallback((data) => {
    onSave(data);
  }, [onSave]);
  
  return <Button onClick={() => handleSave(data)}>Save</Button>;
};

📈 Adım 18: Analytics ve Monitoring

Google Analytics Entegrasyonu

// src/utils/analytics.ts
declare global {
  interface Window {
    gtag: (...args: any[]) => void;
  }
}

export function trackEvent(action: string, category: string, label?: string) {
  if (typeof window !== 'undefined' && window.gtag) {
    window.gtag('event', action, {
      event_category: category,
      event_label: label,
    });
  }
}

// Kullanım
trackEvent('click', 'button', 'header-cta');

Error Tracking

// src/utils/errorTracking.ts
export function logError(error: Error, context?: string) {
  console.error('Error:', error, 'Context:', context);
  
  // Sentry, LogRocket vb. servislere gönder
  if (import.meta.env.PROD) {
    // Production'da error tracking servisine gönder
  }
}

🎯 Sonuç ve Sonraki Adımlar

Tamamladığınız Şeyler ✅

  • ✅ Template kurulumu ve yapılandırması
  • ✅ Temel sayfa oluşturma
  • ✅ Komponent kullanımı
  • ✅ Tema özelleştirme
  • ✅ API entegrasyonu
  • ✅ Form oluşturma
  • ✅ Responsive tasarım
  • ✅ Production deployment

Gelişmiş Konular 🚀

  • State Management: Redux Toolkit, Zustand
  • Testing: Jest, React Testing Library
  • E2E Testing: Playwright, Cypress
  • Monitoring: Sentry, LogRocket
  • CI/CD: GitHub Actions, GitLab CI

Önerilen Kaynaklar 📚

Topluluk ve Destek 🤝


🎉 Tebrikler!

Bu tutorial'ı tamamladığınız için tebrikler! Artık React 19 Clapton Admin Template ile profesyonel admin panelleri oluşturabilirsiniz.

Başarı Rozetleriniz 🏆

  • 🥇 Template Master: Template'i başarıyla kurdunuz
  • 🥈 Component Expert: Komponentleri etkili kullanıyorsunuz
  • 🥉 Theme Designer: Tema özelleştirmesi yapabiliyorsunuz
  • 🏆 Full Stack: API entegrasyonu tamamladınız
  • 💎 Production Ready: Deploy sürecini öğrendiniz

Sonraki Hedefleriniz 🎯

  1. Kendi Projenizi Başlatın: Öğrendiklerinizi gerçek projede uygulayın
  2. Toplulukla Paylaşın: Yaptığınız projeleri toplulukla paylaşın
  3. Katkıda Bulunun: Template'e katkıda bulunun ve geliştirin
  4. Öğretmeye Başlayın: Bilginizi başkalarıyla paylaşın

Başarılı projeler dileriz! 🚀

Made with ❤️ by Clapton Team