@adhix11/clientdesk-react
v1.0.0
Published
A client-facing React SDK for SaaS products to collect support tickets, bug reports, service requests, and change management requests with user context, attachments, and configurable API endpoints.
Maintainers
Readme
@adhix11/clientdesk-react
A client-facing React SDK for SaaS products to collect support tickets, bug reports, service requests, and change management requests with user context, attachments, and configurable API endpoints.
What is ClientDesk React?
ClientDesk React is a client-facing ticket and change request submission SDK — not a full ticketing system.
It lets SaaS products add a polished, branded reporting widget so users can:
- 🐛 Report bugs and issues
- 🎫 Raise support tickets
- 🔄 Request feature/workflow/configuration changes
- 📎 Upload screenshots and file attachments
Your SDK captures rich user context (browser, device, page URL, timezone) automatically and sends everything as structured data to your own API.
Important: This SDK does not manage admin workflows, assignment, SLA, internal comments, escalation, or approvals. It only captures and submits structured client requests.
Installation
npm install @adhix11/clientdesk-reactPeer dependencies: react >= 17, react-dom >= 17
Quick Start
Both Ticketing + Change Requests
import { ClientDeskProvider, ClientRequestWidget } from "@adhix11/clientdesk-react";
function App() {
return (
<ClientDeskProvider
config={{
apiUrl: "https://api.your-saas.com",
clientKey: "public_client_key",
mode: "both",
}}
>
<ClientRequestWidget />
</ClientDeskProvider>
);
}Ticketing Only
import { ClientDeskProvider, TicketReporter } from "@adhix11/clientdesk-react";
function App() {
return (
<ClientDeskProvider
config={{
apiUrl: "https://api.example.com",
clientKey: "client_key",
mode: "ticket",
}}
>
<TicketReporter />
</ClientDeskProvider>
);
}Change Management Only
import { ClientDeskProvider, ChangeRequestReporter } from "@adhix11/clientdesk-react";
function App() {
return (
<ClientDeskProvider
config={{
apiUrl: "https://api.example.com",
clientKey: "client_key",
mode: "change",
}}
>
<ChangeRequestReporter />
</ClientDeskProvider>
);
}Components
| Component | Purpose |
|-----------|---------|
| <ClientDeskProvider /> | Global config: API URL, key, user, theme |
| <ClientRequestWidget /> | Floating button/modal with ticket + change options |
| <TicketReporter /> | Ticket submission form |
| <ChangeRequestReporter /> | Change request submission form |
| <MyRequests /> | Client-side list of user's own submitted requests |
| <AttachmentUploader /> | Image/file upload helper |
Component API
<ClientDeskProvider />
Wrap your app or a subtree with this provider.
<ClientDeskProvider
config={{
apiUrl: "https://api.example.com", // Required
clientKey: "public_client_key", // Required
mode: "both", // "ticket" | "change" | "both"
endpoints: { // Custom API paths
createTicket: "/client/tickets",
createChangeRequest: "/client/change-requests",
uploadAttachment: "/client/attachments",
listMyRequests: "/client/requests/me",
},
user: { // User info
id: "user_123",
name: "John Doe",
email: "[email protected]",
companyId: "company_456",
role: "Manager",
},
theme: { // Theme customization
primaryColor: "#6366f1",
accentColor: "#8b5cf6",
mode: "light", // "light" | "dark"
borderRadius: 12,
},
getAuthToken: () => localStorage.getItem("token"),
appName: "MyApp",
appVersion: "2.1.0",
environment: "production",
}}
>
{children}
</ClientDeskProvider><ClientRequestWidget />
Floating action button with a modal menu.
<ClientRequestWidget
position="bottom-right" // "bottom-right" | "bottom-left" | "top-right" | "top-left"
ticketCustomFields={[...]} // Custom fields for ticket form
changeCustomFields={[...]} // Custom fields for change form
onSuccess={(data) => console.log(data)}
onError={(err) => console.error(err)}
/><TicketReporter />
// Inline
<TicketReporter />
// Button trigger (opens modal)
<TicketReporter trigger="button" buttonText="Report Issue" />
// With custom fields
<TicketReporter
customFields={[
{ name: "assetId", label: "Asset ID", type: "text" },
{ name: "location", label: "Location", type: "select", options: ["Chennai", "Salem", "Bangalore"] },
]}
onSuccess={(data) => console.log(data)}
/><ChangeRequestReporter />
// Inline
<ChangeRequestReporter />
// Button trigger
<ChangeRequestReporter trigger="button" buttonText="Request Change" /><MyRequests />
<MyRequests
limit={10}
onRequestClick={(request) => console.log(request)}
/><AttachmentUploader />
const [files, setFiles] = useState([]);
<AttachmentUploader
files={files}
onChange={setFiles}
maxFileSize={10 * 1024 * 1024} // 10MB
maxFiles={5}
/>Custom Fields
Every SaaS product has different needs. Add custom fields to any form:
<TicketReporter
customFields={[
{ name: "assetId", label: "Asset ID", type: "text", required: true },
{ name: "location", label: "Location", type: "select", options: ["Chennai", "Salem", "Bangalore"] },
{ name: "tags", label: "Tags", type: "multi-select", options: ["Urgent", "Frontend", "Backend", "Data"] },
{ name: "deadline", label: "Deadline", type: "date" },
{ name: "count", label: "Affected Users", type: "number" },
{ name: "critical", label: "Is Critical?", type: "checkbox" },
{ name: "env", label: "Environment", type: "radio", options: ["Production", "Staging", "Dev"] },
{ name: "notes", label: "Additional Notes", type: "textarea" },
{ name: "logFile", label: "Log File", type: "file" },
]}
/>Supported types: text, textarea, select, multi-select, date, number, checkbox, radio, file
Auto-Captured Context
Every submission automatically includes:
| Field | Source |
|-------|--------|
| Page URL | window.location.href |
| Browser | User agent parsing |
| Browser Version | User agent parsing |
| Operating System | User agent parsing |
| Device Type | User agent parsing |
| Screen Size | window.innerWidth/Height |
| Timezone | Intl.DateTimeFormat |
| Timestamp | new Date().toISOString() |
| Language | navigator.language |
| App Name | Config |
| App Version | Config |
| Module Name | Config |
| Environment | Config |
API Configuration
Endpoints are fully configurable — works with any REST backend:
<ClientDeskProvider
config={{
apiUrl: "https://api.example.com",
clientKey: "public_client_key",
endpoints: {
createTicket: "/client/tickets",
createChangeRequest: "/client/change-requests",
uploadAttachment: "/client/attachments",
listMyRequests: "/client/requests/me",
},
}}
>Compatible with: LoopBack 4, Express, NestJS, Laravel, Django, Spring Boot, or any REST API.
Authentication
The clientKey is a public project/client identifier (not a secret). For secure apps, inject auth tokens:
// Dynamic token
<ClientDeskProvider
config={{
apiUrl: "https://api.example.com",
clientKey: "public_client_key",
getAuthToken: () => localStorage.getItem("token"),
}}
>
// Static headers
<ClientDeskProvider
config={{
apiUrl: "https://api.example.com",
clientKey: "public_client_key",
headers: {
Authorization: "Bearer your_token_here",
},
}}
>The backend should verify the real user/session. The frontend key only identifies the SaaS client/project.
Theme Customization
<ClientDeskProvider
config={{
...config,
theme: {
primaryColor: "#6366f1",
accentColor: "#8b5cf6",
backgroundColor: "#f8fafc",
surfaceColor: "#ffffff",
textColor: "#0f172a",
mutedColor: "#64748b",
borderColor: "#e2e8f0",
successColor: "#10b981",
errorColor: "#ef4444",
warningColor: "#f59e0b",
fontFamily: "'Inter', sans-serif",
borderRadius: 12,
mode: "dark", // "light" | "dark"
},
}}
>Ticket Form Fields
| Field | Type | |-------|------| | Subject | text (required) | | Description | textarea (required) | | Issue Type | select: Bug, Support, Access Issue, Performance Issue, Data Issue, Payment Issue, Other | | Category/Module | text | | Priority | select: Low, Medium, High, Critical | | Severity | select: Minor, Major, Critical, Blocker | | Steps to Reproduce | textarea | | Expected Result | textarea | | Actual Result | textarea | | Attachments | file upload |
Change Request Form Fields
| Field | Type | |-------|------| | Change Title | text (required) | | Description | textarea (required) | | Change Type | select: Feature, Configuration, Workflow, Report, User Access, Data, Integration, Other | | Business Reason | textarea (required) | | Affected Module | text | | Expected Outcome | textarea | | Urgency | select: Low, Medium, High, Critical | | Impact Level | select: Low, Medium, High, Enterprise-Wide | | Preferred Date | date | | Attachments | file upload |
UI Modes
// Floating widget (default)
<ClientRequestWidget position="bottom-right" />
// Inline form
<TicketReporter />
// Modal button
<TicketReporter trigger="button" buttonText="Report Issue" />Hook: useClientDesk
Access config, theme, and API client programmatically:
import { useClientDesk } from "@adhix11/clientdesk-react";
function MyComponent() {
const { config, theme, apiClient } = useClientDesk();
// ...
}TypeScript
Fully typed. Import any type you need:
import type {
ClientDeskConfig,
TicketFormData,
ChangeRequestFormData,
CustomField,
CapturedContext,
ApiResponse,
} from "@adhix11/clientdesk-react";License
MIT © adhix11
