Created
August 30, 2025 13:56
-
-
Save sgade/3a3c8355665d9b2781c59c50c5a74013 to your computer and use it in GitHub Desktop.
Scriptable.app widget that displays REWE delivery status
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Variables used by Scriptable. | |
| // These must be at the very top of the file. Do not edit. | |
| // icon-color: red; icon-glyph: shipping-fast; | |
| /* | |
| Wann kommt REWE? | |
| Displays the contents of wannkommt.rewe.de in a simple widget. | |
| Configuration: | |
| After adding the widget, you need to edit it and set the widget's parameter to your order id. | |
| */ | |
| const deliveryId = args.widgetParameter || null; | |
| const data = deliveryId ? await fetchData(deliveryId) : {}; | |
| const widget = await createWidget(data); | |
| // Shows preview of widget in app | |
| if (!config.runsInWidget) { | |
| await widget.presentSmall(); | |
| } | |
| // Tell the system to show the widget. | |
| Script.setWidget(widget); | |
| Script.complete(); | |
| // === Functions === | |
| async function fetchData(deliveryId) { | |
| let url = `https://wannkommt.rewe.de/api/delivery/${deliveryId}`; | |
| let request = new Request(url); | |
| return await request.loadJSON(); | |
| } | |
| async function createWidget(data) { | |
| let widget = new ListWidget(); | |
| widget.backgroundColor = new Color("#C13531"); | |
| // REWE header | |
| (function(widget, data) { | |
| const font = Font.headline(); | |
| const color = Color.white(); | |
| const stack = widget.addStack(); | |
| addSymbol(stack, "shippingbox", font, color); | |
| stack.addSpacer(4); | |
| const text = stack.addText("REWE"); | |
| text.font = font; | |
| text.textColor = color; | |
| if (data.statusTimestamp) { | |
| stack.addSpacer(); | |
| const relativeTimestamp = new RelativeDateTimeFormatter().string( | |
| new Date(data.statusTimestamp), | |
| new Date() | |
| ); | |
| const timestamp = stack.addText(relativeTimestamp); | |
| timestamp.font = font; | |
| timestamp.textColor = Color.lightGray(); | |
| timestamp.rightAlignText(); | |
| } | |
| return stack; | |
| })(widget, data); | |
| // Delivery status | |
| if (data.status) { | |
| widget.addSpacer(); | |
| const status = widget.addText(data.status); | |
| status.font = Font.title3(); | |
| status.textColor = colorForStatus(data.status); | |
| } | |
| // Delivery window (if not delivered) | |
| if (data.expectedArrivalIntervalStart && data.expectedArrivalIntervalEnd && data.status != "DELIVERED") { | |
| widget.addSpacer(); | |
| let timeframe = `${formatTime(data.expectedArrivalIntervalStart)}—${formatTime(data.expectedArrivalIntervalEnd)}`; | |
| if ( ["medium", "large"].includes(config.widgetFamily) ) { | |
| timeframe = `Expected: ${timeframe}` | |
| } | |
| const arrival = widget.addText(timeframe); | |
| arrival.font = Font.subheadline();; | |
| arrival.textColor = Color.white(); | |
| } | |
| // Number of customers before "me" | |
| if (data.customersBeforeMe) { | |
| widget.addSpacer(); | |
| const customersBefore = widget.addText(`${data.customersBeforeMe} customers before me`); | |
| customersBefore.font = Font.subheadline(); | |
| customersBefore.color = Color.white(); | |
| } | |
| return widget; | |
| } | |
| /** | |
| * Loads an SFSymbol by name and renders it in an image container on the base layout. | |
| * @param {*} base The base layout item that has an `addImage` function. | |
| * @param {*} name The SFSymbol name to load. | |
| * @param {*} font The font to render the symbol with. | |
| * @param {*} color The color to render the symbol with. | |
| * @returns The symbol image object that has been added to the base layout. | |
| */ | |
| function addSymbol(base, name, font, color) { | |
| if (!base.addImage) { | |
| console.log("base doesn't have addImage: " + base) | |
| return; | |
| } | |
| const symbol = SFSymbol.named(name); | |
| symbol.applyFont(font); | |
| const symbolImage = base.addImage(symbol.image); | |
| symbolImage.resizable = false; | |
| symbolImage.tintColor = color; | |
| return symbolImage | |
| } | |
| /** | |
| * Determines the color for a given order delivery status. | |
| * @param {string} status The delivery status. | |
| * @returns The color for the delivery status, or black. | |
| */ | |
| function colorForStatus(status) { | |
| switch (status) { | |
| case "CREATED", | |
| "COMMISSION_STARTED": | |
| return Color.darkGray(); | |
| case "STARTED": | |
| return Color.lightGray(); | |
| case "APPROACHING", | |
| "ARRIVED": | |
| return Color.white(); | |
| case "DELIVERED": | |
| return Color.green(); | |
| default: | |
| return Color.black(); | |
| } | |
| } | |
| /** | |
| * Formats the date string into a localized time string. | |
| * @param {string} dateString The date string. | |
| * @returns The time as a localized string. | |
| */ | |
| function formatTime(dateString) { | |
| return new Date(dateString).toLocaleTimeString() | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment