This commit is contained in:
gpt-engineer-app[bot]
2025-12-19 14:13:40 +00:00
parent 46caf550a6
commit e5d42d2d1b
7 changed files with 986 additions and 119 deletions

View File

@@ -9,6 +9,7 @@ import { useCart } from '@/contexts/CartContext';
import { toast } from '@/hooks/use-toast';
import { Skeleton } from '@/components/ui/skeleton';
import { formatIDR } from '@/lib/format';
import { Video } from 'lucide-react';
interface Product {
id: string;
@@ -21,27 +22,45 @@ interface Product {
is_active: boolean;
}
interface ConsultingSettings {
is_consulting_enabled: boolean;
consulting_block_price: number;
consulting_block_duration_minutes: number;
}
export default function Products() {
const [products, setProducts] = useState<Product[]>([]);
const [consultingSettings, setConsultingSettings] = useState<ConsultingSettings | null>(null);
const [loading, setLoading] = useState(true);
const { addItem, items } = useCart();
useEffect(() => {
fetchProducts();
fetchData();
}, []);
const fetchProducts = async () => {
const { data, error } = await supabase
.from('products')
.select('*')
.eq('is_active', true)
.order('created_at', { ascending: false });
const fetchData = async () => {
const [productsRes, consultingRes] = await Promise.all([
supabase
.from('products')
.select('*')
.eq('is_active', true)
.order('created_at', { ascending: false }),
supabase
.from('consulting_settings')
.select('is_consulting_enabled, consulting_block_price, consulting_block_duration_minutes')
.single(),
]);
if (error) {
if (productsRes.error) {
toast({ title: 'Error', description: 'Gagal memuat produk', variant: 'destructive' });
} else {
setProducts(data || []);
setProducts(productsRes.data || []);
}
if (consultingRes.data) {
setConsultingSettings(consultingRes.data);
}
setLoading(false);
};
@@ -87,12 +106,42 @@ export default function Products() {
</Card>
))}
</div>
) : products.length === 0 ? (
<div className="text-center py-12">
<p className="text-muted-foreground">Belum ada produk tersedia.</p>
</div>
) : (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{/* Consulting Card - Only show when enabled */}
{consultingSettings?.is_consulting_enabled && (
<Card className="border-2 border-primary shadow-sm hover:shadow-md transition-shadow bg-primary/5">
<CardHeader>
<div className="flex justify-between items-start">
<CardTitle className="text-xl flex items-center gap-2">
<Video className="w-5 h-5" />
Konsultasi 1-on-1
</CardTitle>
<Badge className="bg-primary">Konsultasi</Badge>
</div>
<CardDescription className="line-clamp-2">
Sesi konsultasi pribadi dengan mentor. Pilih waktu dan durasi sesuai kebutuhan Anda.
</CardDescription>
</CardHeader>
<CardContent>
<div className="flex items-center gap-2 mb-4">
<span className="text-2xl font-bold">
{formatIDR(consultingSettings.consulting_block_price)}
</span>
<span className="text-muted-foreground">
/ {consultingSettings.consulting_block_duration_minutes} menit
</span>
</div>
<Link to="/consulting">
<Button className="w-full shadow-sm">
Booking Sekarang
</Button>
</Link>
</CardContent>
</Card>
)}
{/* Regular Products */}
{products.map((product) => (
<Card key={product.id} className="border-2 border-border shadow-sm hover:shadow-md transition-shadow">
<CardHeader>
@@ -128,6 +177,12 @@ export default function Products() {
</CardContent>
</Card>
))}
{products.length === 0 && !consultingSettings?.is_consulting_enabled && (
<div className="col-span-full text-center py-12">
<p className="text-muted-foreground">Belum ada produk tersedia.</p>
</div>
)}
</div>
)}
</div>

View File

@@ -7,6 +7,8 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
import { WorkhoursTab } from '@/components/admin/settings/WorkhoursTab';
import { NotifikasiTab } from '@/components/admin/settings/NotifikasiTab';
import { KonsultasiTab } from '@/components/admin/settings/KonsultasiTab';
import { BrandingTab } from '@/components/admin/settings/BrandingTab';
import { IntegrasiTab } from '@/components/admin/settings/IntegrasiTab';
import { Clock, Bell, Video, Palette, Puzzle } from 'lucide-react';
export default function AdminSettings() {
@@ -51,11 +53,11 @@ export default function AdminSettings() {
<Video className="w-4 h-4" />
<span className="hidden sm:inline">Konsultasi</span>
</TabsTrigger>
<TabsTrigger value="branding" className="flex items-center gap-2" disabled>
<TabsTrigger value="branding" className="flex items-center gap-2">
<Palette className="w-4 h-4" />
<span className="hidden sm:inline">Branding</span>
</TabsTrigger>
<TabsTrigger value="integrasi" className="flex items-center gap-2" disabled>
<TabsTrigger value="integrasi" className="flex items-center gap-2">
<Puzzle className="w-4 h-4" />
<span className="hidden sm:inline">Integrasi</span>
</TabsTrigger>
@@ -74,15 +76,11 @@ export default function AdminSettings() {
</TabsContent>
<TabsContent value="branding">
<div className="text-center py-12 text-muted-foreground">
Fitur Branding akan segera hadir
</div>
<BrandingTab />
</TabsContent>
<TabsContent value="integrasi">
<div className="text-center py-12 text-muted-foreground">
Fitur Integrasi akan segera hadir
</div>
<IntegrasiTab />
</TabsContent>
</Tabs>
</div>