npm package: @syeedalireza/use-reverse-auction
Description: Professional reverse auction package
Author: Alireza Aminzadeh
Latest version: 1.0.0

# @syeedalireza/use-reverse-auction

A collection of headless React Hooks for managing complex reverse auction state on the client side.

## Features
- **Headless UI**: Provides logic and state management without dictating the UI, allowing you to use Tailwind, Material UI, or custom CSS.
- **Global State**: Uses `zustand` under the hood for efficient, predictable state updates.
- **Bid Validation**: Built-in logic to ensure bids are valid (e.g., lower than the current lowest bid).
- **Timer Management**: Includes a dedicated hook for handling countdown timers.

## Installation

```bash
npm install @syeedalireza/use-reverse-auction zustand date-fns
```

## Usage

### `useReverseAuction`

```tsx
import { useReverseAuction } from '@syeedalireza/use-reverse-auction';

const AuctionComponent = ({ auctionId, endTime }) => {
  const { 
    state, 
    lowestBid, 
    bids, 
    timeRemaining, 
    placeBid, 
    isClosed 
  } = useReverseAuction({
    auctionId,
    initialEndTime: endTime,
    onBidPlaced: (bid) => console.log('New bid:', bid),
    onAuctionClosed: () => console.log('Auction ended!')
  });

  const handleBid = () => {
    placeBid({
      id: Math.random().toString(),
      bidderId: 'user-1',
      amount: (lowestBid?.amount || 100) - 10
    });
  };

  if (isClosed) return <div>Auction Closed! Winning bid: {lowestBid?.amount}</div>;

  return (
    <div>
      <h2>Time Remaining: {Math.floor(timeRemaining / 1000)}s</h2>
      <p>Current Lowest Bid: {lowestBid?.amount || 'None'}</p>
      <button onClick={handleBid}>Place Lower Bid</button>
      
      <ul>
        {bids.map(bid => (
          <li key={bid.id}>{bid.amount} by {bid.bidderId}</li>
        ))}
      </ul>
    </div>
  );
};
```

### `useBidTimer`

```tsx
import { useBidTimer } from '@syeedalireza/use-reverse-auction';

const TimerDisplay = ({ endTime }) => {
  const { hours, minutes, seconds, isExpired } = useBidTimer(endTime);

  if (isExpired) return <span>Time's up!</span>;

  return (
    <span>
      {hours}h {minutes}m {seconds}s
    </span>
  );
};
```

## API

### `useReverseAuction(options)`
**Options:**
- `auctionId` (string): Unique identifier for the auction.
- `initialEndTime` (number): Timestamp (ms) when the auction ends.
- `onBidPlaced` (function): Optional callback when a bid is successfully placed.
- `onAuctionClosed` (function): Optional callback when the timer hits zero.

**Returns:**
- `state` ('DRAFT' | 'ACTIVE' | 'CLOSED'): Current auction state.
- `lowestBid` (Bid | null): The current lowest bid.
- `bids` (Bid[]): Array of all placed bids.
- `timeRemaining` (number): Milliseconds remaining.
- `placeBid` (function): Function to place a new bid. Throws if invalid.
- `isClosed` (boolean): Convenience boolean for `state === 'CLOSED'`.

### `useBidTimer(endTime)`
**Arguments:**
- `endTime` (number | null): Timestamp (ms) when the timer should end.

**Returns:**
- `hours` (number): Hours remaining.
- `minutes` (number): Minutes remaining.
- `seconds` (number): Seconds remaining.
- `isExpired` (boolean): True if the current time is past the `endTime`.