[{"data":1,"prerenderedAt":3004},["ShallowReactive",2],{"navigation_docs":3,"-modules-events":153,"-modules-events-surround":2999},[4,35,50,59,144],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":6},"Getting started",false,"\u002Fgetting-started","1.getting-started",[10,15,20,25,30],{"title":11,"path":12,"stem":13,"icon":14},"Introduction","\u002Fgetting-started\u002Fintroduction","1.getting-started\u002F2.introduction","i-lucide-house",{"title":16,"path":17,"stem":18,"icon":19},"Local Development","\u002Fgetting-started\u002Flocal-development","1.getting-started\u002F3.local-development","i-lucide-terminal",{"title":21,"path":22,"stem":23,"icon":24},"Publishing Packages","\u002Fgetting-started\u002Fpublishing","1.getting-started\u002F4.publishing","i-lucide-package-check",{"title":26,"path":27,"stem":28,"icon":29},"Writing a Module","\u002Fgetting-started\u002Fwriting-a-module","1.getting-started\u002F5.writing-a-module","i-lucide-puzzle",{"title":31,"path":32,"stem":33,"icon":34},"UX Patterns","\u002Fgetting-started\u002Fux-patterns","1.getting-started\u002F6.ux-patterns","i-lucide-layout-template",{"title":36,"path":37,"stem":38,"children":39},"Applications","\u002Fapplications","2.applications",[40,45],{"title":41,"path":42,"stem":43,"icon":44},"Website","\u002Fapplications\u002Fwebsite","2.applications\u002F1.website","i-lucide-layout-dashboard",{"title":46,"path":47,"stem":48,"icon":49},"Docs","\u002Fapplications\u002Fdocs","2.applications\u002F2.docs","i-lucide-book-open",{"title":51,"path":52,"stem":53,"children":54},"Layers","\u002Flayers","3.layers",[55],{"title":56,"path":57,"stem":58},"Base Layer","\u002Flayers\u002Fbase","3.layers\u002F1.base",{"title":60,"path":61,"stem":62,"children":63},"Modules","\u002Fmodules","4.modules",[64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,140],{"title":65,"path":66,"stem":67},"Account","\u002Fmodules\u002Faccount","4.modules\u002F01.account",{"title":69,"path":70,"stem":71},"Admin","\u002Fmodules\u002Fadmin","4.modules\u002F02.admin",{"title":73,"path":74,"stem":75},"Auth","\u002Fmodules\u002Fauth","4.modules\u002F03.auth",{"title":77,"path":78,"stem":79},"Authorization","\u002Fmodules\u002Fauthorization","4.modules\u002F04.authorization",{"title":81,"path":82,"stem":83},"Cookie Consent","\u002Fmodules\u002Fcookie-consent","4.modules\u002F05.cookie-consent",{"title":85,"path":86,"stem":87},"Events","\u002Fmodules\u002Fevents","4.modules\u002F06.events",{"title":89,"path":90,"stem":91},"Forms","\u002Fmodules\u002Fforms","4.modules\u002F07.forms",{"title":93,"path":94,"stem":95},"MCP","\u002Fmodules\u002Fmcp","4.modules\u002F08.mcp",{"title":97,"path":98,"stem":99},"Menu","\u002Fmodules\u002Fmenu","4.modules\u002F09.menu",{"title":101,"path":102,"stem":103},"Module Kit","\u002Fmodules\u002Fmodule-kit","4.modules\u002F10.module-kit",{"title":105,"path":106,"stem":107},"Notify","\u002Fmodules\u002Fnotify","4.modules\u002F11.notify",{"title":109,"path":110,"stem":111},"OAuth Server","\u002Fmodules\u002Foauth-server","4.modules\u002F12.oauth-server",{"title":113,"path":114,"stem":115},"Payments","\u002Fmodules\u002Fpayments","4.modules\u002F13.payments",{"title":117,"path":118,"stem":119},"Preferences","\u002Fmodules\u002Fpreferences","4.modules\u002F14.preferences",{"title":121,"path":122,"stem":123},"Stripe","\u002Fmodules\u002Fstripe","4.modules\u002F15.stripe",{"title":125,"path":126,"stem":127},"Subscriptions","\u002Fmodules\u002Fsubscriptions","4.modules\u002F16.subscriptions",{"title":129,"path":130,"stem":131},"UI","\u002Fmodules\u002Fui","4.modules\u002F17.ui",{"title":133,"path":134,"stem":135},"Users","\u002Fmodules\u002Fusers","4.modules\u002F18.users",{"title":137,"path":138,"stem":139},"Widget","\u002Fmodules\u002Fwidget","4.modules\u002F19.widget",{"title":141,"path":142,"stem":143},"Email Templates","\u002Fmodules\u002Femail-templates","4.modules\u002F20.email-templates",{"title":145,"path":146,"stem":147,"children":148},"Packages","\u002Fpackages","5.packages",[149],{"title":150,"path":151,"stem":152},"CLI","\u002Fpackages\u002Fcli","5.packages\u002F4.cli",{"id":154,"title":85,"body":155,"description":2993,"extension":2994,"links":2995,"meta":2996,"navigation":932,"path":86,"seo":2997,"stem":87,"__hash__":2998},"docs\u002F4.modules\u002F06.events.md",{"type":156,"value":157,"toc":2973},"minimark",[158,171,220,300,305,438,458,462,664,669,676,763,778,782,786,792,834,848,975,993,997,1014,1173,1186,1190,1206,1211,1430,1434,1455,1553,1556,1582,1659,1663,1826,1859,1863,1900,1902,1909,2011,2236,2252,2256,2263,2592,2603,2607,2815,2824,2830,2834,2915,2969],[159,160,161,162,165,166,170],"p",{},"Events and tickets, built on ",[163,164,113],"a",{"href":114},". The module handles ",[167,168,169],"strong",{},"only"," events and tickets; money is\ndelegated to Payments.",[172,173,174,186,204,210],"ul",{},[175,176,177,180,181,185],"li",{},[167,178,179],{},"Prices live in the database"," (minor units) and are charged through Checkout ",[182,183,184],"code",{},"price_data","; there are no Stripe ids to\nmaintain per environment.",[175,187,188,191,192,195,196,199,200,203],{},[167,189,190],{},"Ticket state follows payment state."," A paid ticket becomes ",[182,193,194],{},"paid"," only through the ",[182,197,198],{},"payments:paid"," hook, fed by\nverified Stripe events. Free tickets (total ",[182,201,202],{},"0",") are issued immediately without Stripe.",[175,205,206,209],{},[167,207,208],{},"Purchased tickets are snapshots."," Amount, currency and chosen addons are copied onto the ticket, which has no\nforeign keys to the catalogue, so editing or deleting catalogue rows never changes what someone bought.",[175,211,212,215,216,219],{},[167,213,214],{},"Staff access is the host's decision"," through the ",[182,217,218],{},"events:authorize"," hook (denied by default).",[221,222,223,226,227,230,231,234,235,240,241,234,246,234,251,240,256,261,262,267,268,226,271,276,277,234,282,287,288,293,294,299],"note",{},[167,224,225],{},"Requires"," ",[182,228,229],{},"@nuxthub\u002Fcore"," (KV on), ",[182,232,233],{},"@frigear-nu\u002Fmodule-kit",", ",[163,236,237],{"href":74},[182,238,239],{},"@frigear-nu\u002Fauth",",\n",[163,242,243],{"href":94},[182,244,245],{},"@frigear-nu\u002Fmcp",[163,247,248],{"href":134},[182,249,250],{},"@frigear-nu\u002Fusers",[163,252,253],{"href":130},[182,254,255],{},"@frigear-nu\u002Fui",[163,257,258],{"href":122},[182,259,260],{},"@frigear-nu\u002Fstripe"," and ",[163,263,264],{"href":114},[182,265,266],{},"@frigear-nu\u002Fpayments",".\n",[167,269,270],{},"Optional",[163,272,273],{"href":126},[182,274,275],{},"@frigear-nu\u002Fsubscriptions"," (membership provider),\n",[163,278,279],{"href":98},[182,280,281],{},"@frigear-nu\u002Fmenu",[163,283,284],{"href":138},[182,285,286],{},"@frigear-nu\u002Fwidget"," (event page tabs) and\n",[163,289,290],{"href":70},[182,291,292],{},"@frigear-nu\u002Fadmin"," (the admin pages exist only with it), ",[163,295,296],{"href":66},[182,297,298],{},"@frigear-nu\u002Faccount","\n(the left navigation and heading around the tickets page).",[301,302,304],"h2",{"id":303},"quick-setup","Quick setup",[306,307,312],"pre",{"className":308,"code":309,"language":310,"meta":311,"style":311},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","export default defineNuxtConfig({\n  events: {\n    settings: {\n      pages: { events: true, event: true, tickets: true },\n      reservationMinutes: 30,\n    },\n  },\n})\n","ts","",[182,313,314,338,351,361,403,417,423,429],{"__ignoreMap":311},[315,316,319,323,326,330,334],"span",{"class":317,"line":318},"line",1,[315,320,322],{"class":321},"s7zQu","export",[315,324,325],{"class":321}," default",[315,327,329],{"class":328},"s2Zo4"," defineNuxtConfig",[315,331,333],{"class":332},"sTEyZ","(",[315,335,337],{"class":336},"sMK4o","{\n",[315,339,341,345,348],{"class":317,"line":340},2,[315,342,344],{"class":343},"swJcz","  events",[315,346,347],{"class":336},":",[315,349,350],{"class":336}," {\n",[315,352,354,357,359],{"class":317,"line":353},3,[315,355,356],{"class":343},"    settings",[315,358,347],{"class":336},[315,360,350],{"class":336},[315,362,364,367,369,372,375,377,381,384,387,389,391,393,396,398,400],{"class":317,"line":363},4,[315,365,366],{"class":343},"      pages",[315,368,347],{"class":336},[315,370,371],{"class":336}," {",[315,373,374],{"class":343}," events",[315,376,347],{"class":336},[315,378,380],{"class":379},"sfNiH"," true",[315,382,383],{"class":336},",",[315,385,386],{"class":343}," event",[315,388,347],{"class":336},[315,390,380],{"class":379},[315,392,383],{"class":336},[315,394,395],{"class":343}," tickets",[315,397,347],{"class":336},[315,399,380],{"class":379},[315,401,402],{"class":336}," },\n",[315,404,406,409,411,415],{"class":317,"line":405},5,[315,407,408],{"class":343},"      reservationMinutes",[315,410,347],{"class":336},[315,412,414],{"class":413},"sbssI"," 30",[315,416,240],{"class":336},[315,418,420],{"class":317,"line":419},6,[315,421,422],{"class":336},"    },\n",[315,424,426],{"class":317,"line":425},7,[315,427,428],{"class":336},"  },\n",[315,430,432,435],{"class":317,"line":431},8,[315,433,434],{"class":336},"}",[315,436,437],{"class":332},")\n",[159,439,440,441,449,450,453,454,457],{},"Pages are opt-in and use ",[163,442,446],{"href":443,"rel":444},"https:\u002F\u002Fui.nuxt.com",[445],"nofollow",[182,447,448],{},"@nuxt\u002Fui",". With ",[182,451,452],{},"@nuxtjs\u002Fi18n"," installed, translated texts follow the\nactive locale; otherwise ",[182,455,456],{},"en"," is used.",[301,459,461],{"id":460},"options","Options",[463,464,465,484],"table",{},[466,467,468],"thead",{},[469,470,471,475,478,481],"tr",{},[472,473,474],"th",{},"Option",[472,476,477],{},"Type",[472,479,480],{},"Default",[472,482,483],{},"Purpose",[485,486,487,508,536,562,587,608,638],"tbody",{},[469,488,489,495,500,505],{},[490,491,492],"td",{},[182,493,494],{},"settings.reservationMinutes",[490,496,497],{},[182,498,499],{},"number",[490,501,502],{},[182,503,504],{},"30",[490,506,507],{},"How long an unpaid ticket keeps its seat; also the Stripe session lifetime.",[469,509,510,515,520,525],{},[490,511,512],{},[182,513,514],{},"settings.mcp",[490,516,517],{},[182,518,519],{},"boolean",[490,521,522],{},[182,523,524],{},"false",[490,526,527,528,530,531,535],{},"Expose the module's tools on the ",[163,529,93],{"href":94}," endpoint (see ",[163,532,534],{"href":533},"#mcp-tools","MCP tools",").",[469,537,538,543,548,551],{},[490,539,540],{},[182,541,542],{},"settings.pages.events",[490,544,545],{},[182,546,547],{},"string | boolean",[490,549,550],{},"off",[490,552,553,554,557,558,561],{},"Event list. ",[182,555,556],{},"true"," = ",[182,559,560],{},"\u002Fevents",".",[469,563,564,569,573,575],{},[490,565,566],{},[182,567,568],{},"settings.pages.event",[490,570,571],{},[182,572,547],{},[490,574,550],{},[490,576,577,578,581,582,557,584,561],{},"Event detail; path must contain ",[182,579,580],{},":slug",". ",[182,583,556],{},[182,585,586],{},"\u002Fevents\u002F:slug",[469,588,589,594,598,600],{},[490,590,591],{},[182,592,593],{},"settings.pages.tickets",[490,595,596],{},[182,597,547],{},[490,599,550],{},[490,601,602,603,557,605,561],{},"The signed-in user's tickets. ",[182,604,556],{},[182,606,607],{},"\u002Faccount\u002Ftickets",[469,609,610,615,619,625],{},[490,611,612],{},[182,613,614],{},"settings.pages.admin",[490,616,617],{},[182,618,547],{},[490,620,621,622,624],{},"off (needs ",[182,623,292],{},")",[490,626,627,628,630,631,234,634,637],{},"Staff event list. ",[182,629,556],{}," = the admin route for ",[182,632,633],{},"events",[182,635,636],{},"\u002Fadmin\u002Fevents"," by default.",[469,639,640,645,649,653],{},[490,641,642],{},[182,643,644],{},"settings.pages.adminEvent",[490,646,647],{},[182,648,547],{},[490,650,621,651,624],{},[182,652,292],{},[490,654,655,656,581,659,557,661,561],{},"Staff event page; path must contain ",[182,657,658],{},":id",[182,660,556],{},[182,662,663],{},"\u002Fadmin\u002Fevents\u002F:id",[665,666,668],"h3",{"id":667},"pages-and-their-patterns","Pages and their patterns",[159,670,671,672,675],{},"The pages follow the ",[163,673,674],{"href":32},"UX patterns"," of the ecosystem, one per area:",[172,677,678,721,749],{},[175,679,680,682,683,685,686,689,690,693,694,697,698,701,702,705,706,709,710,712,713,716,717,720],{},[167,681,69],{}," (needs ",[182,684,292],{},", listed in ",[182,687,688],{},"admin.nav","): the list is a ",[182,691,692],{},"PageHeading"," (\"New event\"), a ",[182,695,696],{},"TableCard","\nwith a status badge and a ",[182,699,700],{},"RowMenu"," per row (Open, View public page, Duplicate | Delete), and a ",[182,703,704],{},"UEmpty"," when there are\nno events. \"New event\" opens ",[182,707,708],{},"EventFormSlideover",". The event page has a breadcrumb back to the list, the status as a\nbadge, \"View public page\" and a ",[182,711,700],{}," in the heading, a key-facts ",[182,714,715],{},"SectionCard"," and the ",[182,718,719],{},"admin.events"," tabs\n(Details, Tickets, Attendees). Deleting asks for confirmation; events with paid tickets cannot be deleted, archive\nthem instead.",[175,722,723,725,726,728,729,732,733,736,737,741,742,744,745,561],{},[167,724,65],{},": ",[182,727,607],{}," renders only its content, a grid of ",[182,730,731],{},"EventTicketCard","s or a \"No tickets yet\" empty\nstate with \"Browse events\". The heading and left navigation come from the ",[182,734,735],{},"account"," layout of\n",[163,738,739],{"href":66},[182,740,298],{},". The menu item is registered in the ",[182,743,735],{}," menu (order 40) with\n",[163,746,747],{"href":98},[182,748,281],{},[175,750,751,725,754,261,756,758,759,762],{},[167,752,753],{},"Public",[182,755,560],{},[182,757,586],{}," are ",[182,760,761],{},"UContainer > UPage > UPageHeader"," pages (the detail page has the\nbreadcrumb in the header's headline) with the ticket picker beside the description.",[159,764,765,766,769,770,773,774,777],{},"Every link to an event goes through ",[182,767,768],{},"useEventLinks()",", so a visitor on ",[182,771,772],{},"\u002Fen\u002Fevents"," stays under ",[182,775,776],{},"\u002Fen"," when opening an\nevent.",[301,779,781],{"id":780},"server","Server",[665,783,785],{"id":784},"purchase-rules","Purchase rules",[159,787,788,791],{},[182,789,790],{},"POST \u002Fapi\u002Fevents\u002F:slug\u002Fpurchase"," checks, in this order:",[793,794,795,798,805,812,815,818,821,828],"ol",{},[175,796,797],{},"The event exists and is not over (404 \u002F 409).",[175,799,800,801,804],{},"The ticket type exists and its sale window is open (409). A ",[182,802,803],{},"saleSchedule",", if any, counts as part of the window.",[175,806,807,808,811],{},"Membership at ",[167,809,810],{},"event and ticket level",", then the ticket's exclusion rule (403). Without a membership provider a\nrequirement fails closed and an exclusion excludes nobody.",[175,813,814],{},"Addon rules: every addon belongs to the ticket type, required groups have a choice, single-choice groups have at\nmost one (400).",[175,816,817],{},"Addon capacity (409).",[175,819,820],{},"Ticket capacity (409).",[175,822,823,824,827],{},"The ",[182,825,826],{},"events:purchase:before"," hook.",[175,829,830,833],{},[182,831,832],{},"maxPerUser"," (409).",[159,835,836,837,839,840,843,844,847],{},"The seat is then taken. Capacity counts ",[182,838,194],{}," tickets plus ",[182,841,842],{},"pending"," ones inside the reservation window. D1 has no\ninteractive transactions, so after inserting the ticket the module verifies it is among the first ",[182,845,846],{},"capacity"," seat\nholders (insertion order) and removes it if it lost a race. An expired or failed payment frees its seat.",[306,849,851],{"className":308,"code":850,"language":310,"meta":311,"style":311},"type PurchaseBody = {\n  ticketTypeId: string\n  addonIds?: string[]\n  successUrl?: string\n  cancelUrl?: string\n  locale?: string      \u002F\u002F buyer's site language (e.g. 'da'), stored on the ticket for later mails and Stripe texts\n}\n\ntype PurchaseResponse = {\n  ticket: TicketDto\n  url?: string         \u002F\u002F Stripe redirect; absent for free tickets, which are already `paid`\n}\n",[182,852,853,868,878,892,901,910,923,928,934,946,957,970],{"__ignoreMap":311},[315,854,855,859,863,866],{"class":317,"line":318},[315,856,858],{"class":857},"spNyl","type",[315,860,862],{"class":861},"sBMFI"," PurchaseBody",[315,864,865],{"class":336}," =",[315,867,350],{"class":336},[315,869,870,873,875],{"class":317,"line":340},[315,871,872],{"class":343},"  ticketTypeId",[315,874,347],{"class":336},[315,876,877],{"class":861}," string\n",[315,879,880,883,886,889],{"class":317,"line":353},[315,881,882],{"class":343},"  addonIds",[315,884,885],{"class":336},"?:",[315,887,888],{"class":861}," string",[315,890,891],{"class":332},"[]\n",[315,893,894,897,899],{"class":317,"line":363},[315,895,896],{"class":343},"  successUrl",[315,898,885],{"class":336},[315,900,877],{"class":861},[315,902,903,906,908],{"class":317,"line":405},[315,904,905],{"class":343},"  cancelUrl",[315,907,885],{"class":336},[315,909,877],{"class":861},[315,911,912,915,917,919],{"class":317,"line":419},[315,913,914],{"class":343},"  locale",[315,916,885],{"class":336},[315,918,888],{"class":861},[315,920,922],{"class":921},"sHwdD","      \u002F\u002F buyer's site language (e.g. 'da'), stored on the ticket for later mails and Stripe texts\n",[315,924,925],{"class":317,"line":425},[315,926,927],{"class":336},"}\n",[315,929,930],{"class":317,"line":431},[315,931,933],{"emptyLinePlaceholder":932},true,"\n",[315,935,937,939,942,944],{"class":317,"line":936},9,[315,938,858],{"class":857},[315,940,941],{"class":861}," PurchaseResponse",[315,943,865],{"class":336},[315,945,350],{"class":336},[315,947,949,952,954],{"class":317,"line":948},10,[315,950,951],{"class":343},"  ticket",[315,953,347],{"class":336},[315,955,956],{"class":861}," TicketDto\n",[315,958,960,963,965,967],{"class":317,"line":959},11,[315,961,962],{"class":343},"  url",[315,964,885],{"class":336},[315,966,888],{"class":861},[315,968,969],{"class":921},"         \u002F\u002F Stripe redirect; absent for free tickets, which are already `paid`\n",[315,971,973],{"class":317,"line":972},12,[315,974,927],{"class":336},[159,976,977,978,981,982,984,985,988,989,992],{},"Check-in is idempotent: a second scan returns ",[182,979,980],{},"alreadyCheckedIn"," with the first scan time, and only ",[182,983,194],{}," tickets\nvalidate. A refund starts at Stripe; the ticket turns ",[182,986,987],{},"refunded"," when ",[182,990,991],{},"charge.refunded"," arrives, and partial refunds\nkeep the ticket valid.",[665,994,996],{"id":995},"seasonal-ticket-sales","Seasonal ticket sales",[159,998,999,1000,1002,1003,1006,1007,1010,1011,347],{},"A ticket type can carry a ",[182,1001,803],{}," on top of ",[182,1004,1005],{},"saleStartsAt"," \u002F ",[182,1008,1009],{},"saleEndsAt","; both must be open for a ticket to be\nsold. It uses the shared schedule of ",[182,1012,1013],{},"@frigear-nu\u002Fmodule-kit\u002Fschedule",[306,1015,1017],{"className":308,"code":1016,"language":310,"meta":311,"style":311},"type Schedule =\n  | { type: 'yearly', timezone: string, from: { month: number, day: number, time: string }, to: { month: number, day: number, time: string } }\n  | { type: 'range', from: string, to: string }\n\u002F\u002F null = always. A yearly `to` before `from` wraps over new year.\n",[182,1018,1019,1029,1133,1168],{"__ignoreMap":311},[315,1020,1021,1023,1026],{"class":317,"line":318},[315,1022,858],{"class":857},[315,1024,1025],{"class":861}," Schedule",[315,1027,1028],{"class":336}," =\n",[315,1030,1031,1034,1036,1039,1041,1044,1048,1051,1053,1056,1058,1060,1062,1065,1067,1069,1072,1074,1077,1079,1082,1084,1086,1088,1091,1093,1095,1098,1101,1103,1105,1107,1109,1111,1113,1115,1117,1119,1121,1123,1125,1127,1130],{"class":317,"line":340},[315,1032,1033],{"class":336},"  |",[315,1035,371],{"class":336},[315,1037,1038],{"class":343}," type",[315,1040,347],{"class":336},[315,1042,1043],{"class":336}," '",[315,1045,1047],{"class":1046},"sfazB","yearly",[315,1049,1050],{"class":336},"'",[315,1052,383],{"class":336},[315,1054,1055],{"class":343}," timezone",[315,1057,347],{"class":336},[315,1059,888],{"class":861},[315,1061,383],{"class":336},[315,1063,1064],{"class":343}," from",[315,1066,347],{"class":336},[315,1068,371],{"class":336},[315,1070,1071],{"class":343}," month",[315,1073,347],{"class":336},[315,1075,1076],{"class":861}," number",[315,1078,383],{"class":336},[315,1080,1081],{"class":343}," day",[315,1083,347],{"class":336},[315,1085,1076],{"class":861},[315,1087,383],{"class":336},[315,1089,1090],{"class":343}," time",[315,1092,347],{"class":336},[315,1094,888],{"class":861},[315,1096,1097],{"class":336}," },",[315,1099,1100],{"class":343}," to",[315,1102,347],{"class":336},[315,1104,371],{"class":336},[315,1106,1071],{"class":343},[315,1108,347],{"class":336},[315,1110,1076],{"class":861},[315,1112,383],{"class":336},[315,1114,1081],{"class":343},[315,1116,347],{"class":336},[315,1118,1076],{"class":861},[315,1120,383],{"class":336},[315,1122,1090],{"class":343},[315,1124,347],{"class":336},[315,1126,888],{"class":861},[315,1128,1129],{"class":336}," }",[315,1131,1132],{"class":336}," }\n",[315,1134,1135,1137,1139,1141,1143,1145,1148,1150,1152,1154,1156,1158,1160,1162,1164,1166],{"class":317,"line":353},[315,1136,1033],{"class":336},[315,1138,371],{"class":336},[315,1140,1038],{"class":343},[315,1142,347],{"class":336},[315,1144,1043],{"class":336},[315,1146,1147],{"class":1046},"range",[315,1149,1050],{"class":336},[315,1151,383],{"class":336},[315,1153,1064],{"class":343},[315,1155,347],{"class":336},[315,1157,888],{"class":861},[315,1159,383],{"class":336},[315,1161,1100],{"class":343},[315,1163,347],{"class":336},[315,1165,888],{"class":861},[315,1167,1132],{"class":336},[315,1169,1170],{"class":317,"line":363},[315,1171,1172],{"class":921},"\u002F\u002F null = always. A yearly `to` before `from` wraps over new year.\n",[159,1174,1175,1176,1179,1180,1182,1183,561],{},"Outside the schedule the ticket type is ",[182,1177,1178],{},"not_started"," (with ",[182,1181,1005],{}," set to the next opening) and purchases are\nrejected with ",[182,1184,1185],{},"409",[665,1187,1189],{"id":1188},"membership-providers","Membership providers",[159,1191,1192,1193,1197,1198,1201,1202,1205],{},"This module does not know what a membership is. A provider answers two Nitro hooks (see ",[163,1194,1196],{"href":1195},"#hooks","Hooks","):\n",[182,1199,1200],{},"events:membership:check"," decides whether a user holds a requirement, and ",[182,1203,1204],{},"events:membership:options"," turns on the\nmembership pickers in the admin UI and lists the choices. With no provider the API rejects membership rules, because a\nrequirement nobody can meet would silently lock the ticket.",[159,1207,1208,1210],{},[163,1209,125],{"href":126}," is the provider out of the box: when installed, plans are the memberships and\nholding one means an active subscription to it. Subscriptions itself knows nothing about events. Another source (a\npartner list, an imported roster) can be added with its own Nitro plugin:",[306,1212,1214],{"className":308,"code":1213,"language":310,"meta":311,"style":311},"export default defineNitroPlugin((nitro) => {\n  nitro.hooks.hook('events:membership:options', (ctx) => {\n    ctx.available = true\n    ctx.options.push({ value: 'volunteer', label: 'Volunteer' })\n  })\n  nitro.hooks.hook('events:membership:check', async (ctx) => {\n    if (await isVolunteer(ctx.userId)) ctx.satisfied = true\n  })\n})\n",[182,1215,1216,1240,1277,1292,1340,1347,1382,1418,1424],{"__ignoreMap":311},[315,1217,1218,1220,1222,1225,1227,1229,1233,1235,1238],{"class":317,"line":318},[315,1219,322],{"class":321},[315,1221,325],{"class":321},[315,1223,1224],{"class":328}," defineNitroPlugin",[315,1226,333],{"class":332},[315,1228,333],{"class":336},[315,1230,1232],{"class":1231},"sHdIc","nitro",[315,1234,624],{"class":336},[315,1236,1237],{"class":857}," =>",[315,1239,350],{"class":336},[315,1241,1242,1245,1247,1250,1252,1255,1257,1259,1261,1263,1265,1268,1271,1273,1275],{"class":317,"line":340},[315,1243,1244],{"class":332},"  nitro",[315,1246,561],{"class":336},[315,1248,1249],{"class":332},"hooks",[315,1251,561],{"class":336},[315,1253,1254],{"class":328},"hook",[315,1256,333],{"class":343},[315,1258,1050],{"class":336},[315,1260,1204],{"class":1046},[315,1262,1050],{"class":336},[315,1264,383],{"class":336},[315,1266,1267],{"class":336}," (",[315,1269,1270],{"class":1231},"ctx",[315,1272,624],{"class":336},[315,1274,1237],{"class":857},[315,1276,350],{"class":336},[315,1278,1279,1282,1284,1287,1289],{"class":317,"line":353},[315,1280,1281],{"class":332},"    ctx",[315,1283,561],{"class":336},[315,1285,1286],{"class":332},"available",[315,1288,865],{"class":336},[315,1290,1291],{"class":379}," true\n",[315,1293,1294,1296,1298,1300,1302,1305,1307,1310,1313,1315,1317,1320,1322,1324,1327,1329,1331,1334,1336,1338],{"class":317,"line":363},[315,1295,1281],{"class":332},[315,1297,561],{"class":336},[315,1299,460],{"class":332},[315,1301,561],{"class":336},[315,1303,1304],{"class":328},"push",[315,1306,333],{"class":343},[315,1308,1309],{"class":336},"{",[315,1311,1312],{"class":343}," value",[315,1314,347],{"class":336},[315,1316,1043],{"class":336},[315,1318,1319],{"class":1046},"volunteer",[315,1321,1050],{"class":336},[315,1323,383],{"class":336},[315,1325,1326],{"class":343}," label",[315,1328,347],{"class":336},[315,1330,1043],{"class":336},[315,1332,1333],{"class":1046},"Volunteer",[315,1335,1050],{"class":336},[315,1337,1129],{"class":336},[315,1339,437],{"class":343},[315,1341,1342,1345],{"class":317,"line":405},[315,1343,1344],{"class":336},"  }",[315,1346,437],{"class":343},[315,1348,1349,1351,1353,1355,1357,1359,1361,1363,1365,1367,1369,1372,1374,1376,1378,1380],{"class":317,"line":419},[315,1350,1244],{"class":332},[315,1352,561],{"class":336},[315,1354,1249],{"class":332},[315,1356,561],{"class":336},[315,1358,1254],{"class":328},[315,1360,333],{"class":343},[315,1362,1050],{"class":336},[315,1364,1200],{"class":1046},[315,1366,1050],{"class":336},[315,1368,383],{"class":336},[315,1370,1371],{"class":857}," async",[315,1373,1267],{"class":336},[315,1375,1270],{"class":1231},[315,1377,624],{"class":336},[315,1379,1237],{"class":857},[315,1381,350],{"class":336},[315,1383,1384,1387,1389,1392,1395,1397,1399,1401,1404,1407,1409,1411,1414,1416],{"class":317,"line":425},[315,1385,1386],{"class":321},"    if",[315,1388,1267],{"class":343},[315,1390,1391],{"class":321},"await",[315,1393,1394],{"class":328}," isVolunteer",[315,1396,333],{"class":343},[315,1398,1270],{"class":332},[315,1400,561],{"class":336},[315,1402,1403],{"class":332},"userId",[315,1405,1406],{"class":343},")) ",[315,1408,1270],{"class":332},[315,1410,561],{"class":336},[315,1412,1413],{"class":332},"satisfied",[315,1415,865],{"class":336},[315,1417,1291],{"class":379},[315,1419,1420,1422],{"class":317,"line":431},[315,1421,1344],{"class":336},[315,1423,437],{"class":343},[315,1425,1426,1428],{"class":317,"line":936},[315,1427,434],{"class":336},[315,1429,437],{"class":332},[665,1431,1433],{"id":1432},"staff-authorization","Staff authorization",[159,1435,1436,1437,1440,1441,1444,1445,1447,1448,1450,1451,1454],{},"Staff routes need the ",[182,1438,1439],{},"events:manage"," scope ",[167,1442,1443],{},"and"," an allowing ",[182,1446,218],{}," hook. ",[182,1449,1439],{}," and\n",[182,1452,1453],{},"events:pii"," are only offered to users that hook lets in.",[306,1456,1458],{"className":308,"code":1457,"language":310,"meta":311,"style":311},"export default defineNitroPlugin((nitro) => {\n  nitro.hooks.hook('events:authorize', async (ctx) => {\n    ctx.allowed = await isEventStaff(ctx.userId)\n  })\n})\n",[182,1459,1460,1480,1514,1541,1547],{"__ignoreMap":311},[315,1461,1462,1464,1466,1468,1470,1472,1474,1476,1478],{"class":317,"line":318},[315,1463,322],{"class":321},[315,1465,325],{"class":321},[315,1467,1224],{"class":328},[315,1469,333],{"class":332},[315,1471,333],{"class":336},[315,1473,1232],{"class":1231},[315,1475,624],{"class":336},[315,1477,1237],{"class":857},[315,1479,350],{"class":336},[315,1481,1482,1484,1486,1488,1490,1492,1494,1496,1498,1500,1502,1504,1506,1508,1510,1512],{"class":317,"line":340},[315,1483,1244],{"class":332},[315,1485,561],{"class":336},[315,1487,1249],{"class":332},[315,1489,561],{"class":336},[315,1491,1254],{"class":328},[315,1493,333],{"class":343},[315,1495,1050],{"class":336},[315,1497,218],{"class":1046},[315,1499,1050],{"class":336},[315,1501,383],{"class":336},[315,1503,1371],{"class":857},[315,1505,1267],{"class":336},[315,1507,1270],{"class":1231},[315,1509,624],{"class":336},[315,1511,1237],{"class":857},[315,1513,350],{"class":336},[315,1515,1516,1518,1520,1523,1525,1528,1531,1533,1535,1537,1539],{"class":317,"line":353},[315,1517,1281],{"class":332},[315,1519,561],{"class":336},[315,1521,1522],{"class":332},"allowed",[315,1524,865],{"class":336},[315,1526,1527],{"class":321}," await",[315,1529,1530],{"class":328}," isEventStaff",[315,1532,333],{"class":343},[315,1534,1270],{"class":332},[315,1536,561],{"class":336},[315,1538,1403],{"class":332},[315,1540,437],{"class":343},[315,1542,1543,1545],{"class":317,"line":363},[315,1544,1344],{"class":336},[315,1546,437],{"class":343},[315,1548,1549,1551],{"class":317,"line":405},[315,1550,434],{"class":336},[315,1552,437],{"class":332},[665,1554,534],{"id":1555},"mcp-tools",[159,1557,1558,1559,1562,1563,1565,1566,716,1568,1570,1571,1573,1574,1577,1578,1581],{},"With ",[182,1560,1561],{},"settings.mcp: true",", the tools below are exposed on the ",[163,1564,93],{"href":94}," endpoint. Staff tools need\n",[182,1567,1439],{},[182,1569,218],{}," policy; attendee names and emails also need ",[182,1572,1453],{},". Prices and amounts in MCP inputs and outputs are whole currency\nunits (",[182,1575,1576],{},"52.2"," = 52.20, ",[182,1579,1580],{},"500"," JPY), unlike the REST API and database, which use minor units.",[463,1583,1584,1596],{},[466,1585,1586],{},[469,1587,1588,1591,1594],{},[472,1589,1590],{},"Tool",[472,1592,1593],{},"Scope",[472,1595,483],{},[485,1597,1598,1616,1630],{},[469,1599,1600,1608,1613],{},[490,1601,1602,234,1605],{},[182,1603,1604],{},"list-events",[182,1606,1607],{},"get-event",[490,1609,1610],{},[182,1611,1612],{},"tickets:read",[490,1614,1615],{},"Public events and details.",[469,1617,1618,1623,1627],{},[490,1619,1620],{},[182,1621,1622],{},"my-tickets",[490,1624,1625],{},[182,1626,1612],{},[490,1628,1629],{},"The caller's tickets.",[469,1631,1632,1652,1656],{},[490,1633,1634,234,1637,234,1640,234,1643,234,1646,234,1649],{},[182,1635,1636],{},"list-all-events",[182,1638,1639],{},"get-event-definition",[182,1641,1642],{},"create-event",[182,1644,1645],{},"update-event",[182,1647,1648],{},"update-ticket-type",[182,1650,1651],{},"list-attendees",[490,1653,1654],{},[182,1655,1439],{},[490,1657,1658],{},"Staff catalogue management and attendees.",[301,1660,1662],{"id":1661},"app","App",[463,1664,1665,1675],{},[466,1666,1667],{},[469,1668,1669,1672],{},[472,1670,1671],{},"Export",[472,1673,1674],{},"Description",[485,1676,1677,1703,1715,1727,1755,1780,1795,1807],{},[469,1678,1679,1684],{},[490,1680,1681],{},[182,1682,1683],{},"useEvents()",[490,1685,1686,1689,1690,1693,1694,234,1697,234,1700,561],{},[182,1687,1688],{},"{ events, grouped, status, refresh }","; ",[182,1691,1692],{},"grouped"," splits into ",[182,1695,1696],{},"ongoing",[182,1698,1699],{},"upcoming",[182,1701,1702],{},"past",[469,1704,1705,1710],{},[490,1706,1707],{},[182,1708,1709],{},"useEvent(slug)",[490,1711,1712,561],{},[182,1713,1714],{},"{ event, status, error, refresh, purchase(ticketTypeId, addonIds?) }",[469,1716,1717,1722],{},[490,1718,1719],{},[182,1720,1721],{},"useMyTickets()",[490,1723,1724,561],{},[182,1725,1726],{},"{ tickets, status, refresh, pay(ticketId) }",[469,1728,1729,1733],{},[490,1730,1731],{},[182,1732,768],{},[490,1734,1735,1736,234,1739,234,1742,234,1745,234,1748,1751,1752,561],{},"Locale-aware links: ",[182,1737,1738],{},"events()",[182,1740,1741],{},"event(slug)",[182,1743,1744],{},"tickets()",[182,1746,1747],{},"admin()",[182,1749,1750],{},"adminEvent(id)",". Follows ",[182,1753,1754],{},"settings.pages",[469,1756,1757,1762],{},[490,1758,1759],{},[182,1760,1761],{},"useEventActions()",[490,1763,1764,1765,1768,1769,234,1772,1775,1776,1779],{},"Staff actions: ",[182,1766,1767],{},"create()"," (slideover, resolves with the new event), ",[182,1770,1771],{},"duplicate(event)",[182,1773,1774],{},"remove(event)"," (confirms), ",[182,1777,1778],{},"menu(event, { extra?, onRemoved? })"," for the row menu.",[469,1781,1782,1787],{},[490,1783,1784],{},[182,1785,1786],{},"useEventsLocale()",[490,1788,1789,1790,1792,1793,561],{},"Current locale: ",[182,1791,452],{},"'s, else ",[182,1794,456],{},[469,1796,1797,1802],{},[490,1798,1799],{},[182,1800,1801],{},"useEventsFallbackLocale()",[490,1803,1804,1805,561],{},"The site's default locale, else ",[182,1806,456],{},[469,1808,1809,1814],{},[490,1810,1811],{},[182,1812,1813],{},"useEventsTranslate()",[490,1815,1816,1819,1820,1823,1824,561],{},[182,1817,1818],{},"tr(value)",": a ",[182,1821,1822],{},"Translated"," text in the current locale, falling back to the default, then ",[182,1825,456],{},[159,1827,1828,1829,234,1832,234,1835,1837,1838,1840,1841,1844,1845,1848,1849,234,1852,240,1855,1858],{},"Components: ",[182,1830,1831],{},"EventCard",[182,1833,1834],{},"EventTicketPicker",[182,1836,731],{}," (with QR code), ",[182,1839,708],{}," (create an event) and\nthe ",[182,1842,1843],{},"EventAdmin*"," dialogs used by the admin pages. ",[182,1846,1847],{},"@frigear-nu\u002Fevents\u002Futils"," exports the DTO and hook types, ",[182,1850,1851],{},"translate",[182,1853,1854],{},"normalizeMembership",[182,1856,1857],{},"DEFAULT_CURRENCY"," and id helpers.",[665,1860,1862],{"id":1861},"extending-the-admin-event-page","Extending the admin event page",[159,1864,1865,1866,1868,1869,1871,1872,234,1875,261,1878,1881,1882,1885,1886,1889,1890,1893,1894,1897,1898,561],{},"The page shows status, dates and location, and below them a tab view over the ",[182,1867,719],{}," tab area of\n",[163,1870,137],{"href":138},", which this module owns. It registers ",[167,1873,1874],{},"Details",[167,1876,1877],{},"Tickets",[167,1879,1880],{},"Attendees"," tabs; any\nmodule can add more with ",[182,1883,1884],{},"extendTabs(nuxt, 'admin.events', { ... })",". Each tab component receives ",[182,1887,1888],{},"event"," (the response\nof ",[182,1891,1892],{},"GET \u002Fapi\u002Fevents\u002Fadmin\u002Fevents\u002F:id",") as a prop and may emit ",[182,1895,1896],{},"refresh",". Without Widget the three built-in tabs render\nstacked. Hiding a tab is not access control: authorize its API calls through ",[182,1899,218],{},[301,1901,1196],{"id":1249},[159,1903,1904,1905,1908],{},"Register with ",[182,1906,1907],{},"nitro.hooks.hook(...)"," in a Nitro plugin.",[463,1910,1911,1924],{},[466,1912,1913],{},[469,1914,1915,1918,1921],{},[472,1916,1917],{},"Hook",[472,1919,1920],{},"When",[472,1922,1923],{},"Payload",[485,1925,1926,1940,1954,1969,1983,1997],{},[469,1927,1928,1932,1935],{},[490,1929,1930],{},[182,1931,218],{},[490,1933,1934],{},"Staff gate for management routes, check-in and staff scopes.",[490,1936,1937],{},[182,1938,1939],{},"AuthorizeContext",[469,1941,1942,1946,1949],{},[490,1943,1944],{},[182,1945,826],{},[490,1947,1948],{},"During purchase, after the capacity checks; throw to deny.",[490,1950,1951],{},[182,1952,1953],{},"PurchaseBeforeContext",[469,1955,1956,1961,1964],{},[490,1957,1958],{},[182,1959,1960],{},"events:ticket:paid",[490,1962,1963],{},"A ticket became paid (free tickets immediately). Send confirmations here.",[490,1965,1966],{},[182,1967,1968],{},"TicketHookContext",[469,1970,1971,1976,1979],{},[490,1972,1973],{},[182,1974,1975],{},"events:ticket:refunded",[490,1977,1978],{},"A ticket was fully refunded.",[490,1980,1981],{},[182,1982,1968],{},[469,1984,1985,1989,1992],{},[490,1986,1987],{},[182,1988,1200],{},[490,1990,1991],{},"A membership requirement is evaluated.",[490,1993,1994],{},[182,1995,1996],{},"MembershipCheckContext",[469,1998,1999,2003,2006],{},[490,2000,2001],{},[182,2002,1204],{},[490,2004,2005],{},"The admin UI asks which memberships can be picked.",[490,2007,2008],{},[182,2009,2010],{},"MembershipOptionsContext",[306,2012,2014],{"className":308,"code":2013,"language":310,"meta":311,"style":311},"type AuthorizeContext = { event: H3Event, userId: number, allowed: boolean }          \u002F\u002F set allowed = true\ntype PurchaseBeforeContext = { event: H3Event, userId: number, eventId: string, ticketTypeId: string, addonIds: string[] }\ntype TicketHookContext = { ticket: TicketDto }\ntype MembershipCheckContext = { userId: number, requirement: 'any' | string[], satisfied: boolean }\ntype MembershipOptionsContext = { available: boolean, options: Array\u003C{ value: string, label: string }> }\n",[182,2015,2016,2058,2115,2136,2186],{"__ignoreMap":311},[315,2017,2018,2020,2023,2025,2027,2029,2031,2034,2036,2039,2041,2043,2045,2048,2050,2053,2055],{"class":317,"line":318},[315,2019,858],{"class":857},[315,2021,2022],{"class":861}," AuthorizeContext",[315,2024,865],{"class":336},[315,2026,371],{"class":336},[315,2028,386],{"class":343},[315,2030,347],{"class":336},[315,2032,2033],{"class":861}," H3Event",[315,2035,383],{"class":336},[315,2037,2038],{"class":343}," userId",[315,2040,347],{"class":336},[315,2042,1076],{"class":861},[315,2044,383],{"class":336},[315,2046,2047],{"class":343}," allowed",[315,2049,347],{"class":336},[315,2051,2052],{"class":861}," boolean",[315,2054,1129],{"class":336},[315,2056,2057],{"class":921},"          \u002F\u002F set allowed = true\n",[315,2059,2060,2062,2065,2067,2069,2071,2073,2075,2077,2079,2081,2083,2085,2088,2090,2092,2094,2097,2099,2101,2103,2106,2108,2110,2113],{"class":317,"line":340},[315,2061,858],{"class":857},[315,2063,2064],{"class":861}," PurchaseBeforeContext",[315,2066,865],{"class":336},[315,2068,371],{"class":336},[315,2070,386],{"class":343},[315,2072,347],{"class":336},[315,2074,2033],{"class":861},[315,2076,383],{"class":336},[315,2078,2038],{"class":343},[315,2080,347],{"class":336},[315,2082,1076],{"class":861},[315,2084,383],{"class":336},[315,2086,2087],{"class":343}," eventId",[315,2089,347],{"class":336},[315,2091,888],{"class":861},[315,2093,383],{"class":336},[315,2095,2096],{"class":343}," ticketTypeId",[315,2098,347],{"class":336},[315,2100,888],{"class":861},[315,2102,383],{"class":336},[315,2104,2105],{"class":343}," addonIds",[315,2107,347],{"class":336},[315,2109,888],{"class":861},[315,2111,2112],{"class":332},"[] ",[315,2114,927],{"class":336},[315,2116,2117,2119,2122,2124,2126,2129,2131,2134],{"class":317,"line":353},[315,2118,858],{"class":857},[315,2120,2121],{"class":861}," TicketHookContext",[315,2123,865],{"class":336},[315,2125,371],{"class":336},[315,2127,2128],{"class":343}," ticket",[315,2130,347],{"class":336},[315,2132,2133],{"class":861}," TicketDto",[315,2135,1132],{"class":336},[315,2137,2138,2140,2143,2145,2147,2149,2151,2153,2155,2158,2160,2162,2165,2167,2170,2172,2175,2177,2180,2182,2184],{"class":317,"line":363},[315,2139,858],{"class":857},[315,2141,2142],{"class":861}," MembershipCheckContext",[315,2144,865],{"class":336},[315,2146,371],{"class":336},[315,2148,2038],{"class":343},[315,2150,347],{"class":336},[315,2152,1076],{"class":861},[315,2154,383],{"class":336},[315,2156,2157],{"class":343}," requirement",[315,2159,347],{"class":336},[315,2161,1043],{"class":336},[315,2163,2164],{"class":1046},"any",[315,2166,1050],{"class":336},[315,2168,2169],{"class":336}," |",[315,2171,888],{"class":861},[315,2173,2174],{"class":332},"[]",[315,2176,383],{"class":336},[315,2178,2179],{"class":343}," satisfied",[315,2181,347],{"class":336},[315,2183,2052],{"class":861},[315,2185,1132],{"class":336},[315,2187,2188,2190,2193,2195,2197,2200,2202,2204,2206,2209,2211,2214,2217,2219,2221,2223,2225,2227,2229,2231,2234],{"class":317,"line":405},[315,2189,858],{"class":857},[315,2191,2192],{"class":861}," MembershipOptionsContext",[315,2194,865],{"class":336},[315,2196,371],{"class":336},[315,2198,2199],{"class":343}," available",[315,2201,347],{"class":336},[315,2203,2052],{"class":861},[315,2205,383],{"class":336},[315,2207,2208],{"class":343}," options",[315,2210,347],{"class":336},[315,2212,2213],{"class":861}," Array",[315,2215,2216],{"class":336},"\u003C{",[315,2218,1312],{"class":343},[315,2220,347],{"class":336},[315,2222,888],{"class":861},[315,2224,383],{"class":336},[315,2226,1326],{"class":343},[315,2228,347],{"class":336},[315,2230,888],{"class":861},[315,2232,2233],{"class":336}," }>",[315,2235,1132],{"class":336},[159,2237,2238,261,2241,758,2244,2247,2248,2251],{},[182,2239,2240],{},"requiresMembership",[182,2242,2243],{},"excludesMembership",[182,2245,2246],{},"null"," (nobody \u002F everyone), ",[182,2249,2250],{},"'any'"," (any active membership) or a list\nof membership keys.",[301,2253,2255],{"id":2254},"routes","Routes",[159,2257,2258,2259,2262],{},"All paths are under ",[182,2260,2261],{},"\u002Fapi\u002Fevents",". User routes also accept bearer and OAuth tokens that carry the scope.",[463,2264,2265,2279],{},[466,2266,2267],{},[469,2268,2269,2272,2275,2277],{},[472,2270,2271],{},"Method",[472,2273,2274],{},"Path",[472,2276,73],{},[472,2278,483],{},[485,2280,2281,2297,2318,2336,2351,2367,2383,2402,2416,2430,2444,2465,2479,2493,2508,2522,2536,2550,2564,2578],{},[469,2282,2283,2286,2291,2294],{},[490,2284,2285],{},"GET",[490,2287,2288],{},[182,2289,2290],{},"\u002F",[490,2292,2293],{},"public",[490,2295,2296],{},"Published events.",[469,2298,2299,2301,2306,2311],{},[490,2300,2285],{},[490,2302,2303],{},[182,2304,2305],{},"\u002F:slug",[490,2307,2308,2309,624],{},"public (optional ",[182,2310,1612],{},[490,2312,2313,2314,2317],{},"Event detail; includes per-user ",[182,2315,2316],{},"blocked"," flags when signed in.",[469,2319,2320,2323,2328,2333],{},[490,2321,2322],{},"POST",[490,2324,2325],{},[182,2326,2327],{},"\u002F:slug\u002Fpurchase",[490,2329,2330],{},[182,2331,2332],{},"tickets:write",[490,2334,2335],{},"Buy a ticket.",[469,2337,2338,2340,2345,2349],{},[490,2339,2285],{},[490,2341,2342],{},[182,2343,2344],{},"\u002Ftickets\u002Fme",[490,2346,2347],{},[182,2348,1612],{},[490,2350,1629],{},[469,2352,2353,2355,2360,2364],{},[490,2354,2285],{},[490,2356,2357],{},[182,2358,2359],{},"\u002Ftickets\u002F:id",[490,2361,2362],{},[182,2363,1612],{},[490,2365,2366],{},"One ticket (poll after returning from Stripe).",[469,2368,2369,2371,2376,2380],{},[490,2370,2322],{},[490,2372,2373],{},[182,2374,2375],{},"\u002Ftickets\u002F:id\u002Fpay",[490,2377,2378],{},[182,2379,2332],{},[490,2381,2382],{},"Resume payment of a pending ticket.",[469,2384,2385,2387,2392,2395],{},[490,2386,2322],{},[490,2388,2389],{},[182,2390,2391],{},"\u002Fcheck-in",[490,2393,2394],{},"staff",[490,2396,2397,2398,2401],{},"Body ",[182,2399,2400],{},"{ code }",". Check a ticket in.",[469,2403,2404,2406,2411,2413],{},[490,2405,2285],{},[490,2407,2408],{},[182,2409,2410],{},"\u002Fadmin\u002Fmembership-options",[490,2412,2394],{},[490,2414,2415],{},"Selectable memberships from the provider.",[469,2417,2418,2421,2425,2427],{},[490,2419,2420],{},"GET, POST",[490,2422,2423],{},[182,2424,636],{},[490,2426,2394],{},[490,2428,2429],{},"List events; create one (accepts the whole nested catalogue).",[469,2431,2432,2435,2439,2441],{},[490,2433,2434],{},"GET, PATCH, DELETE",[490,2436,2437],{},[182,2438,663],{},[490,2440,2394],{},[490,2442,2443],{},"One event with all ticket types whatever its status; update; delete.",[469,2445,2446,2448,2453,2455],{},[490,2447,2322],{},[490,2449,2450],{},[182,2451,2452],{},"\u002Fadmin\u002Fevents\u002F:id\u002Fclone",[490,2454,2394],{},[490,2456,2457,2458,234,2461,2464],{},"Copy into a new draft (",[182,2459,2460],{},"\u003Cslug>-copy",[182,2462,2463],{},"-copy-2",", ...). Tickets are not copied; dates stay.",[469,2466,2467,2469,2474,2476],{},[490,2468,2285],{},[490,2470,2471],{},[182,2472,2473],{},"\u002Fadmin\u002Fevents\u002F:id\u002Ftickets",[490,2475,2394],{},[490,2477,2478],{},"Attendees.",[469,2480,2481,2483,2488,2490],{},[490,2482,2322],{},[490,2484,2485],{},[182,2486,2487],{},"\u002Fadmin\u002Fevents\u002F:id\u002Fticket-types",[490,2489,2394],{},[490,2491,2492],{},"Add a ticket type.",[469,2494,2495,2498,2503,2505],{},[490,2496,2497],{},"PATCH, DELETE",[490,2499,2500],{},[182,2501,2502],{},"\u002Fadmin\u002Fticket-types\u002F:id",[490,2504,2394],{},[490,2506,2507],{},"Update or delete a ticket type.",[469,2509,2510,2512,2517,2519],{},[490,2511,2322],{},[490,2513,2514],{},[182,2515,2516],{},"\u002Fadmin\u002Fticket-types\u002F:id\u002Faddon-groups",[490,2518,2394],{},[490,2520,2521],{},"Add an addon group.",[469,2523,2524,2526,2531,2533],{},[490,2525,2497],{},[490,2527,2528],{},[182,2529,2530],{},"\u002Fadmin\u002Faddon-groups\u002F:id",[490,2532,2394],{},[490,2534,2535],{},"Update or delete an addon group.",[469,2537,2538,2540,2545,2547],{},[490,2539,2322],{},[490,2541,2542],{},[182,2543,2544],{},"\u002Fadmin\u002Faddon-groups\u002F:id\u002Faddons",[490,2546,2394],{},[490,2548,2549],{},"Add an addon.",[469,2551,2552,2554,2559,2561],{},[490,2553,2497],{},[490,2555,2556],{},[182,2557,2558],{},"\u002Fadmin\u002Faddons\u002F:id",[490,2560,2394],{},[490,2562,2563],{},"Update or delete an addon.",[469,2565,2566,2568,2573,2575],{},[490,2567,2322],{},[490,2569,2570],{},[182,2571,2572],{},"\u002Fadmin\u002Ftickets\u002F:id\u002Fcancel",[490,2574,2394],{},[490,2576,2577],{},"Cancel a ticket.",[469,2579,2580,2582,2587,2589],{},[490,2581,2322],{},[490,2583,2584],{},[182,2585,2586],{},"\u002Fadmin\u002Ftickets\u002F:id\u002Frefund",[490,2588,2394],{},[490,2590,2591],{},"Start a full refund (only paid tickets with a payment).",[159,2593,2594,2595,2597,2598,827],{},"\"staff\" means the ",[182,2596,1439],{}," scope plus an allowing ",[163,2599,2601],{"href":2600},"#staff-authorization",[182,2602,218],{},[301,2604,2606],{"id":2605},"database","Database",[463,2608,2609,2618],{},[466,2610,2611],{},[469,2612,2613,2616],{},[472,2614,2615],{},"Table",[472,2617,483],{},[485,2619,2620,2671,2727,2747,2767],{},[469,2621,2622,2626],{},[490,2623,2624],{},[182,2625,633],{},[490,2627,2628,2631,2632,1006,2635,1006,2638,234,2641,234,2644,234,2647,234,2650,1006,2653,234,2656,1267,2659,234,2662,234,2665,2668,2669,561],{},[182,2629,2630],{},"slug",", translated ",[182,2633,2634],{},"name",[182,2636,2637],{},"description",[182,2639,2640],{},"body",[182,2642,2643],{},"image",[182,2645,2646],{},"location",[182,2648,2649],{},"locationUrl",[182,2651,2652],{},"startsAt",[182,2654,2655],{},"endsAt",[182,2657,2658],{},"status",[182,2660,2661],{},"draft",[182,2663,2664],{},"published",[182,2666,2667],{},"archived","), event-level ",[182,2670,2240],{},[469,2672,2673,2678],{},[490,2674,2675],{},[182,2676,2677],{},"event_ticket_types",[490,2679,2680,2681,2684,2685,234,2687,234,2689,1267,2692,2694,2695,2698,2699,2702,2703,234,2706,234,2708,1006,2710,234,2712,234,2714,2716,2717,234,2719,234,2721,234,2724,561],{},"Per event: ",[182,2682,2683],{},"key"," (unique per event), ",[182,2686,2634],{},[182,2688,2637],{},[182,2690,2691],{},"price",[182,2693,202],{}," = free), ",[182,2696,2697],{},"currency"," (default ",[182,2700,2701],{},"DKK","), ",[182,2704,2705],{},"hidePrice",[182,2707,846],{},[182,2709,1005],{},[182,2711,1009],{},[182,2713,803],{},[182,2715,832],{}," (default 1), ",[182,2718,2240],{},[182,2720,2243],{},[182,2722,2723],{},"isDefault",[182,2725,2726],{},"sortOrder",[469,2728,2729,2734],{},[490,2730,2731],{},[182,2732,2733],{},"event_addon_groups",[490,2735,2736,2737,2740,2741,2744,2745,561],{},"Per ticket type, e.g. \"Food\": ",[182,2738,2739],{},"required"," (pick at least one), ",[182,2742,2743],{},"multiple"," (pick several), ",[182,2746,2726],{},[469,2748,2749,2754],{},[490,2750,2751],{},[182,2752,2753],{},"event_addons",[490,2755,2756,2757,234,2760,2762,2763,234,2765,561],{},"Choices in a group: ",[182,2758,2759],{},"label",[182,2761,2691],{},", optional ",[182,2764,846],{},[182,2766,2726],{},[469,2768,2769,2774],{},[490,2770,2771],{},[182,2772,2773],{},"event_tickets",[490,2775,2776,2777,1267,2779,234,2781,234,2783,234,2786,234,2788,2702,2791,234,2794,261,2797,2799,2800,2803,2804,234,2806,234,2809,234,2812,561],{},"Purchased or reserved tickets: ",[182,2778,2658],{},[182,2780,842],{},[182,2782,194],{},[182,2784,2785],{},"cancelled",[182,2787,987],{},[182,2789,2790],{},"expired",[182,2792,2793],{},"addons",[182,2795,2796],{},"amount",[182,2798,2697],{}," snapshot, ",[182,2801,2802],{},"paymentId",", unique QR ",[182,2805,182],{},[182,2807,2808],{},"locale",[182,2810,2811],{},"checkedInAt",[182,2813,2814],{},"checkedInBy",[159,2816,2817,2818,2821,2822,535],{},"Translated texts are a string or a ",[182,2819,2820],{},"{ da, en }"," map (",[182,2823,1822],{},[2825,2826,2827,2828,561],"warning",{},"The module changes the generated schema, not the database: generate and commit a migration in every host app and\nfixture that uses it (including the Payments, Users and Subscriptions tables it relies on). See\n",[163,2829,101],{"href":102},[301,2831,2833],{"id":2832},"translations","Translations",[159,2835,2836,261,2839,2841,2842,2845,2846,2849,2850,234,2853,234,2856,234,2859,2862,2863,2866,2867,2702,2870,234,2873,234,2876,2879,2880,261,2883,2886,2887,234,2890,234,2893,234,2896,234,2899,261,2902,2905,2906,2909,2910,2914],{},[182,2837,2838],{},"da",[182,2840,456],{}," locale files are registered with ",[163,2843,101],{"href":2844},"\u002Fmodules\u002Fmodule-kit#translations-i18n"," under ",[182,2847,2848],{},"events.*",".\nKey groups: ",[182,2851,2852],{},"upcoming.*",[182,2854,2855],{},"ongoing.*",[182,2857,2858],{},"past.*",[182,2860,2861],{},"detail.*"," (including the purchase flow), ",[182,2864,2865],{},"tickets.*","\n(including ",[182,2868,2869],{},"tickets.status.*",[182,2871,2872],{},"cart.*",[182,2874,2875],{},"menu.*",[182,2877,2878],{},"admin.*"," (including ",[182,2881,2882],{},"admin.tabs.*",[182,2884,2885],{},"admin.statuses.*","), plus top-level messages such as\n",[182,2888,2889],{},"title",[182,2891,2892],{},"empty",[182,2894,2895],{},"loading",[182,2897,2898],{},"ticketReady",[182,2900,2901],{},"paymentReceived",[182,2903,2904],{},"purchaseFailed",". Override any string in your app's\n",[182,2907,2908],{},"i18n\u002Flocales\u002F\u003Ccode>.json"," (see\n",[163,2911,2913],{"href":2912},"\u002Fmodules\u002Fmodule-kit#overriding-module-strings-in-your-app","overriding module strings","):",[306,2916,2920],{"className":2917,"code":2918,"language":2919,"meta":311,"style":311},"language-json shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","{ \"events\": { \"upcoming\": { \"title\": \"What's on\" } } }\n","json",[182,2921,2922],{"__ignoreMap":311},[315,2923,2924,2926,2929,2931,2934,2936,2938,2940,2942,2944,2946,2948,2950,2952,2954,2956,2958,2961,2963,2965,2967],{"class":317,"line":318},[315,2925,1309],{"class":336},[315,2927,2928],{"class":336}," \"",[315,2930,633],{"class":857},[315,2932,2933],{"class":336},"\"",[315,2935,347],{"class":336},[315,2937,371],{"class":336},[315,2939,2928],{"class":336},[315,2941,1699],{"class":861},[315,2943,2933],{"class":336},[315,2945,347],{"class":336},[315,2947,371],{"class":336},[315,2949,2928],{"class":336},[315,2951,2889],{"class":413},[315,2953,2933],{"class":336},[315,2955,347],{"class":336},[315,2957,2928],{"class":336},[315,2959,2960],{"class":1046},"What's on",[315,2962,2933],{"class":336},[315,2964,1129],{"class":336},[315,2966,1129],{"class":336},[315,2968,1132],{"class":336},[2970,2971,2972],"style",{},"html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}",{"title":311,"searchDepth":340,"depth":340,"links":2974},[2975,2976,2979,2986,2989,2990,2991,2992],{"id":303,"depth":340,"text":304},{"id":460,"depth":340,"text":461,"children":2977},[2978],{"id":667,"depth":353,"text":668},{"id":780,"depth":340,"text":781,"children":2980},[2981,2982,2983,2984,2985],{"id":784,"depth":353,"text":785},{"id":995,"depth":353,"text":996},{"id":1188,"depth":353,"text":1189},{"id":1432,"depth":353,"text":1433},{"id":1555,"depth":353,"text":534},{"id":1661,"depth":340,"text":1662,"children":2987},[2988],{"id":1861,"depth":353,"text":1862},{"id":1249,"depth":340,"text":1196},{"id":2254,"depth":340,"text":2255},{"id":2605,"depth":340,"text":2606},{"id":2832,"depth":340,"text":2833},"Database-backed events with ticket types, addons, capacity, sale windows, membership requirements, Stripe payments and QR check-in.","md",null,{},{"title":85,"description":2993},"7Rqka9FLjdHSJBAbJ-5oQxo6FlAo1-SRMgJivy4y7os",[3000,3002],{"title":81,"path":82,"stem":83,"description":3001,"children":-1},"GDPR cookie banner with categories other modules contribute to, consent gating hooks and proof of consent stored on the user.",{"title":89,"path":90,"stem":91,"description":3003,"children":-1},"Dynamic forms stored in the database - single page or stepped, conditional fields, file uploads, stored or email-only submissions.",1792824488867]