FoodEase
Hooks

useNumformatter

Hook for formatting numbers with currency and ordinal notation support

Overview

useNumformatter is a custom hook that provides a number formatting function with built-in support for currency display, ordinal notation, and decimal formatting. It wraps the formatNumber and formatOrdinal utilities with additional features like currency symbols. By deafult it formats numbers with the Nigerian Naira (₦) symbol, but it can be configured to use any currency prefix eg say with global state or local storage or api calls

Installation

npx shadcn@latest add https://foodease-dev-registry.cap.reachcinema.io/r/v1/use-numformatter.json

Usage

Basic Usage

import useNumformatter from "@/hooks/useNumformatter"

export default function PriceDisplay() {
  const { formatNum } = useNumformatter()

  return (
    <div>
      <p>{formatNum({ number: 1234.56 })}</p>
      {/* Output: ₦1,234.56 */}
    </div>
  )
}

Format as Currency

import useNumformatter from "@/hooks/useNumformatter"

export default function Product({ price }: { price: number }) {
  const { formatNum } = useNumformatter()

  return (
    <div className="product-card">
      <h3>Product Name</h3>
      <p className="price">
        {formatNum({ number: price, asCurrency: true })}
      </p>
    </div>
  )
}

Format as Ordinal

import useNumformatter from "@/hooks/useNumformatter"

export default function Metrics() {
  const { formatNum } = useNumformatter()

  return (
    <div>
      <p>Users: {formatNum({ number: 1500000, asOrdinal: true, asCurrency:false })}</p>
      {/* Output: 2M */}
      
      <p>Views: {formatNum({ number: 2500, asOrdinal: true, asCurrency:false })}</p>
      {/* Output: 3K */}
    </div>
  )
}

Custom Prefix

import useNumformatter from "@/hooks/useNumformatter"

export default function MultiCurrency() {
  const { formatNum } = useNumformatter()

  return (
    <div>
      <p>{formatNum({ number: 100, prefix: "$",asCurrency:false })}</p>
      {/* Output: $100.00 */}
    </div>
  )
}

API Reference

useNumformatter

const { formatNum } = useNumformatter()

Returns:

PropertyTypeDescription
formatNum(config: Config) => stringFunction to format numbers

formatNum Config

interface Config {
  number: number | string       // The value to format
  asCurrency?: boolean          // Add currency symbol (₦)
  prefix?: string               // Custom prefix, to make it override default currency, pass asCurrency: false 
  asOrdinal?: boolean           // Format as K/M/G/T/P/E
  forceDecimal?: boolean        // Always show decimal places
}

Examples

Price List

import useNumformatter from "@/hooks/useNumformatter"

export default function PriceList({ items }) {
  const { formatNum } = useNumformatter()

  return (
    <ul>
      {items.map(item => (
        <li key={item.id}>
          <span>{item.name}</span>
          <span>{formatNum({ number: item.price })}</span>
        </li>
      ))}
    </ul>
  )
}

Dashboard Stats

import useNumformatter from "@/hooks/useNumformatter"

export default function Dashboard({ stats }) {
  const { formatNum } = useNumformatter()

  return (
    <div className="grid grid-cols-3 gap-4">
      <div className="stat-card">
        <h3>Total Users</h3>
        <p className="text-2xl">
          {formatNum({ number: stats.users, asOrdinal: true, asCurrency:false })}
        </p>
      </div>
      
      <div className="stat-card">
        <h3>Revenue</h3>
        <p className="text-2xl">
          {formatNum({ number: stats.revenue })}
        </p>
      </div>
      
      <div className="stat-card">
        <h3>Page Views</h3>
        <p className="text-2xl">
          {formatNum({ number: stats.views, asOrdinal: true, asCurrency:false })}
        </p>
      </div>
    </div>
  )
}

Invoice Generator

import useNumformatter from "@/hooks/useNumformatter"

export default function Invoice({ items }) {
  const { formatNum } = useNumformatter()
  
  const subtotal = items.reduce((sum, item) => sum + item.price, 0)
  const tax = subtotal * 0.1
  const total = subtotal + tax

  return (
    <div className="invoice">
      <table>
        <tbody>
          {items.map(item => (
            <tr key={item.id}>
              <td>{item.name}</td>
              <td>{formatNum({ number: item.price })}</td>
            </tr>
          ))}
        </tbody>
        <tfoot>
          <tr>
            <td>Subtotal</td>
            <td>{formatNum({ number: subtotal,  })}</td>
          </tr>
          <tr>
            <td>Tax (10%)</td>
            <td>{formatNum({ number: tax,  })}</td>
          </tr>
          <tr className="font-bold">
            <td>Total</td>
            <td>{formatNum({ number: total,  })}</td>
          </tr>
        </tfoot>
      </table>
    </div>
  )
}

Social Media Counts

import useNumformatter from "@/hooks/useNumformatter"

export default function SocialStats({ followers, likes, views }) {
  const { formatNum } = useNumformatter()

  return (
    <div className="flex gap-6">
      <div>
        <p className="text-sm text-gray-500">Followers</p>
        <p className="text-xl font-semibold">
          {formatNum({ number: followers, asOrdinal: true, asCurrency:false })}
        </p>
      </div>
      
      <div>
        <p className="text-sm text-gray-500">Likes</p>
        <p className="text-xl font-semibold">
          {formatNum({ number: likes, asOrdinal: true, asCurrency:false })}
        </p>
      </div>
      
      <div>
        <p className="text-sm text-gray-500">Views</p>
        <p className="text-xl font-semibold">
          {formatNum({ number: views, asOrdinal: true, asCurrency:false })}
        </p>
      </div>
    </div>
  )
}

Shopping Cart Total

import useNumformatter from "@/hooks/useNumformatter"

export default function CartSummary({ items }) {
  const { formatNum } = useNumformatter()
  
  const total = items.reduce((sum, item) => sum + item.price * item.quantity, 0)

  return (
    <div className="cart-summary">
      {items.map(item => (
        <div key={item.id} className="flex justify-between">
          <span>{item.name} × {item.quantity}</span>
          <span>{formatNum({ number: item.price * item.quantity,  })}</span>
        </div>
      ))}
      
      <div className="border-t pt-4 flex justify-between font-bold">
        <span>Total</span>
        <span>{formatNum({ number: total})}</span>
      </div>
    </div>
  )
}

Percentage Display

import useNumformatter from "@/hooks/useNumformatter"

export default function ProgressBar({ value, max }) {
  const { formatNum } = useNumformatter()
  const percentage = (value / max) * 100

  return (
    <div>
      <div className="flex justify-between mb-2">
        <span>Progress</span>
        <span>{formatNum({ number: percentage, asCurrency:false, suffix: "%" })}</span>
      </div>
      <div className="h-2 bg-gray-200 rounded">
        <div 
          className="h-full bg-blue-500 rounded"
          style={{ width: `${percentage}%` }}
        />
      </div>
    </div>
  )
}

Dynamic Currency Selector

import useNumformatter from "@/hooks/useNumformatter"
import { useState } from "react"

export default function CurrencyConverter() {
  const { formatNum } = useNumformatter()
  const [amount] = useState(100)
  const [currency, setCurrency] = useState("$")

  return (
    <div>
      <select value={currency} onChange={(e) => setCurrency(e.target.value)}>
        <option value="$">USD</option>
        <option value="€">EUR</option>
        <option value="£">GBP</option>
        <option value="₦">NGN</option>
      </select>
      
      <p className="text-2xl">
        {formatNum({ number: amount, prefix: currency, asCurrency:false })}
      </p>
    </div>
  )
}

File Size Formatter

import useNumformatter from "@/hooks/useNumformatter"

export default function FileInfo({ bytes, name }) {
  const { formatNum } = useNumformatter()

  return (
    <div className="file-item">
      <span>{name}</span>
      <span className="text-gray-500">
        {formatNum({ number: bytes, asOrdinal: true, asCurrency:false })}B
      </span>
    </div>
  )
}

// Usage
<FileInfo name="document.pdf" bytes={2500000} />
// Shows: document.pdf 3MB

Configuration

Default Currency

The hook defaults to the Nigerian Naira (₦) symbol. To change the default currency:

// In the hook file (registry/v1/hooks/useNumformatter.tsx)
const currency = "$" // Change from "₦" to your preferred symbol

Notes

  • Default currency symbol is ₦ (Nigerian Naira)
  • asCurrency option adds ₦ prefix automatically
  • prefix option overrides will combine currency and prefix unless asCurrency is false, then it overrides it
  • asOrdinal formats as K/M/G/T/P/E

Type Definition

interface Config {
  number: number | string
  asCurrency?: boolean
  prefix?: string
  asOrdinal?: boolean
  forceDecimal?: boolean
}

function useNumformatter(): {
  formatNum: (config: Config) => string
}

Dependencies

  • @/lib/helpers/numberHelpers (formatNumber, formatOrdinal)
  • React (useCallback)

On this page