Changes
This commit is contained in:
@@ -15,7 +15,15 @@ import { QRCodeSVG } from "qrcode.react";
|
||||
|
||||
// Pakasir configuration
|
||||
const PAKASIR_PROJECT_SLUG = "dewengoding";
|
||||
const PAKASIR_API_KEY = "iP13osgh7lAzWWIPsj7TbW5M3iGEAQMo";
|
||||
const SANDBOX_API_KEY = "iP13osgh7lAzWWIPsj7TbW5M3iGEAQMo";
|
||||
|
||||
// Centralized API key retrieval - uses env var with sandbox fallback
|
||||
const getPakasirApiKey = (): string => {
|
||||
return import.meta.env.VITE_PAKASIR_API_KEY || SANDBOX_API_KEY;
|
||||
};
|
||||
|
||||
// TODO: Replace with actual Supabase Edge Function URL after creation
|
||||
const PAKASIR_CALLBACK_URL = "https://lovable.backoffice.biz.id/functions/v1/pakasir-webhook";
|
||||
|
||||
type PaymentMethod = "qris" | "paypal";
|
||||
type CheckoutStep = "cart" | "payment" | "waiting";
|
||||
@@ -117,6 +125,9 @@ export default function Checkout() {
|
||||
|
||||
setOrderId(order.id);
|
||||
|
||||
// Build description from product titles
|
||||
const productTitles = items.map(item => item.title).join(", ");
|
||||
|
||||
if (paymentMethod === "qris") {
|
||||
// Call Pakasir API for QRIS
|
||||
try {
|
||||
@@ -127,7 +138,9 @@ export default function Checkout() {
|
||||
project: PAKASIR_PROJECT_SLUG,
|
||||
order_id: order.id,
|
||||
amount: amountInRupiah,
|
||||
api_key: PAKASIR_API_KEY,
|
||||
api_key: getPakasirApiKey(),
|
||||
description: productTitles,
|
||||
callback_url: PAKASIR_CALLBACK_URL,
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -222,7 +235,7 @@ export default function Checkout() {
|
||||
</Button>
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground text-center">
|
||||
Pembayaran akan otomatis terkonfirmasi setelah Anda scan dan bayar QR code di atas
|
||||
Pembayaran diproses melalui Pakasir dan akan dikonfirmasi otomatis setelah berhasil.
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
@@ -121,13 +121,35 @@ export default function ProductDetail() {
|
||||
|
||||
const checkUserAccess = async () => {
|
||||
if (!product || !user) return;
|
||||
const { data } = await supabase
|
||||
|
||||
// Check user_access table first
|
||||
const { data: accessData } = await supabase
|
||||
.from('user_access')
|
||||
.select('id')
|
||||
.eq('user_id', user.id)
|
||||
.eq('product_id', product.id)
|
||||
.maybeSingle();
|
||||
setHasAccess(!!data);
|
||||
|
||||
if (accessData) {
|
||||
setHasAccess(true);
|
||||
setCheckingAccess(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Also check for paid orders containing this product
|
||||
const { data: paidOrders } = await supabase
|
||||
.from('orders')
|
||||
.select(`
|
||||
id,
|
||||
order_items!inner (product_id)
|
||||
`)
|
||||
.eq('user_id', user.id)
|
||||
.eq('payment_status', 'paid')
|
||||
.eq('payment_provider', 'pakasir')
|
||||
.eq('order_items.product_id', product.id)
|
||||
.limit(1);
|
||||
|
||||
setHasAccess(!!(paidOrders && paidOrders.length > 0));
|
||||
setCheckingAccess(false);
|
||||
};
|
||||
|
||||
|
||||
@@ -42,11 +42,38 @@ export default function MemberDashboard() {
|
||||
}, [user, authLoading]);
|
||||
|
||||
const fetchData = async () => {
|
||||
const [accessRes, ordersRes] = await Promise.all([
|
||||
const [accessRes, ordersRes, paidOrdersRes] = await Promise.all([
|
||||
supabase.from('user_access').select(`id, product:products (id, title, slug, type, meeting_link, recording_url)`).eq('user_id', user!.id),
|
||||
supabase.from('orders').select('*').eq('user_id', user!.id).order('created_at', { ascending: false }).limit(3)
|
||||
supabase.from('orders').select('*').eq('user_id', user!.id).order('created_at', { ascending: false }).limit(3),
|
||||
// Also get products from paid orders (via order_items)
|
||||
supabase.from('orders')
|
||||
.select(`
|
||||
order_items (
|
||||
product:products (id, title, slug, type, meeting_link, recording_url)
|
||||
)
|
||||
`)
|
||||
.eq('user_id', user!.id)
|
||||
.eq('payment_status', 'paid')
|
||||
.eq('payment_provider', 'pakasir')
|
||||
]);
|
||||
if (accessRes.data) setAccess(accessRes.data as unknown as UserAccess[]);
|
||||
|
||||
// Combine access from user_access and paid orders
|
||||
const directAccess = accessRes.data as unknown as UserAccess[] || [];
|
||||
const paidProductAccess: UserAccess[] = [];
|
||||
|
||||
if (paidOrdersRes.data) {
|
||||
const existingIds = new Set(directAccess.map(a => a.product.id));
|
||||
paidOrdersRes.data.forEach((order: any) => {
|
||||
order.order_items?.forEach((item: any) => {
|
||||
if (item.product && !existingIds.has(item.product.id)) {
|
||||
existingIds.add(item.product.id);
|
||||
paidProductAccess.push({ id: `paid-${item.product.id}`, product: item.product });
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
setAccess([...directAccess, ...paidProductAccess]);
|
||||
if (ordersRes.data) setRecentOrders(ordersRes.data);
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user