Scan Item
+Use camera or type barcode
+diff --git a/docs/App Extensions/app-extension-examples/_order.yaml b/docs/App Extensions/app-extension-examples/_order.yaml index e566674b..9bf03483 100644 --- a/docs/App Extensions/app-extension-examples/_order.yaml +++ b/docs/App Extensions/app-extension-examples/_order.yaml @@ -1,2 +1,9 @@ - index +- date-picker-with-blackout-dates +- high-energy-hazard-selector +- illness-symptoms-selector +- inventory-scanner-with-barcode +- offline-capabilities - rich-text-editor +- share-pdf +- visualize-data-with-chart-js diff --git a/docs/App Extensions/app-extension-examples/date-picker-with-blackout-dates.md b/docs/App Extensions/app-extension-examples/date-picker-with-blackout-dates.md new file mode 100644 index 00000000..7ff5d7a9 --- /dev/null +++ b/docs/App Extensions/app-extension-examples/date-picker-with-blackout-dates.md @@ -0,0 +1,229 @@ +--- +title: Date picker with blackout dates +excerpt: >- + This App Extension opens a popup calendar that prevents users from selecting + blacked-out date ranges. Blackout dates are loaded dynamically from a + separate Fulcrum app using LOADRECORDS, so administrators can manage blocked + dates without touching the data event code. +deprecated: false +hidden: false +metadata: + title: '' + description: '' + robots: noindex +next: + description: '' +--- + +# Date picker with blackout dates + +This example uses an App Extension to display a Flatpickr-powered calendar popup that restricts users from selecting certain dates. Blackout date ranges are stored in a separate Fulcrum app and loaded at runtime via `LOADRECORDS`, so administrators can add or remove blocked dates without updating the Data Event. + +When the user clicks a button on the form, `OPENEXTENSION` launches the calendar. The selected date is returned to the form and written to a date field. + +## How it works + +1. A separate **blackout dates app** stores date range records (start date / end date). +2. On `load-record`, the Data Event fetches those ranges via `LOADRECORDS` and stores them in a variable. +3. When the user clicks the calendar button, `OPENEXTENSION` opens `calendar_picker.html` — a self-contained HTML page that uses [Flatpickr](https://flatpickr.js.org/) to render the calendar. +4. The blackout ranges are passed to the HTML page via the `data` option. Flatpickr disables those date ranges in the calendar. +5. When the user picks a date, the HTML page sends it back via `Fulcrum.finish()`, and the Data Event writes it to an appointment date field. + +## Setup + +1. Create a **blackout dates app** with two Date fields: + - `start` — the first day of the blocked range + - `end` — the last day of the blocked range (inclusive) + Note the app's **Form ID** and the field keys for `start` and `end`. +2. Upload `calendar_picker.html` (below) as a **Reference File** in your Fulcrum org, or attach it directly to your app. +3. In your data collection app, add: + - A **Date** field for the appointment result (e.g. data name: `appointment_date`) + - A **Button** field to trigger the calendar (e.g. data name: `open_calendar`) +4. Add the Data Event code below to the app and update the configuration constants. + +> **Note:** The Flatpickr calendar requires an internet connection when using the CDN version below. For fully offline use, replace the CDN links with a locally hosted or embedded copy of Flatpickr. + +## Data Event Code + +```js +// ─── Configuration ─────────────────────────────────────────────────────────── + +// Form ID of the blackout dates app +const BLACKOUT_FORM_ID = 'YOUR-BLACKOUT-DATES-FORM-ID-HERE'; + +// Field key of the start date field in the blackout app +const START_DATE_KEY = 'YOUR-START-DATE-FIELD-KEY'; + +// Field key of the end date field in the blackout app +const END_DATE_KEY = 'YOUR-END-DATE-FIELD-KEY'; + +// Data name of the date field to write the selected appointment date to +const APPOINTMENT_FIELD = 'appointment_date'; + +// Data name of the button field that opens the calendar +const CALENDAR_BUTTON = 'open_calendar'; + +// ─── Load blackout ranges on record open ───────────────────────────────────── + +let blackoutRanges = []; + +ON('load-record', () => { + LOADRECORDS({ form_id: BLACKOUT_FORM_ID }, (err, result) => { + if (err) { + console.log('Error loading blackout dates:', INSPECT(err)); + return; + } + + // Build an array of { start, end } objects from the loaded records + blackoutRanges = (result.records || []).map(rec => ({ + start: rec.form_values[START_DATE_KEY] || '', + end: rec.form_values[END_DATE_KEY] || '' + })).filter(range => range.start && range.end); + }); +}); + +// ─── Open the calendar extension ───────────────────────────────────────────── + +ON('click', CALENDAR_BUTTON, () => { + if (!blackoutRanges.length) { + // Allow the calendar to open even if no blackout dates loaded yet + console.log('No blackout ranges loaded; opening calendar without restrictions.'); + } + + OPENEXTENSION({ + url: 'attachment://calendar_picker.html', + title: 'Select Appointment Date', + width: 400, + height: 500, + data: { + blackoutRanges: blackoutRanges, + today: (function (d) { + const year = d.getFullYear(); + const month = String(d.getMonth() + 1).padStart(2, '0'); + const day = String(d.getDate()).padStart(2, '0'); + return year + '-' + month + '-' + day; + })(new Date()) + }, + onMessage: ({ data }) => { + if (data.selectedDate) { + SETVALUE(APPOINTMENT_FIELD, data.selectedDate); + } + } + }); +}); +``` + +## HTML Extension File (`calendar_picker.html`) + +Save the content below as `calendar_picker.html` and attach it to your Fulcrum app as a Reference File. This file is loaded inside the `OPENEXTENSION` popup. + +```html + + +
+ + +Direct Connection
+Use camera or type barcode
+