@msflib/react-support¶
Multi-Tenant Support module built on TanStack Query, following the same approach as other @msflib/react-* modules.
Install¶
pnpm add @msflib/core @msflib/react-support
Peer dependencies¶
- react >= 18
- @tanstack/react-query >= 5
Wrap your app with SupportProvider inside your QueryClientProvider.
API Reference¶
SupportProvider¶
A React context provider that manages support tickets and categories for the current user and workspace.
import { SupportProvider } from '@msflib/react-support';
<QueryClientProvider client={queryClient}>
<SupportProvider>{/* your app */}</SupportProvider>
</QueryClientProvider>;
Props
| Prop | Type | Required | Description |
|---|---|---|---|
children |
React.ReactNode |
Yes | Child component tree. |
options |
object |
No | Configuration options for the provider. See below for details. |
options Configuration¶
| Key | Type | Default | Description |
|---|---|---|---|
isWorkspaceScoped |
boolean |
true |
If true, support tickets are isolated per workspace. |
requireAuth |
boolean |
false |
If true, data will only be fetched when isAuthenticated is true. |
isAuthenticated |
boolean |
false |
The authentication status of the user (e.g. from useAuth().status). |
In Next.js App Router, SupportProvider must be in a client component (
"use client").
'use client';
import React from 'react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { SupportProvider } from '@msflib/react-support';
const qc = new QueryClient();
export default function Providers({ children }: { children: React.ReactNode }) {
return (
<QueryClientProvider client={qc}>
<SupportProvider options={{ isWorkspaceScoped: true }}>{children}</SupportProvider>
</QueryClientProvider>
);
}
Multi-Tenancy¶
This module supports multi-tenancy using the options.isWorkspaceScoped setting and the useActiveWorkspace hook from @msflib/react-shared. All API calls are automatically scoped to the current workspace if isWorkspaceScoped is true (default).
Configuration¶
Configure the support endpoints using the configureApplication function:
import { configureApplication } from '@msflib/core';
configureApplication({
baseURL: process.env.NEXT_PUBLIC_API_URL!,
accessTokenKey: 'access_token',
endpoints: {
support: {
support: '/support', // default
},
},
});
API & Hook Methods¶
list¶
Fetches all support issues for the current workspace from /support (GET) on mount.
getIssue¶
Synchronous local lookup by issue id from the cached list. Returns undefined if not found.
const issue = getIssue('abc-123');
createIssue¶
Creates a new support issue (POST).
Payload:
{
title: string;
category: string; // e.g. 'general'
message: string;
}
refetch¶
Manually refetch the issues list.
Hook Usage¶
import { useSupport } from '@msflib/react-support';
function SupportPage() {
const { issues, getIssue, createIssue, refetch, loading } = useSupport();
if (loading.issues) return <div>Loading...</div>;
const handleSubmit = async () => {
await createIssue({
title: 'Cannot access dashboard',
category: 'general',
message: 'I get a 403 error when visiting /dashboard.',
});
};
return (
<div>
<button onClick={handleSubmit} disabled={loading.create}>
Submit Issue
</button>
<ul>
{issues.map((issue) => (
<li key={issue.id}>
[{issue.status}] {issue.title}
</li>
))}
</ul>
</div>
);
}
Returned Hook Shape¶
const {
issues,
getIssue,
createIssue,
refetch,
loading,
} = useSupport();
// Shape:
{
issues: SupportIssue[];
getIssue: (id: string) => SupportIssue | undefined;
createIssue: (data: CreateSupportPayload, options?: MutateOptions) => Promise<SupportIssue>;
refetch: () => void;
loading: {
issues: boolean;
create: boolean;
};
}
Types¶
export type SupportIssue = {
id: string;
title: string;
category: string;
message: string;
created_at: string;
status: 'pending' | string;
};
export type CreateSupportPayload = {
title: string;
category: string;
message: string;
};
Notes¶
SupportProvidermust be rendered in a client component in Next.js ("use client").- The issues query is cached for 60 seconds by default.
- All API calls are workspace-aware if
isWorkspaceScopedis true (default). getIssueperforms a local cache lookup — it does not fire a network request.