# The Eagerly agenda, built for Glamrock

## For local testing

cd your-lib-folder/

```
npm link
```

cd your-app/

```
npm link name-of-your-lib
```

### Want to also minify bundle output?

You can install rollup-plugin-terser (still works with rollup v3, but since it has no updates, we need to install it with legacy peer options)

```
npm i rollup-plugin-terser --save-dev --legacy-peer-deps
```

The `Agenda` component allows for flexible rendering of the following components:

- `Tile`
- `Image`
- `Link`
- `NotFound`
- `LoadMoreButton`
  This is useful when you want to overwrite a default component with different markup or styling.

## Props

The Agenda component accepts the following props:

| **Prop Name**            | **Type**                                    | **Required** | **Description**                                                                                                                                      |
| ------------------------ | ------------------------------------------- | ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`data`**               | `Array`                                     | Yes          | An array of events and promo texts to render in the agenda. Each item should follow the structure expected by the agenda.                            |
| **`helperText`**         | `ReactNode` or `string`                     | No           | Optional text strings to overwrite default strings that can be found in strings.ts.                                                                  |
| **`searchParams`**       | `Record<string, unknown>`                   | No           | An object containing key-value pairs for filtering, pagination, and other query parameters. Useful for server-side filtering or client-side control. |
| **`handleParamsChange`** | `(params: Record<string, unknown>) => void` | No           | A callback function triggered when the `searchParams` are updated by user actions or internal state changes.                                         |
| **`filters`**            | `Array` or `Record<string, unknown>`        | No           | Configures the filter options available for users to refine the displayed data.                                                                      |
| **`options`**            | `Object`                                    | No           | A collection of configuration options for customizing agenda behavior. See [Options Table](#options-table) for details.                              |
| **`components`**         | `Object`                                    | No           | Custom React components to override default UI elements. See [Components Table](#components-table) for details.                                      |

### Example helperText

```js
...
helperText={{
  loadMore: 'Show me more please!',
}}
...
```

### Options

| **Prop**                | **Type**                                       | **Default**                                        | **Description**                                                  |
| ----------------------- | ---------------------------------------------- | -------------------------------------------------- | ---------------------------------------------------------------- |
| `locale`                | `string`                                       | `'nl-NL'`                                          | Sets the locale for date formatting.                             |
| `postsPerPage`          | `number`                                       | `5`                                                | Number of posts to display per page.                             |
| `showViewSwitcher`      | `boolean`                                      | `false`                                            | Enables the view switcher functionality.                         |
| `showTotal`             | `boolean`                                      | `true`                                             | Optionally show a total count above results                      |
| `useOverlay`            | `boolean`                                      | `true`                                             | Whether to show the filters in an overlay or not                 |
| `promoFrequency`        | `number`                                       | `4`                                                | Frequency at which promo strips are shown.                       |
| `promoStrips`           | `ReactNode[]`                                  | `[]`                                               | Array of custom promo strips to display.                         |
| `date.formatSingle`     | `string`                                       | `'EEE d MMM yyyy'`                                 | Date format for single dates.                                    |
| `date.formatRange`      | `{start: string, end: string}`                 | `{start: 'EEE d MMM yyyy', end: 'EEE d MMM yyyy'}` | Date format for range of dates.                                  |
| `date.dateRangeDivider` | `string`                                       | `'->'`                                             | Divider used in date ranges.                                     |
| `date.useMostRecent`    | `boolean`                                      | `false`                                            | Uses the most recent date if multiple are available.             |
| `groupEventsByMonth`    | `boolean`                                      | `true`                                             | Groups events by month in the agenda view.                       |
| `loadMore`              | `function`                                     | `undefined`                                        | Callback function triggered when loading more events.            |
| `icons`                 | `{ prevPage: ReactNode, nextPage: ReactNode }` | `{}`                                               | Object containing custom icon components for navigation buttons. |
| `filters`               | `any[]`                                        | `[]`                                               | Array of filter options for the agenda.                          |
| `searchParams`          | `object`                                       | `{}`                                               | Search parameters for filtering agenda items.                    |
| `handleParamsChange`    | `function`                                     | `undefined`                                        | Callback function triggered when search parameters change.       |

### Example custom options

```js
const promoStrips = [
  <div key={1} style={{ background: 'green' }}>
    Promo 1
  </div>,
  <div key={2} style={{ background: 'blue' }}>
    Promo 2
  </div>
];
```

### Components

| **Prop**                    | **Type**                                       | **Default** | **Description**                                                  |
| --------------------------- | ---------------------------------------------- | ----------- | ---------------------------------------------------------------- |
| `components.Image`          | `React.Component`                              | Next Image  | Custom image component for rendering images.                     |
| `components.Link`           | `React.Component`                              | Next Link   | Custom link component for handling navigation.                   |
| `components.Tile`           | `function`                                     | `undefined` | Custom tile renderer for agenda items.                           |
| `components.NotFound`       | `ReactNode`                                    | `undefined` | Custom component to display when no items are found.             |
| `components.LoadMoreButton` | `ReactNode`                                    | `undefined` | Custom button for loading more items.                            |
| `icons`                     | `{ prevPage: ReactNode, nextPage: ReactNode }` | `{}`        | Object containing custom icon components for navigation buttons. |
| `filters`                   | `any[]`                                        | `[]`        | Array of filter options for the agenda.                          |
| `searchParams`              | `object`                                       | `{}`        | Search parameters for filtering agenda items.                    |
| `handleParamsChange`        | `function`                                     | `undefined` | Callback function triggered when search parameters change.       |

### Example custom components

The following components do not have a custom value in settings.js file of your Glamrock project. Here's how you can overwrite them:

```js
Tile: ({ item }) => (
  <div key={item.title} className="custom-tile">
    <h3>{item.title}</h3>
  </div>
);
```

```js
NotFound: <div>No items found</div>,
```

```js
icons: {
  prevPage: <Icon icon="ARROW_RIGHT" fill="secondary" width="15px" height="15px" />,
  nextPage: <Icon icon="ARROW_RIGHT" fill="secondary" width="15px" height="15px" />
}
```

```js
LoadMoreButton: <button>Load more</button>;
```

## Full example

Here’s an example demonstrating how to implement a custom tile and custom promo strips.
To use a custom tile rendering function, follow these steps:

1. **Define a custom rendering function** that accepts a `DataItem` and returns the desired JSX markup.
2. **Overwrite the default Tile by passing this function to the `Agenda` component** via the `Tile` prop:

```js
'use client';

import Agenda from 'glamrock-agenda';
import AgendaStyled from './style'; // wrapper that contains all the styling
import useEvents from './useEvents'; // hook to prepare data
import { defaultOptions, defaultComponents } from './settings'; // default settings

const EagerlyAgenda = () => {
  const postsPerPage = defaultOptions.postsPerPage;
  const useLoadMore = defaultOptions.useLoadMore;

  const { currentParams, data, filters, handleParamsChange, loadMore } = useEvents({
    postsPerPage,
    useLoadMore,
  });

  // extend default options
  const customOptions = {
    ...defaultOptions,
    loadMore,
    // overwrite default value
    promoFrequency: 2,
    // overwrite default promo strips
    promoStrips: [
      <div key={1} style={{ background: 'green' }}>
        Promo 1
      </div>,
      <div key={2} style={{ background: 'blue' }}>
        Promo 2
      </div>,
    ],
  };

  // extend default components
  const customComponents = {
    ...defaultComponents,
    // add custom Tile
    Tile: (item) => (
      <div key={item.title} className="custom-tile">
        <h4 style={{ color: 'blue' }}>{item.title}</h4>
        <a href={item.link}>Read more</a>
      </div>
    ),
  };

  return (
    <AgendaStyled>
      <Agenda
        data={data}
        helperText={}
        searchParams={currentParams}
        handleParamsChange={handleParamsChange}
        filters={filters}
        options={customOptions}
        components={customComponents}
      />
    </AgendaStyled>
  );
};

export default EagerlyAgenda;
```

## Build & Publish

You can use this template and
change the name under package.json.

Build

```
npm run build
```

Build & Watch

```
npm run build:watch
```

Publish (public library)

Be sure you are either logged in under `npm login` or you have a token (check https://docs.npmjs.com/creating-and-viewing-access-tokens).

```
npm run publish --access=public
```
