stripe 2/2
This commit is contained in:
parent
c580407163
commit
d87afd8654
@ -62,7 +62,6 @@ const I18nPlayground = React.lazy(() => import("./components/playground/I18nPlay
|
||||
|
||||
const VersionMap = React.lazy(() => import("./pages/VersionMap"));
|
||||
|
||||
|
||||
// <GlobalDebug />
|
||||
import { EcommerceBundleWrapper } from "./bundles/ecommerce";
|
||||
|
||||
|
||||
@ -2,11 +2,14 @@ import React from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useAuth } from "@/hooks/useAuth";
|
||||
|
||||
import { getCurrentLang } from "@/i18n";
|
||||
|
||||
const EcommerceBundle = React.lazy(() => import("@polymech/ecommerce").then(m => ({ default: m.EcommerceBundle })));
|
||||
|
||||
export const EcommerceBundleWrapper = () => {
|
||||
const { user } = useAuth();
|
||||
const { user, session } = useAuth();
|
||||
const navigate = useNavigate();
|
||||
const locale = getCurrentLang();
|
||||
|
||||
// Memoize dependencies to prevent re-renders
|
||||
const dependencies = React.useMemo(() => {
|
||||
@ -51,6 +54,9 @@ export const EcommerceBundleWrapper = () => {
|
||||
})),
|
||||
total_amount: subtotal,
|
||||
payment_provider: data.paymentMethod,
|
||||
// Stripe-specific fields (undefined for non-Stripe payments)
|
||||
external_order_id: data.external_order_id,
|
||||
metadata: data.metadata,
|
||||
});
|
||||
useCartStore.getState().clearCart();
|
||||
},
|
||||
@ -60,9 +66,13 @@ export const EcommerceBundleWrapper = () => {
|
||||
},
|
||||
onNavigate: (path: string) => navigate(path),
|
||||
siteName: "PolyMech",
|
||||
contactEmail: "legal@polymech.org"
|
||||
contactEmail: "sales@plastic-hub.com",
|
||||
stripePublishableKey: import.meta.env.VITE_STRIPE_PUBLISHABLE_KEY,
|
||||
apiBaseUrl: import.meta.env.VITE_SERVER_IMAGE_API_URL || "",
|
||||
getAuthToken: async () => session?.access_token ?? null,
|
||||
locale,
|
||||
};
|
||||
}, [user, navigate]);
|
||||
}, [user, session, navigate, locale]);
|
||||
|
||||
return (
|
||||
<React.Suspense fallback={<div className="flex items-center justify-center p-12">Loading...</div>}>
|
||||
|
||||
@ -236,6 +236,7 @@ interface CompactAction {
|
||||
disabled?: boolean;
|
||||
iconColor?: string;
|
||||
onDelete?: () => void;
|
||||
testId?: string;
|
||||
}
|
||||
|
||||
const CompactFlowGroup = ({
|
||||
@ -266,6 +267,7 @@ const CompactFlowGroup = ({
|
||||
disabled={action.disabled}
|
||||
iconColor={action.iconColor}
|
||||
onDelete={action.onDelete}
|
||||
{...(action.testId ? { 'data-testid': action.testId } : {})}
|
||||
/>
|
||||
))}
|
||||
{shouldOverflow && (
|
||||
@ -738,14 +740,16 @@ export const PageRibbonBar = ({
|
||||
label: page.visible ? "Visible" : "Hidden",
|
||||
active: !page.visible,
|
||||
onClick: () => handleToggleVisibility(),
|
||||
iconColor: page.visible ? "text-emerald-500" : "text-gray-400"
|
||||
iconColor: page.visible ? "text-emerald-500" : "text-gray-400",
|
||||
testId: 'page-visibility-toggle'
|
||||
},
|
||||
{
|
||||
icon: page.is_public ? GitMerge : Settings,
|
||||
label: page.is_public ? "Public" : "Private",
|
||||
active: !page.is_public,
|
||||
onClick: () => handleTogglePublic(),
|
||||
iconColor: page.is_public ? "text-amber-500" : "text-gray-400"
|
||||
iconColor: page.is_public ? "text-amber-500" : "text-gray-400",
|
||||
testId: 'page-public-toggle'
|
||||
},
|
||||
{
|
||||
icon: FolderTree,
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { useAuth } from "@/hooks/useAuth";
|
||||
import ImageGallery from "@/components/ImageGallery";
|
||||
import { ImageFile } from "@/types";
|
||||
@ -10,7 +10,7 @@ import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card";
|
||||
import { User, Images, Save, Camera, Upload, Check, Key, Globe, Hash, MapPin, Building2 } from "lucide-react";
|
||||
import { User, Images, Save, Camera, Upload, Check, Key, Globe, Hash, MapPin, Building2, ShoppingBag } from "lucide-react";
|
||||
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
|
||||
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog";
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
||||
@ -33,7 +33,11 @@ import {
|
||||
useSidebar
|
||||
} from "@/components/ui/sidebar";
|
||||
|
||||
type ActiveSection = 'general' | 'api-keys' | 'variables' | 'addresses' | 'vendor' | 'gallery';
|
||||
const LazyPurchasesList = React.lazy(() =>
|
||||
import("@polymech/ecommerce").then(m => ({ default: m.PurchasesList }))
|
||||
);
|
||||
|
||||
type ActiveSection = 'general' | 'api-keys' | 'variables' | 'addresses' | 'vendor' | 'gallery' | 'purchases';
|
||||
|
||||
const Profile = () => {
|
||||
const { user, loading } = useAuth();
|
||||
@ -560,6 +564,26 @@ const Profile = () => {
|
||||
</Card>
|
||||
)}
|
||||
|
||||
{activeSection === 'purchases' && (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle><T>My Purchases</T></CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<React.Suspense fallback={<div className="flex items-center justify-center py-12 text-muted-foreground">Loading...</div>}>
|
||||
<LazyPurchasesList
|
||||
onFetchTransactions={async () => {
|
||||
const { listTransactions } = await import('@/modules/ecommerce/client-ecommerce');
|
||||
return listTransactions();
|
||||
}}
|
||||
onNavigate={navigate}
|
||||
toast={{ error: (msg: string) => toast.error(msg) }}
|
||||
/>
|
||||
</React.Suspense>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
{activeSection === 'analytics' && roles.includes('admin') && (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
@ -622,6 +646,7 @@ const ProfileSidebar = ({
|
||||
{ id: 'variables' as ActiveSection, label: translate('Variables'), icon: Hash },
|
||||
{ id: 'addresses' as ActiveSection, label: translate('Shipping Addresses'), icon: MapPin },
|
||||
{ id: 'vendor' as ActiveSection, label: translate('Vendor Profiles'), icon: Building2 },
|
||||
{ id: 'purchases' as ActiveSection, label: translate('Purchases'), icon: ShoppingBag },
|
||||
];
|
||||
|
||||
|
||||
|
||||
@ -342,6 +342,7 @@ const UserProfile = () => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Photos Grid - Using PhotoGrid with customPictures */}
|
||||
{/* Photos Grid - Using PhotoGrid with customPictures */}
|
||||
<div>
|
||||
<PhotoGrid
|
||||
|
||||
@ -25,6 +25,7 @@ import { Label } from "@/components/ui/label";
|
||||
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
|
||||
|
||||
import { fetchAnalytics, clearAnalytics } from '@/lib/db';
|
||||
import { supabase } from '@/integrations/supabase/client';
|
||||
import {
|
||||
filterModelToParams,
|
||||
paramsToFilterModel,
|
||||
@ -140,8 +141,13 @@ const AnalyticsDashboard = () => {
|
||||
|
||||
setData(events.map((e: any, index: number) => ({ ...e, id: `init-${index}` })));
|
||||
|
||||
// Start Streaming
|
||||
eventSource = new EventSource('/api/analytics/stream');
|
||||
// Start Streaming (with auth token as query param — EventSource doesn't support headers)
|
||||
const { data: sessionData } = await supabase.auth.getSession();
|
||||
const token = sessionData.session?.access_token;
|
||||
const streamUrl = token
|
||||
? `/api/analytics/stream?token=${encodeURIComponent(token)}`
|
||||
: '/api/analytics/stream';
|
||||
eventSource = new EventSource(streamUrl);
|
||||
|
||||
eventSource.addEventListener('log', (event: any) => {
|
||||
if (!isMounted) return;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user