dlock-svelte
v0.3.3
Published
Coownable Basket is a library for booking seats for a cinema. Except the library was not built for "seats", but _shares in an asset_.
Readme
Coownable Basket
Coownable Basket is a library for booking seats for a cinema. Except the library was not built for "seats", but shares in an asset.
It's optimized for usability, giving users instantaneous feedback even if network latency is high.
It allows users to add shares to their basket (acquire lock) or remove them (release lock).
The user sees the share in their basket immediately, before the server has had a chance to confirm whether it's still available (it may have been snatched right before our nose by someone else).
If the server rejects the user's request to add it to the basket, the user will see the share removed from their basket automatically, and they can no longer select it.
All of this logic is a bit tricky to implement. This library encapsulates this behaviour. You need to provide 4 arguments:
basketId- the ID of our basket (from cookie or URL).subscribe- a function that subscribes to update events from the server.getBasketAssets- a function that returns the initial list of assets (with their shares).getAsset- a function to retrieve an asset. Called when an event for an unseen asset is received.
The library implements the following concepts:
- Optimistic locking of individual seats.
- Eventual consistency, consuming events from an
EventSourceorWebSocket - Intuitive rendering and interaction - aims to be WAI-ARIA / keyboard friendly
This library implements Svelte components and reactive state for Coownable Baskets.
Components
ShareTile- A square that displays the state of a share.
You can build your own components in React, Vue, Svelte or plain HTML and JavaScript and integrate them with the Coownable JavaScript API.
JavaScript API
The API is encapsulated in the BasketState class.
First you need an instance:
const basketState = new BasketState(assetsState);Once you have an instance of BasketState you can query its properties:
console.log(basketState.quantity);
console.log(basketState.accountEntries);You can listen for events.
basketState.addEventListener('changed', (event) => {
console.log('changed', event.detail);
});
The `changed` event fires whenever there is a change to the basket.
That is - whenever a share is added or removed from the basket.
Share states
Each share can be in one of the following states:
in-my-basket- it's in my basketin-someone-elses-basket- it's in someone else's basketacquiring- optimistically in my basketavailable- not in anyone's basketreleasing- not in my basket locally, not yet propagated to serverunknown- this normally shouldn't happen
Styling <ShareTile>
The <ShareTile> component ships with default styles.
There are two ways to override these styles:
Using CSS variable overrides
This is the recommended approach if you only need to tweak colours or other simple attributes.
:root {
--share-tile-bg-in-my-basket: #10b981;
--share-tile-bg-in-someone-elses-basket: #f43f5e;
--share-tile-width: 48px;
--share-tile-height: 48px;
}Using custom CSS
This approach gives you full control, but there is more CSS to write.
When you specify a class, all default styles are disabled:
<ShareTile class="my-custom-class" />Now you can provide your own stylesheet:
.my-custom-class input {
display: none;
}
/* More styles here... */TODO:
- [ ] Update
state.d2 - [ ] Rename to coownable-basket
- [ ] Release on npm
- [ ] Move keyboard navigation logic
- [x] Move draw image+tiles components
- [x] Move image loading code
- [x] Need to serve up images
- [x] Move draw image+tiles component:
<AssetTiles> - [x] Add x,y,locked etc to Share type
- [ ] Add quantity selector [-]3[+]
- [ ] Move code to check/uncheck "nearest" based on quantity
Coownable
- [ ] Add a requested_by_basket_id column
- [ ] Unless we can somehow inject it JIT in the Kysely plugin (passing in basketId)
- [ ] Delete all the API routes
- [ ] OpenAPI libs and code
- [ ] Client generation
- [ ] Package wafer thin coownable.js library with a constant
window.coownable : BasketState- [ ] Add custom elements
