Integration
Exports and events for calling into legacy-shops from other resources.
Opening the storefront (client)
Call from any client script (e.g. a qb-target/legacy-lib Target interaction, a command, etc.):
-- client-side, e.g. client/main.lua
exports['legacy-shops']:OpenStore(3) -- shopId
This awaits the legacy-shops:getInitData and legacy-shops:openStore server callbacks and opens the store NUI. It no-ops if the UI is already open, or shows an lib.notify error if the server returns no data (e.g. job-locked).
Opening the admin creator (client)
-- client-side
exports['legacy-shops']:OpenCreator()
Requires initData.isAdmin (from the cached legacy-shops:getInitData result) to be true, otherwise shows an lib.notify error. Note this admin check is client-side only after the initial fetch — the server-side legacy-shops:getInitData callback is the real enforcement point.
Opening the creator from the server
-- server-side, e.g. server/main.lua
TriggerClientEvent('legacy-shops:openCreator', src)
This triggers the local OpenCreator() function on that client, instead of relying on the client to call the export directly. This is what Config.CreatorCommand uses internally.
Reacting to shop list changes (client)
-- client-side
AddEventHandler('legacy-shops:syncShops', function()
-- re-fetch and respawn shop peds/blips automatically (handled internally)
end)
Broadcast server-side (to all clients, -1) after any shop is created, updated, deleted, or after a preset re-sync propagates to its linked shops. You don't need to trigger this yourself in normal usage — the server callbacks below already broadcast it.
legacy-shops:stockUpdatedis also broadcast to all clients after restock/fluctuation ticks, but its client-side handler is currently an empty stub — do not rely on it to refresh an open store UI.
Server callbacks (ox_lib lib.callback)
All of the following are registered server-side and consumed via lib.callback.await(...) from the client, or can be called from other server scripts via the export syntax exports['legacy-shops']:<name>(...) where applicable. Admin-gated ones return an empty result for non-admins.
-- server-side example: fetch a shop's items from another resource
local items = exports['legacy-shops']:getItems(shopId)
Key callbacks:
| Callback | Access | Purpose |
|---|---|---|
legacy-shops:getInitData(src) |
any | Locale, isAdmin flag, Config.PedPresets, all presets, branding theme. |
legacy-shops:getPresets(src) |
admin | Full preset catalogue enriched with live item label/image data. |
legacy-shops:savePreset(src, data) |
admin | Create/update a preset; re-syncs linked shops on update. |
legacy-shops:deletePreset(src, presetId) |
admin | Deletes a preset; linked shops keep their contents but lose the link. |
legacy-shops:getShops(src) |
admin | Summary list of all shops for the creator UI. |
legacy-shops:createShop(src, data) |
admin | Creates a shop, seeds contents from preset/data, broadcasts legacy-shops:syncShops. |
legacy-shops:updateShop(src, data) |
admin | Updates name/ped_model/coords/blip fields only (not groups/preset_id). |
legacy-shops:deleteShop(src, shopId) |
admin | Deletes a shop and its items/categories/prices. |
legacy-shops:getCategories(src, shopId) |
any | Returns a shop's categories sorted by sort_order. |
legacy-shops:saveCategory(src, data) |
admin | Create/update a category. |
legacy-shops:deleteCategory(src, categoryId) |
admin | Deletes a category and cascades to its items. |
legacy-shops:getItems(src, shopId) |
any | Items enriched with label/image and current fluctuated price. |
legacy-shops:saveItem(src, data) |
admin | Create/update an item. |
legacy-shops:deleteItem(src, data) |
admin | Removes an item from a shop. |
legacy-shops:getAllItems(src) |
admin | Full inventory item catalogue for the item picker. |
legacy-shops:getShopList(src) |
any | Raw shop rows used by clients to place peds/blips. |
legacy-shops:openStore(src, shopId) |
any (job-gated) | Shop, categories, items with current price/stock, and player balances. |
legacy-shops:purchase(src, data) |
any (validated) | Validates access/stock/licence/grade/funds, deducts payment, adds items, logs to legacy_shops_history. |
Example: purchase flow trigger from the storefront NUI
-- this happens internally via lib.callback from the NUI; shown here as a
-- reference for what a purchase payload looks like
local result = lib.callback.await('legacy-shops:purchase', false, {
shopId = 3,
paymentMethod = 'cash', -- or 'bank'
lines = {
{ id = 12, quantity = 2 },
},
})
