npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

em-crm-claim-module

v1.0.0

Published

A responsive React component module for managing claims - Add Claim and List Claims

Readme

em-crm-claim-module

A responsive React component module for managing claims - Add Claim and List Claims functionality extracted from em-crm project. The module handles all API calls internally, requiring only baseURL, token, and userData as inputs.

Features

  • Add Claim Component - Responsive form to create new claims
  • Claims List Component - Responsive table to view and manage claims
  • Internal API Handling - All API calls are handled within the package
  • Fully Responsive - Works seamlessly on mobile, tablet, and desktop
  • Material-UI Integration - Built with Material-UI v5
  • Auto-refresh - Claims list auto-refreshes at configurable intervals
  • TypeScript Ready - Can be used with TypeScript projects

Installation

npm install em-crm-claim-module

Peer Dependencies

Make sure you have these peer dependencies installed:

npm install react react-dom @mui/material @mui/icons-material @mui/x-date-pickers react-select@^5.0.0 moment react-hot-toast axios@^1.0.0 dayjs

Notes:

  • react-select version 5.x is required for React 18 compatibility. Version 4.x only supports React 16-17.
  • axios version 1.x is required for security. Versions < 1.0.0 have known vulnerabilities (CSRF, DoS, SSRF).

Quick Start

The module requires three essential inputs:

  • baseURL - Your API base URL
  • token - Authentication token
  • userData - User information object

Optional (recommended):

  • refreshToken - Refresh token for automatic token renewal
  • onTokenRefresh - Callback function to handle token refresh
import React from 'react';
import { ClaimProvider, AddClaim, ClaimsList } from 'em-crm-claim-module';
import { LocalizationProvider } from '@mui/x-date-pickers';
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
import { ThemeProvider, createTheme } from '@mui/material/styles';
import 'em-crm-claim-module/dist/index.css';

const theme = createTheme({
  palette: {
    primary: {
      main: '#f45e29',
    },
  },
});

function App() {
  const baseURL = 'https://api.example.com'; // Your API base URL
  const token = 'your-auth-token'; // Your authentication token
  const refreshToken = 'your-refresh-token'; // Optional: for automatic token refresh
  
  // Token refresh handler (optional but recommended)
  const handleTokenRefresh = async (refreshTokenValue) => {
    const response = await fetch(`${baseURL}/api/auth/refresh`, {
      method: 'POST',
      body: JSON.stringify({ refreshToken: refreshTokenValue }),
    });
    const data = await response.json();
    return data.token || data.accessToken;
  };
  
  const userData = {
    crm_role: 'EMPLOYEE',
    name: 'John Doe',
    crm_profile: 'SALES',
    employee_code: 'EMP001',
    username: 'johndoe',
    uuid: 'user-uuid-123',
  };

  return (
    <ThemeProvider theme={theme}>
      <LocalizationProvider dateAdapter={AdapterDayjs}>
        <ClaimProvider 
          baseURL={baseURL} 
          token={token} 
          refreshToken={refreshToken}
          onTokenRefresh={handleTokenRefresh}
          userData={userData}
        >
          {/* Your components */}
          <ClaimsList />
        </ClaimProvider>
      </LocalizationProvider>
    </ThemeProvider>
  );
}

Usage

Basic Setup

Wrap your application with ClaimProvider and provide the required props:

import { ClaimProvider, AddClaim, ClaimsList } from 'em-crm-claim-module';
import axios from 'axios';

function App() {
  const baseURL = 'https://api.example.com';
  const token = localStorage.getItem('authToken');
  const refreshToken = localStorage.getItem('refreshToken');
  
  // Token refresh handler
  const handleTokenRefresh = async (refreshTokenValue) => {
    try {
      const response = await axios.post(`${baseURL}/api/auth/refresh`, {
        refreshToken: refreshTokenValue,
      });
      const newToken = response.data?.token || response.data?.accessToken;
      if (newToken) {
        localStorage.setItem('authToken', newToken);
        return newToken;
      }
    } catch (error) {
      // Handle refresh failure (e.g., redirect to login)
      console.error('Token refresh failed:', error);
      throw error;
    }
  };

  return (
    <ClaimProvider
      baseURL={baseURL}
      token={token}
      refreshToken={refreshToken}
      onTokenRefresh={handleTokenRefresh}
      userData={{
        crm_role: 'EMPLOYEE',
        name: 'John Doe',
        crm_profile: 'SALES',
        employee_code: 'EMP001',
        username: 'johndoe',
        uuid: 'user-uuid-123',
      }}
    >
      <ClaimsList />
    </ClaimProvider>
  );
}

AddClaim Component

import { ClaimProvider, AddClaim } from 'em-crm-claim-module';

function AddClaimPage() {
  const [view, setView] = useState('list');

  return (
    <ClaimProvider baseURL={baseURL} token={token} userData={userData}>
      <AddClaim
        onSuccess={(data) => {
          console.log('Claim created:', data);
          setView('list'); // Navigate back to list
        }}
        onCancel={() => setView('list')}
      />
    </ClaimProvider>
  );
}

ClaimsList Component

import { ClaimProvider, ClaimsList } from 'em-crm-claim-module';

function ClaimsListPage() {
  const [view, setView] = useState('list');

  return (
    <ClaimProvider baseURL={baseURL} token={token} userData={userData}>
      <ClaimsList
        onAddClaim={() => setView('add')}
        onRefresh={() => {
          console.log('Claims refreshed');
        }}
        autoRefresh={true}
        refreshInterval={30000} // Refresh every 30 seconds
      />
    </ClaimProvider>
  );
}

Complete Example with Navigation and Refresh Token

import React, { useState } from 'react';
import { ClaimProvider, AddClaim, ClaimsList } from 'em-crm-claim-module';
import { LocalizationProvider } from '@mui/x-date-pickers';
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
import axios from 'axios';

function ClaimModule() {
  const [view, setView] = useState('list'); // 'list' or 'add'
  
  const baseURL = process.env.REACT_APP_API_URL || 'https://api.example.com';
  const token = localStorage.getItem('authToken');
  const refreshToken = localStorage.getItem('refreshToken');
  
  // Token refresh handler
  const handleTokenRefresh = async (refreshTokenValue) => {
    try {
      const response = await axios.post(`${baseURL}/api/auth/refresh`, {
        refreshToken: refreshTokenValue,
      });
      const newToken = response.data?.token || response.data?.accessToken;
      if (newToken) {
        localStorage.setItem('authToken', newToken);
        // Update refresh token if provided
        if (response.data?.refreshToken) {
          localStorage.setItem('refreshToken', response.data.refreshToken);
        }
        return newToken;
      }
      throw new Error('No token received');
    } catch (error) {
      console.error('Token refresh failed:', error);
      // Redirect to login on refresh failure
      // window.location.href = '/login';
      throw error;
    }
  };
  
  const userData = {
    crm_role: 'EMPLOYEE',
    name: 'John Doe',
    crm_profile: 'SALES',
    employee_code: 'EMP001',
    username: 'johndoe',
    uuid: 'user-uuid-123',
  };

  return (
    <LocalizationProvider dateAdapter={AdapterDayjs}>
      <ClaimProvider 
        baseURL={baseURL} 
        token={token} 
        refreshToken={refreshToken}
        onTokenRefresh={handleTokenRefresh}
        userData={userData}
      >
        {view === 'add' ? (
          <AddClaim
            onSuccess={() => setView('list')}
            onCancel={() => setView('list')}
          />
        ) : (
          <ClaimsList
            onAddClaim={() => setView('add')}
          />
        )}
      </ClaimProvider>
    </LocalizationProvider>
  );
}

Refresh Token Handling

The module supports automatic token refresh when API calls receive a 401 (Unauthorized) response. There are two ways to handle token refresh:

Option 1: Custom Refresh Handler (Recommended)

Provide a callback function that handles the token refresh:

const handleTokenRefresh = async (refreshTokenValue) => {
  const response = await fetch(`${baseURL}/api/auth/refresh`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ refreshToken: refreshTokenValue }),
  });
  const data = await response.json();
  return data.token || data.accessToken;
};

<ClaimProvider
  baseURL={baseURL}
  token={token}
  refreshToken={refreshToken}
  onTokenRefresh={handleTokenRefresh}
  userData={userData}
>
  {/* ... */}
</ClaimProvider>

Option 2: Automatic Refresh

Set onTokenRefresh to 'auto' to use the standard endpoint /api/auth/refresh:

<ClaimProvider
  baseURL={baseURL}
  token={token}
  refreshToken={refreshToken}
  onTokenRefresh="auto"
  userData={userData}
>
  {/* ... */}
</ClaimProvider>

How it works:

  • When any API call receives a 401 response, the module automatically attempts to refresh the token
  • All pending requests are queued and retried after a successful token refresh
  • If token refresh fails, all queued requests are rejected and an error is shown
  • The new token is automatically updated in the API service

Props

ClaimProvider Props

| Prop | Type | Required | Description | |------|------|----------|-------------| | baseURL | string | Yes | Base URL for API calls (e.g., 'https://api.example.com') | | token | string | Yes | Authentication token for API requests | | userData | object | Yes | User data object (see UserData structure below) | | refreshToken | string | No | Refresh token for automatic token renewal | | onTokenRefresh | function \| string | No | Callback function to refresh token, or 'auto' for automatic refresh using /api/auth/refresh endpoint | | children | ReactNode | Yes | React children components |

AddClaim Props

| Prop | Type | Required | Description | |------|------|----------|-------------| | onSuccess | function | No | Callback function called when claim is successfully created | | onCancel | function | No | Callback function called when cancel button is clicked | | visitOptions | array | No | Custom visit purpose options |

ClaimsList Props

| Prop | Type | Required | Description | |------|------|----------|-------------| | onAddClaim | function | No | Callback function called when Add Claim button is clicked | | onRefresh | function | No | Callback function called after claims are refreshed | | columns | array | No | Custom column configuration | | autoRefresh | boolean | No | Enable auto-refresh (default: true) | | refreshInterval | number | No | Auto-refresh interval in milliseconds (default: 30000) |

Data Structures

UserData Object

{
  crm_role: 'EMPLOYEE',           // User's role
  name: 'John Doe',               // User's name
  crm_profile: 'SALES',            // User's profile
  employee_code: 'EMP001',        // Employee code
  username: 'johndoe',            // Username
  uuid: 'user-uuid-123',          // User UUID
  // Optional fields:
  roleId: 'EMPLOYEE',             // Alternative role ID
  profileName: 'SALES',            // Alternative profile name
  empCode: 'EMP001',               // Alternative employee code
}

Claim Object Structure

The API should return claim objects with the following structure:

{
  _id: 'claim-id',
  claimId: 'CLM001',
  requestBy_name: 'John Doe',
  schoolName: 'ABC School',
  expenseType: 'Food',
  claimStatus: 'PENDING AT BUH',
  createdAt: '2024-01-01T00:00:00Z',
  approvedDate: '2024-01-02T00:00:00Z',
  claimAmount: 1000,
  approvedAmount: 950
}

API Endpoints

The module expects the following API endpoints:

  • POST /api/userClaim/createMyClaim - Create a new claim
  • POST /api/userClaim/getMyClaimList - Get list of claims
  • PUT /api/userClaim/bulkDelete - Delete multiple claims
  • GET /api/claimMaster/getClaimMasterList - Get claim master list
  • GET /api/school/getSchoolCodeList - Search schools

All endpoints should:

  • Accept Bearer token authentication in the Authorization header
  • Return data in the format: { result: [...], message: '...' }

Responsive Design

Both components are fully responsive and adapt to different screen sizes:

  • Mobile (< 768px): Stacked layout, optimized for touch interactions
  • Tablet (768px - 1024px): Balanced layout with some columns hidden
  • Desktop (> 1024px): Full layout with all columns visible

Styling

The components use Material-UI's theming system. You can customize the appearance by wrapping your app with a Material-UI ThemeProvider:

import { ThemeProvider, createTheme } from '@mui/material/styles';

const theme = createTheme({
  palette: {
    primary: {
      main: '#f45e29',
    },
  },
});

function App() {
  return (
    <ThemeProvider theme={theme}>
      {/* Your components */}
    </ThemeProvider>
  );
}

Error Handling

The module handles errors internally and displays toast notifications using react-hot-toast. Common errors:

  • 401 Unauthorized: Token is invalid or expired - automatically triggers token refresh if refreshToken and onTokenRefresh are provided
  • Network errors: Connection issues are displayed to the user
  • Validation errors: Form validation errors are shown inline
  • Token refresh failures: If token refresh fails, a toast notification is shown and you can handle redirect to login in your onTokenRefresh callback

License

ISC

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.