mirror of
https://github.com/rzmk/learnhouse.git
synced 2025-12-19 04:19:25 +00:00
feat: add customers list on the dashboard
This commit is contained in:
parent
3988ee1d4b
commit
9f1d8c58d1
8 changed files with 361 additions and 7 deletions
|
|
@ -20,6 +20,7 @@ from src.services.payments.payments_courses import (
|
||||||
from src.services.payments.payments_webhook import handle_stripe_webhook
|
from src.services.payments.payments_webhook import handle_stripe_webhook
|
||||||
from src.services.payments.stripe import create_checkout_session
|
from src.services.payments.stripe import create_checkout_session
|
||||||
from src.services.payments.payments_access import check_course_paid_access
|
from src.services.payments.payments_access import check_course_paid_access
|
||||||
|
from src.services.payments.payments_customers import get_customers
|
||||||
|
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
@ -205,3 +206,15 @@ async def api_check_course_paid_access(
|
||||||
db_session=db_session
|
db_session=db_session
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@router.get("/{org_id}/customers")
|
||||||
|
async def api_get_customers(
|
||||||
|
request: Request,
|
||||||
|
org_id: int,
|
||||||
|
current_user: PublicUser = Depends(get_current_user),
|
||||||
|
db_session: Session = Depends(get_db_session),
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Get list of customers and their subscriptions for an organization
|
||||||
|
"""
|
||||||
|
return await get_customers(request, org_id, current_user, db_session)
|
||||||
|
|
|
||||||
51
apps/api/src/services/payments/payments_customers.py
Normal file
51
apps/api/src/services/payments/payments_customers.py
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
from fastapi import HTTPException, Request
|
||||||
|
from sqlmodel import Session, select
|
||||||
|
from src.db.organizations import Organization
|
||||||
|
from src.db.users import PublicUser, AnonymousUser, User
|
||||||
|
from src.db.payments.payments_users import PaymentsUser
|
||||||
|
from src.db.payments.payments_products import PaymentsProduct
|
||||||
|
from src.services.orgs.orgs import rbac_check
|
||||||
|
from src.services.payments.payments_products import get_payments_product
|
||||||
|
from src.services.users.users import read_user_by_id
|
||||||
|
|
||||||
|
async def get_customers(
|
||||||
|
request: Request,
|
||||||
|
org_id: int,
|
||||||
|
current_user: PublicUser | AnonymousUser,
|
||||||
|
db_session: Session,
|
||||||
|
):
|
||||||
|
# Check if organization exists
|
||||||
|
statement = select(Organization).where(Organization.id == org_id)
|
||||||
|
org = db_session.exec(statement).first()
|
||||||
|
if not org:
|
||||||
|
raise HTTPException(status_code=404, detail="Organization not found")
|
||||||
|
|
||||||
|
# RBAC check
|
||||||
|
await rbac_check(request, org.org_uuid, current_user, "read", db_session)
|
||||||
|
|
||||||
|
# Get all payment users for the organization
|
||||||
|
statement = select(PaymentsUser).where(PaymentsUser.org_id == org_id)
|
||||||
|
payment_users = db_session.exec(statement).all()
|
||||||
|
|
||||||
|
customers_data = []
|
||||||
|
|
||||||
|
for payment_user in payment_users:
|
||||||
|
# Get user data
|
||||||
|
user = await read_user_by_id(request, db_session, current_user, payment_user.user_id)
|
||||||
|
|
||||||
|
# Get product data
|
||||||
|
if org.id is None:
|
||||||
|
raise HTTPException(status_code=400, detail="Invalid organization ID")
|
||||||
|
product = await get_payments_product(request, org.id, payment_user.payment_product_id, current_user, db_session)
|
||||||
|
|
||||||
|
customer_data = {
|
||||||
|
'payment_user_id': payment_user.id,
|
||||||
|
'user': user if user else None,
|
||||||
|
'product': product if product else None,
|
||||||
|
'status': payment_user.status,
|
||||||
|
'creation_date': payment_user.creation_date,
|
||||||
|
'update_date': payment_user.update_date
|
||||||
|
}
|
||||||
|
customers_data.append(customer_data)
|
||||||
|
|
||||||
|
return customers_data
|
||||||
|
|
@ -9,6 +9,7 @@ import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||||
import { useOrg } from '@components/Contexts/OrgContext'
|
import { useOrg } from '@components/Contexts/OrgContext'
|
||||||
import PaymentsConfigurationPage from '@components/Dashboard/Payments/PaymentsConfigurationPage'
|
import PaymentsConfigurationPage from '@components/Dashboard/Payments/PaymentsConfigurationPage'
|
||||||
import PaymentsProductPage from '@components/Dashboard/Payments/PaymentsProductPage'
|
import PaymentsProductPage from '@components/Dashboard/Payments/PaymentsProductPage'
|
||||||
|
import PaymentsCustomersPage from '@components/Dashboard/Payments/PaymentsCustomersPage'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -101,7 +102,7 @@ function PaymentsPage({ params }: { params: PaymentsParams }) {
|
||||||
{selectedSubPage === 'general' && <div>General</div>}
|
{selectedSubPage === 'general' && <div>General</div>}
|
||||||
{selectedSubPage === 'configuration' && <PaymentsConfigurationPage />}
|
{selectedSubPage === 'configuration' && <PaymentsConfigurationPage />}
|
||||||
{selectedSubPage === 'paid-products' && <PaymentsProductPage />}
|
{selectedSubPage === 'paid-products' && <PaymentsProductPage />}
|
||||||
{selectedSubPage === 'customers' && <div>Customers</div>}
|
{selectedSubPage === 'customers' && <PaymentsCustomersPage />}
|
||||||
</motion.div>
|
</motion.div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
137
apps/web/components/Dashboard/Payments/PaymentsCustomersPage.tsx
Normal file
137
apps/web/components/Dashboard/Payments/PaymentsCustomersPage.tsx
Normal file
|
|
@ -0,0 +1,137 @@
|
||||||
|
import React from 'react'
|
||||||
|
import { useOrg } from '@components/Contexts/OrgContext'
|
||||||
|
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||||
|
import useSWR from 'swr'
|
||||||
|
import {
|
||||||
|
Table,
|
||||||
|
TableBody,
|
||||||
|
TableCell,
|
||||||
|
TableHead,
|
||||||
|
TableHeader,
|
||||||
|
TableRow,
|
||||||
|
} from "@/components/ui/table"
|
||||||
|
import { getOrgCustomers } from '@services/payments/payments'
|
||||||
|
import { Badge } from '@/components/ui/badge'
|
||||||
|
import PageLoading from '@components/Objects/Loaders/PageLoading'
|
||||||
|
import { RefreshCcw, SquareCheck } from 'lucide-react'
|
||||||
|
import { getUserAvatarMediaDirectory } from '@services/media/media'
|
||||||
|
import UserAvatar from '@components/Objects/UserAvatar'
|
||||||
|
|
||||||
|
interface PaymentUserData {
|
||||||
|
payment_user_id: number;
|
||||||
|
user: {
|
||||||
|
username: string;
|
||||||
|
first_name: string;
|
||||||
|
last_name: string;
|
||||||
|
email: string;
|
||||||
|
avatar_image: string;
|
||||||
|
user_uuid: string;
|
||||||
|
};
|
||||||
|
product: {
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
product_type: string;
|
||||||
|
amount: number;
|
||||||
|
currency: string;
|
||||||
|
};
|
||||||
|
status: string;
|
||||||
|
creation_date: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
function PaymentsUsersTable({ data }: { data: PaymentUserData[] }) {
|
||||||
|
return (
|
||||||
|
<Table>
|
||||||
|
<TableHeader>
|
||||||
|
<TableRow>
|
||||||
|
<TableHead>User</TableHead>
|
||||||
|
<TableHead>Product</TableHead>
|
||||||
|
<TableHead>Type</TableHead>
|
||||||
|
<TableHead>Amount</TableHead>
|
||||||
|
<TableHead>Status</TableHead>
|
||||||
|
<TableHead>Purchase Date</TableHead>
|
||||||
|
</TableRow>
|
||||||
|
</TableHeader>
|
||||||
|
<TableBody>
|
||||||
|
{data.map((item) => (
|
||||||
|
<TableRow key={item.payment_user_id}>
|
||||||
|
<TableCell className="font-medium">
|
||||||
|
<div className="flex items-center space-x-3">
|
||||||
|
<UserAvatar
|
||||||
|
border="border-2"
|
||||||
|
rounded="rounded-md"
|
||||||
|
avatar_url={getUserAvatarMediaDirectory(item.user.user_uuid, item.user.avatar_image)}
|
||||||
|
/>
|
||||||
|
<div className="flex flex-col">
|
||||||
|
<span className="font-medium">
|
||||||
|
{item.user.first_name || item.user.username}
|
||||||
|
</span>
|
||||||
|
<span className="text-sm text-gray-500">{item.user.email}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>{item.product.name}</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<div className="flex items-center space-x-2">
|
||||||
|
{item.product.product_type === 'subscription' ? (
|
||||||
|
<Badge variant="outline" className="flex items-center gap-1">
|
||||||
|
<RefreshCcw size={12} />
|
||||||
|
<span>Subscription</span>
|
||||||
|
</Badge>
|
||||||
|
) : (
|
||||||
|
<Badge variant="outline" className="flex items-center gap-1">
|
||||||
|
<SquareCheck size={12} />
|
||||||
|
<span>One-time</span>
|
||||||
|
</Badge>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
{new Intl.NumberFormat('en-US', {
|
||||||
|
style: 'currency',
|
||||||
|
currency: item.product.currency
|
||||||
|
}).format(item.product.amount)}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Badge
|
||||||
|
variant={item.status === 'active' ? 'default' :
|
||||||
|
item.status === 'completed' ? 'default' : 'secondary'}
|
||||||
|
>
|
||||||
|
{item.status}
|
||||||
|
</Badge>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
{new Date(item.creation_date).toLocaleDateString()}
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
))}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function PaymentsCustomersPage() {
|
||||||
|
const org = useOrg() as any
|
||||||
|
const session = useLHSession() as any
|
||||||
|
const access_token = session?.data?.tokens?.access_token
|
||||||
|
|
||||||
|
const { data: customers, error, isLoading } = useSWR(
|
||||||
|
org ? [`/payments/${org.id}/customers`, access_token] : null,
|
||||||
|
([url, token]) => getOrgCustomers(org.id, token)
|
||||||
|
)
|
||||||
|
|
||||||
|
if (isLoading) return <PageLoading />
|
||||||
|
if (error) return <div>Error loading customers</div>
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="ml-10 mr-10 mx-auto bg-white rounded-xl shadow-sm px-4 py-4">
|
||||||
|
<div className="flex flex-col bg-gray-50 -space-y-1 px-5 py-3 rounded-md mb-3">
|
||||||
|
<h1 className="font-bold text-xl text-gray-800">Customers</h1>
|
||||||
|
<h2 className="text-gray-500 text-md">View and manage your customer information</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<PaymentsUsersTable data={customers} />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PaymentsCustomersPage
|
||||||
120
apps/web/components/ui/table.tsx
Normal file
120
apps/web/components/ui/table.tsx
Normal file
|
|
@ -0,0 +1,120 @@
|
||||||
|
import * as React from "react"
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
|
const Table = React.forwardRef<
|
||||||
|
HTMLTableElement,
|
||||||
|
React.HTMLAttributes<HTMLTableElement>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<div className="relative w-full overflow-auto">
|
||||||
|
<table
|
||||||
|
ref={ref}
|
||||||
|
className={cn("w-full caption-bottom text-sm", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
))
|
||||||
|
Table.displayName = "Table"
|
||||||
|
|
||||||
|
const TableHeader = React.forwardRef<
|
||||||
|
HTMLTableSectionElement,
|
||||||
|
React.HTMLAttributes<HTMLTableSectionElement>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<thead ref={ref} className={cn("[&_tr]:border-b", className)} {...props} />
|
||||||
|
))
|
||||||
|
TableHeader.displayName = "TableHeader"
|
||||||
|
|
||||||
|
const TableBody = React.forwardRef<
|
||||||
|
HTMLTableSectionElement,
|
||||||
|
React.HTMLAttributes<HTMLTableSectionElement>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<tbody
|
||||||
|
ref={ref}
|
||||||
|
className={cn("[&_tr:last-child]:border-0", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
TableBody.displayName = "TableBody"
|
||||||
|
|
||||||
|
const TableFooter = React.forwardRef<
|
||||||
|
HTMLTableSectionElement,
|
||||||
|
React.HTMLAttributes<HTMLTableSectionElement>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<tfoot
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
"border-t bg-muted/50 font-medium [&>tr]:last:border-b-0",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
TableFooter.displayName = "TableFooter"
|
||||||
|
|
||||||
|
const TableRow = React.forwardRef<
|
||||||
|
HTMLTableRowElement,
|
||||||
|
React.HTMLAttributes<HTMLTableRowElement>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<tr
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
"border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
TableRow.displayName = "TableRow"
|
||||||
|
|
||||||
|
const TableHead = React.forwardRef<
|
||||||
|
HTMLTableCellElement,
|
||||||
|
React.ThHTMLAttributes<HTMLTableCellElement>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<th
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
"h-10 px-2 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
TableHead.displayName = "TableHead"
|
||||||
|
|
||||||
|
const TableCell = React.forwardRef<
|
||||||
|
HTMLTableCellElement,
|
||||||
|
React.TdHTMLAttributes<HTMLTableCellElement>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<td
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
"p-2 align-middle [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
TableCell.displayName = "TableCell"
|
||||||
|
|
||||||
|
const TableCaption = React.forwardRef<
|
||||||
|
HTMLTableCaptionElement,
|
||||||
|
React.HTMLAttributes<HTMLTableCaptionElement>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<caption
|
||||||
|
ref={ref}
|
||||||
|
className={cn("mt-4 text-sm text-muted-foreground", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
TableCaption.displayName = "TableCaption"
|
||||||
|
|
||||||
|
export {
|
||||||
|
Table,
|
||||||
|
TableHeader,
|
||||||
|
TableBody,
|
||||||
|
TableFooter,
|
||||||
|
TableHead,
|
||||||
|
TableRow,
|
||||||
|
TableCell,
|
||||||
|
TableCaption,
|
||||||
|
}
|
||||||
|
|
@ -31,6 +31,7 @@
|
||||||
"@sentry/nextjs": "^8.35.0",
|
"@sentry/nextjs": "^8.35.0",
|
||||||
"@sentry/utils": "^8.35.0",
|
"@sentry/utils": "^8.35.0",
|
||||||
"@stitches/react": "^1.2.8",
|
"@stitches/react": "^1.2.8",
|
||||||
|
"@tanstack/react-table": "^8.20.5",
|
||||||
"@tiptap/core": "^2.9.1",
|
"@tiptap/core": "^2.9.1",
|
||||||
"@tiptap/extension-code-block-lowlight": "^2.9.1",
|
"@tiptap/extension-code-block-lowlight": "^2.9.1",
|
||||||
"@tiptap/extension-collaboration": "^2.9.1",
|
"@tiptap/extension-collaboration": "^2.9.1",
|
||||||
|
|
|
||||||
34
apps/web/pnpm-lock.yaml
generated
34
apps/web/pnpm-lock.yaml
generated
|
|
@ -68,6 +68,9 @@ importers:
|
||||||
'@stitches/react':
|
'@stitches/react':
|
||||||
specifier: ^1.2.8
|
specifier: ^1.2.8
|
||||||
version: 1.2.8(react@18.3.1)
|
version: 1.2.8(react@18.3.1)
|
||||||
|
'@tanstack/react-table':
|
||||||
|
specifier: ^8.20.5
|
||||||
|
version: 8.20.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
'@tiptap/core':
|
'@tiptap/core':
|
||||||
specifier: ^2.9.1
|
specifier: ^2.9.1
|
||||||
version: 2.9.1(@tiptap/pm@2.9.1)
|
version: 2.9.1(@tiptap/pm@2.9.1)
|
||||||
|
|
@ -1539,6 +1542,17 @@ packages:
|
||||||
'@swc/helpers@0.5.5':
|
'@swc/helpers@0.5.5':
|
||||||
resolution: {integrity: sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==}
|
resolution: {integrity: sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==}
|
||||||
|
|
||||||
|
'@tanstack/react-table@8.20.5':
|
||||||
|
resolution: {integrity: sha512-WEHopKw3znbUZ61s9i0+i9g8drmDo6asTWbrQh8Us63DAk/M0FkmIqERew6P71HI75ksZ2Pxyuf4vvKh9rAkiA==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
peerDependencies:
|
||||||
|
react: '>=16.8'
|
||||||
|
react-dom: '>=16.8'
|
||||||
|
|
||||||
|
'@tanstack/table-core@8.20.5':
|
||||||
|
resolution: {integrity: sha512-P9dF7XbibHph2PFRz8gfBKEXEY/HJPOhym8CHmjF8y3q5mWpKx9xtZapXQUWCgkqvsK0R46Azuz+VaxD4Xl+Tg==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
'@tiptap/core@2.9.1':
|
'@tiptap/core@2.9.1':
|
||||||
resolution: {integrity: sha512-tifnLL/ARzQ6/FGEJjVwj9UT3v+pENdWHdk9x6F3X0mB1y0SeCjV21wpFLYESzwNdBPAj8NMp8Behv7dBnhIfw==}
|
resolution: {integrity: sha512-tifnLL/ARzQ6/FGEJjVwj9UT3v+pENdWHdk9x6F3X0mB1y0SeCjV21wpFLYESzwNdBPAj8NMp8Behv7dBnhIfw==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
|
@ -5523,6 +5537,14 @@ snapshots:
|
||||||
'@swc/counter': 0.1.3
|
'@swc/counter': 0.1.3
|
||||||
tslib: 2.8.0
|
tslib: 2.8.0
|
||||||
|
|
||||||
|
'@tanstack/react-table@8.20.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||||
|
dependencies:
|
||||||
|
'@tanstack/table-core': 8.20.5
|
||||||
|
react: 18.3.1
|
||||||
|
react-dom: 18.3.1(react@18.3.1)
|
||||||
|
|
||||||
|
'@tanstack/table-core@8.20.5': {}
|
||||||
|
|
||||||
'@tiptap/core@2.9.1(@tiptap/pm@2.9.1)':
|
'@tiptap/core@2.9.1(@tiptap/pm@2.9.1)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@tiptap/pm': 2.9.1
|
'@tiptap/pm': 2.9.1
|
||||||
|
|
@ -6486,7 +6508,7 @@ snapshots:
|
||||||
'@typescript-eslint/parser': 8.12.2(eslint@8.57.1)(typescript@5.4.4)
|
'@typescript-eslint/parser': 8.12.2(eslint@8.57.1)(typescript@5.4.4)
|
||||||
eslint: 8.57.1
|
eslint: 8.57.1
|
||||||
eslint-import-resolver-node: 0.3.9
|
eslint-import-resolver-node: 0.3.9
|
||||||
eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@8.12.2(eslint@8.57.1)(typescript@5.4.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.12.2(eslint@8.57.1)(typescript@5.4.4))(eslint@8.57.1))(eslint@8.57.1)
|
eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@8.12.2(eslint@8.57.1)(typescript@5.4.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@8.57.1)
|
||||||
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.12.2(eslint@8.57.1)(typescript@5.4.4))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1)
|
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.12.2(eslint@8.57.1)(typescript@5.4.4))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1)
|
||||||
eslint-plugin-jsx-a11y: 6.10.2(eslint@8.57.1)
|
eslint-plugin-jsx-a11y: 6.10.2(eslint@8.57.1)
|
||||||
eslint-plugin-react: 7.37.2(eslint@8.57.1)
|
eslint-plugin-react: 7.37.2(eslint@8.57.1)
|
||||||
|
|
@ -6506,13 +6528,13 @@ snapshots:
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.12.2(eslint@8.57.1)(typescript@5.4.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.12.2(eslint@8.57.1)(typescript@5.4.4))(eslint@8.57.1))(eslint@8.57.1):
|
eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.12.2(eslint@8.57.1)(typescript@5.4.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@8.57.1):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@nolyfill/is-core-module': 1.0.39
|
'@nolyfill/is-core-module': 1.0.39
|
||||||
debug: 4.3.7
|
debug: 4.3.7
|
||||||
enhanced-resolve: 5.17.1
|
enhanced-resolve: 5.17.1
|
||||||
eslint: 8.57.1
|
eslint: 8.57.1
|
||||||
eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.12.2(eslint@8.57.1)(typescript@5.4.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.12.2(eslint@8.57.1)(typescript@5.4.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.12.2(eslint@8.57.1)(typescript@5.4.4))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1)
|
eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.12.2(eslint@8.57.1)(typescript@5.4.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.12.2(eslint@8.57.1)(typescript@5.4.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1)
|
||||||
fast-glob: 3.3.2
|
fast-glob: 3.3.2
|
||||||
get-tsconfig: 4.8.1
|
get-tsconfig: 4.8.1
|
||||||
is-bun-module: 1.2.1
|
is-bun-module: 1.2.1
|
||||||
|
|
@ -6525,14 +6547,14 @@ snapshots:
|
||||||
- eslint-import-resolver-webpack
|
- eslint-import-resolver-webpack
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
eslint-module-utils@2.12.0(@typescript-eslint/parser@8.12.2(eslint@8.57.1)(typescript@5.4.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.12.2(eslint@8.57.1)(typescript@5.4.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.12.2(eslint@8.57.1)(typescript@5.4.4))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1):
|
eslint-module-utils@2.12.0(@typescript-eslint/parser@8.12.2(eslint@8.57.1)(typescript@5.4.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.12.2(eslint@8.57.1)(typescript@5.4.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1):
|
||||||
dependencies:
|
dependencies:
|
||||||
debug: 3.2.7
|
debug: 3.2.7
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@typescript-eslint/parser': 8.12.2(eslint@8.57.1)(typescript@5.4.4)
|
'@typescript-eslint/parser': 8.12.2(eslint@8.57.1)(typescript@5.4.4)
|
||||||
eslint: 8.57.1
|
eslint: 8.57.1
|
||||||
eslint-import-resolver-node: 0.3.9
|
eslint-import-resolver-node: 0.3.9
|
||||||
eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@8.12.2(eslint@8.57.1)(typescript@5.4.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.12.2(eslint@8.57.1)(typescript@5.4.4))(eslint@8.57.1))(eslint@8.57.1)
|
eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@8.12.2(eslint@8.57.1)(typescript@5.4.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@8.57.1)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
|
|
@ -6547,7 +6569,7 @@ snapshots:
|
||||||
doctrine: 2.1.0
|
doctrine: 2.1.0
|
||||||
eslint: 8.57.1
|
eslint: 8.57.1
|
||||||
eslint-import-resolver-node: 0.3.9
|
eslint-import-resolver-node: 0.3.9
|
||||||
eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.12.2(eslint@8.57.1)(typescript@5.4.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.12.2(eslint@8.57.1)(typescript@5.4.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.12.2(eslint@8.57.1)(typescript@5.4.4))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1)
|
eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.12.2(eslint@8.57.1)(typescript@5.4.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.12.2(eslint@8.57.1)(typescript@5.4.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1)
|
||||||
hasown: 2.0.2
|
hasown: 2.0.2
|
||||||
is-core-module: 2.15.1
|
is-core-module: 2.15.1
|
||||||
is-glob: 4.0.3
|
is-glob: 4.0.3
|
||||||
|
|
|
||||||
|
|
@ -45,3 +45,12 @@ export async function deletePaymentConfig(orgId: number, id: string, access_toke
|
||||||
const res = await errorHandling(result);
|
const res = await errorHandling(result);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getOrgCustomers(orgId: number, access_token: string) {
|
||||||
|
const result = await fetch(
|
||||||
|
`${getAPIUrl()}payments/${orgId}/customers`,
|
||||||
|
RequestBodyWithAuthHeader('GET', null, null, access_token)
|
||||||
|
);
|
||||||
|
const res = await errorHandling(result);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue