@cardql/react
TypeScript icon, indicating that this package has built-in type declarations

1.0.1 • Public • Published

@cardql/react

CardQL SDK for React web applications with hooks, context providers, and pre-built components.

Installation

npm install @cardql/react
# or
yarn add @cardql/react
# or
pnpm add @cardql/react

Quick Start

1. Setup Provider

Wrap your app with the CardQL provider:

import React from "react";
import { CardQLProvider } from "@cardql/react";

function App() {
  return (
    <CardQLProvider
      config={{
        apiKey: "your-api-key",
        endpoint: "https://api.cardql.com/graphql",
      }}>
      <YourApp />
    </CardQLProvider>
  );
}

2. Use Hooks

Use CardQL hooks in your components:

import React from "react";
import { usePayments, useCreatePayment } from "@cardql/react";

function PaymentList() {
  const { data: paymentsData, loading, error } = usePayments();
  const createPayment = useCreatePayment({
    onSuccess: (data) => {
      console.log("Payment created:", data.createPayment);
    },
  });

  const handleCreatePayment = async () => {
    await createPayment.mutateAsync({
      amount: "10.00",
      currency: "USD",
      merchantID: "merchant_123",
      userID: "user_456",
    });
  };

  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error.message}</div>;

  return (
    <div>
      <h2>Payments</h2>
      <button onClick={handleCreatePayment} disabled={createPayment.loading}>
        {createPayment.loading ? "Creating..." : "Create Payment"}
      </button>

      {paymentsData?.payments.map((payment) => (
        <div key={payment.id}>
          {payment.amount} {payment.currency} - {payment.status}
        </div>
      ))}
    </div>
  );
}

3. Use Pre-built Components

Use ready-made components:

import React from "react";
import { PaymentForm } from "@cardql/react";

function CheckoutPage() {
  return (
    <div>
      <h1>Checkout</h1>
      <PaymentForm
        merchantID="merchant_123"
        userID="user_456"
        onSuccess={(payment) => {
          console.log("Payment successful:", payment);
          // Redirect to success page
        }}
        onError={(error) => {
          console.error("Payment failed:", error);
          // Show error message
        }}
      />
    </div>
  );
}

API Reference

Provider

CardQLProvider

interface CardQLProviderProps {
  config: CardQLConfig;
  children: ReactNode;
}

<CardQLProvider config={{ apiKey: "...", endpoint: "..." }}>
  <App />
</CardQLProvider>;

Context Hooks

useCardQL()

Access the CardQL context:

const { cardql, config } = useCardQL();

useCardQLClient()

Get the CardQL client directly:

const cardql = useCardQLClient();

useCardQLApi()

Get the CardQL API directly:

const api = useCardQLApi();

Data Fetching Hooks

useQuery()

Generic hook for GraphQL queries:

const { data, loading, error, refetch } = useQuery(
  "query GetPayments { payments { id amount status } }",
  variables,
  {
    enabled: true,
    refetchOnMount: true,
    refetchInterval: 30000,
    onSuccess: (data) => console.log(data),
    onError: (error) => console.error(error),
  }
);

useMutation()

Generic hook for GraphQL mutations:

const { data, loading, error, mutate, mutateAsync } = useMutation(
  "mutation CreatePayment($input: CreatePaymentInput!) { createPayment(input: $input) { id } }",
  {
    onSuccess: (data, variables) => console.log("Success:", data),
    onError: (error, variables) => console.error("Error:", error),
    onSettled: (data, error, variables) => console.log("Settled"),
  }
);

Entity-Specific Hooks

Account Hooks

// Query hooks
const { data, loading, error } = useAccounts();
const { data, loading, error } = useAccount(accountID);

// Mutation hooks
const createAccount = useCreateAccount();
const updateAccount = useUpdateAccount();
const deleteAccount = useDeleteAccount();

Customer Hooks

// Query hooks
const { data, loading, error } = useCustomers();
const { data, loading, error } = useCustomer(customerID);

// Mutation hooks
const createCustomer = useCreateCustomer({
  onSuccess: (data) => {
    console.log("Customer created:", data.createCustomer);
  },
});

// Usage
await createCustomer.mutateAsync({
  firstName: "John",
  lastName: "Doe",
  email: "john@example.com",
});

Payment Hooks

// Query hooks
const { data, loading, error } = usePayments();
const { data, loading, error } = usePayment(paymentID);

// Mutation hooks
const createPayment = useCreatePayment();
const updatePayment = useUpdatePayment();
const deletePayment = useDeletePayment();

// Usage
const handlePayment = async () => {
  try {
    const result = await createPayment.mutateAsync({
      amount: "25.99",
      currency: "USD",
      merchantID: "merchant_123",
      userID: "user_456",
      description: "Product purchase",
    });
    console.log("Payment created:", result.createPayment);
  } catch (error) {
    console.error("Payment failed:", error);
  }
};

Merchant Hooks

const { data, loading, error } = useMerchants();
const { data, loading, error } = useMerchant(merchantID);

const createMerchant = useCreateMerchant();
const updateMerchant = useUpdateMerchant();
const deleteMerchant = useDeleteMerchant();

Ledger Hooks

const { data, loading, error } = useLedgers();
const { data, loading, error } = useLedger(ledgerID);

const createLedger = useCreateLedger();
const updateLedger = useUpdateLedger();
const deleteLedger = useDeleteLedger();

Components

PaymentForm

Pre-built payment form component:

<PaymentForm
  merchantID="merchant_123"
  userID="user_456"
  onSuccess={(payment) => {
    // Handle successful payment
    router.push("/success");
  }}
  onError={(error) => {
    // Handle payment error
    setErrorMessage(error.message);
  }}
  className="custom-payment-form"
  disabled={false}
/>

Advanced Usage

Custom Queries

Execute custom GraphQL queries:

import { useQuery } from "@cardql/react";

function CustomPaymentList() {
  const { data, loading, error } = useQuery(
    `
    query GetPaymentsByMerchant($merchantID: String!) {
      payments(where: { merchantID: $merchantID }) {
        id
        amount
        currency
        status
        customer {
          firstName
          lastName
        }
      }
    }
  `,
    {
      merchantID: "merchant_123",
    }
  );

  // ... render logic
}

Polling and Real-time Updates

// Poll every 30 seconds
const { data } = usePayments({
  refetchInterval: 30000,
});

// Manual refetch
const { data, refetch } = usePayments();

const handleRefresh = () => {
  refetch();
};

Error Handling

import { usePayments, useCreatePayment } from "@cardql/react";

function PaymentComponent() {
  const { data, loading, error } = usePayments({
    onError: (error) => {
      console.error("Failed to load payments:", error);
      // Send to error tracking service
    },
  });

  const createPayment = useCreatePayment({
    onError: (error, variables) => {
      console.error("Payment creation failed:", error);
      // Show user-friendly error message
      if (error.code === "INSUFFICIENT_FUNDS") {
        alert("Insufficient funds");
      } else {
        alert("Payment failed. Please try again.");
      }
    },
  });

  // ... component logic
}

Loading States

function PaymentList() {
  const { data, loading, error } = usePayments();
  const createPayment = useCreatePayment();

  if (loading) {
    return <PaymentSkeleton />;
  }

  if (error) {
    return <ErrorMessage error={error} />;
  }

  return (
    <div>
      <button
        onClick={() => createPayment.mutate(paymentData)}
        disabled={createPayment.loading}>
        {createPayment.loading ? <Spinner /> : "Create Payment"}
      </button>

      {/* Payment list */}
    </div>
  );
}

Form Integration

import { useForm } from "react-hook-form";
import { useCreateCustomer } from "@cardql/react";

function CustomerForm() {
  const { register, handleSubmit, reset } = useForm();
  const createCustomer = useCreateCustomer({
    onSuccess: () => {
      reset(); // Clear form on success
    },
  });

  const onSubmit = async (data) => {
    await createCustomer.mutateAsync(data);
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input {...register("firstName")} placeholder="First Name" />
      <input {...register("lastName")} placeholder="Last Name" />
      <input {...register("email")} placeholder="Email" />

      <button type="submit" disabled={createCustomer.loading}>
        {createCustomer.loading ? "Creating..." : "Create Customer"}
      </button>
    </form>
  );
}

TypeScript Support

The React SDK is fully typed:

import type { Payment, CreatePaymentInput } from "@cardql/react";

const createPayment = useCreatePayment();

// TypeScript knows the exact shape of the data
const handleSubmit = async (input: CreatePaymentInput) => {
  const result = await createPayment.mutateAsync(input);
  // result.createPayment is typed as Payment
  console.log(result.createPayment.id);
};

Styling

The pre-built components use CSS classes that you can style:

.cardql-payment-form {
  max-width: 400px;
  padding: 20px;
  border: 1px solid #ddd;
  border-radius: 8px;
}

.cardql-form-field {
  margin-bottom: 16px;
}

.cardql-form-field label {
  display: block;
  margin-bottom: 4px;
  font-weight: 500;
}

.cardql-form-field input,
.cardql-form-field select {
  width: 100%;
  padding: 8px 12px;
  border: 1px solid #ccc;
  border-radius: 4px;
}

.cardql-error {
  color: #dc3545;
  margin-bottom: 16px;
  padding: 8px;
  background-color: #f8d7da;
  border-radius: 4px;
}

.cardql-submit-button {
  width: 100%;
  padding: 12px;
  background-color: #007bff;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

.cardql-submit-button:disabled {
  background-color: #6c757d;
  cursor: not-allowed;
}

Best Practices

1. Provider Placement

Place the CardQL provider at the highest level where you need CardQL functionality:

// ✅ Good - wrap entire app
function App() {
  return (
    <CardQLProvider config={config}>
      <Router>
        <Routes>
          <Route path="/payments" component={PaymentPage} />
          <Route path="/customers" component={CustomerPage} />
        </Routes>
      </Router>
    </CardQLProvider>
  );
}

2. Error Boundaries

Use error boundaries to catch and handle errors:

import { ErrorBoundary } from "react-error-boundary";

function ErrorFallback({ error, resetErrorBoundary }) {
  return (
    <div role="alert">
      <h2>Something went wrong:</h2>
      <pre>{error.message}</pre>
      <button onClick={resetErrorBoundary}>Try again</button>
    </div>
  );
}

function App() {
  return (
    <CardQLProvider config={config}>
      <ErrorBoundary FallbackComponent={ErrorFallback}>
        <YourApp />
      </ErrorBoundary>
    </CardQLProvider>
  );
}

3. Loading States

Always handle loading states for better UX:

function PaymentList() {
  const { data, loading, error } = usePayments();

  if (loading) return <PaymentSkeleton />;
  if (error) return <ErrorMessage error={error} />;
  if (!data?.payments.length) return <EmptyState />;

  return <PaymentGrid payments={data.payments} />;
}

License

MIT

Support

For support, please contact the CardQL team or visit our documentation.

Package Sidebar

Install

npm i @cardql/react

Weekly Downloads

2

Version

1.0.1

License

MIT

Unpacked Size

75.7 kB

Total Files

12

Last publish

Collaborators

  • andrejs1979