@antlur/backstage 1.0.9 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/client.js +18 -5
- package/dist/cjs/components/json-ld.js +8 -0
- package/dist/cjs/config.js +2 -3
- package/dist/cjs/endpoints/alerts.js +8 -6
- package/dist/cjs/endpoints/base.js +9 -0
- package/dist/cjs/endpoints/events.js +16 -19
- package/dist/cjs/endpoints/locations.js +21 -20
- package/dist/cjs/endpoints/menus.js +23 -23
- package/dist/cjs/endpoints/navigation.js +26 -26
- package/dist/cjs/endpoints/pages.js +20 -21
- package/dist/cjs/endpoints/press.js +8 -6
- package/dist/cjs/endpoints/website.js +8 -6
- package/dist/cjs/util/event.js +70 -0
- package/dist/cjs/util/gtag.js +14 -0
- package/dist/cjs/util/imgproxy-loader.js +14 -0
- package/dist/cjs/util/publishing.js +6 -0
- package/dist/cjs/util/special-hours.js +23 -0
- package/dist/esm/client.d.ts +16 -1
- package/dist/esm/client.d.ts.map +1 -1
- package/dist/esm/client.js +17 -3
- package/dist/esm/components/json-ld.d.ts +7 -0
- package/dist/esm/components/json-ld.d.ts.map +1 -0
- package/dist/esm/components/json-ld.js +5 -0
- package/dist/esm/endpoints/alerts.d.ts +4 -1
- package/dist/esm/endpoints/alerts.d.ts.map +1 -1
- package/dist/esm/endpoints/alerts.js +6 -4
- package/dist/esm/endpoints/base.d.ts +6 -0
- package/dist/esm/endpoints/base.d.ts.map +1 -0
- package/dist/esm/endpoints/base.js +5 -0
- package/dist/esm/endpoints/events.d.ts +6 -3
- package/dist/esm/endpoints/events.d.ts.map +1 -1
- package/dist/esm/endpoints/events.js +14 -15
- package/dist/esm/endpoints/locations.d.ts +5 -2
- package/dist/esm/endpoints/locations.d.ts.map +1 -1
- package/dist/esm/endpoints/locations.js +19 -17
- package/dist/esm/endpoints/menus.d.ts +6 -3
- package/dist/esm/endpoints/menus.d.ts.map +1 -1
- package/dist/esm/endpoints/menus.js +21 -19
- package/dist/esm/endpoints/navigation.d.ts +6 -3
- package/dist/esm/endpoints/navigation.d.ts.map +1 -1
- package/dist/esm/endpoints/navigation.js +24 -22
- package/dist/esm/endpoints/pages.d.ts +8 -5
- package/dist/esm/endpoints/pages.d.ts.map +1 -1
- package/dist/esm/endpoints/pages.js +18 -16
- package/dist/esm/endpoints/press.d.ts +4 -1
- package/dist/esm/endpoints/press.d.ts.map +1 -1
- package/dist/esm/endpoints/press.js +6 -4
- package/dist/esm/endpoints/website.d.ts +4 -1
- package/dist/esm/endpoints/website.d.ts.map +1 -1
- package/dist/esm/endpoints/website.js +6 -4
- package/dist/esm/types/location.d.ts +2 -0
- package/dist/esm/types/location.d.ts.map +1 -1
- package/dist/esm/types/website.d.ts +1 -0
- package/dist/esm/types/website.d.ts.map +1 -1
- package/dist/esm/util/event.d.ts +8 -0
- package/dist/esm/util/event.d.ts.map +1 -0
- package/dist/esm/util/event.js +63 -0
- package/dist/esm/util/gtag.d.ts +23 -0
- package/dist/esm/util/gtag.d.ts.map +1 -0
- package/dist/esm/util/gtag.js +10 -0
- package/dist/esm/util/imgproxy-loader.d.ts +9 -0
- package/dist/esm/util/imgproxy-loader.d.ts.map +1 -0
- package/dist/esm/util/imgproxy-loader.js +11 -0
- package/dist/esm/util/publishing.d.ts +2 -0
- package/dist/esm/util/publishing.d.ts.map +1 -0
- package/dist/esm/util/publishing.js +3 -0
- package/dist/esm/util/special-hours.d.ts +3 -0
- package/dist/esm/util/special-hours.d.ts.map +1 -0
- package/dist/esm/util/special-hours.js +20 -0
- package/dist/types/client.d.ts +16 -1
- package/dist/types/client.d.ts.map +1 -1
- package/dist/types/components/json-ld.d.ts +7 -0
- package/dist/types/components/json-ld.d.ts.map +1 -0
- package/dist/types/endpoints/alerts.d.ts +4 -1
- package/dist/types/endpoints/alerts.d.ts.map +1 -1
- package/dist/types/endpoints/base.d.ts +6 -0
- package/dist/types/endpoints/base.d.ts.map +1 -0
- package/dist/types/endpoints/events.d.ts +6 -3
- package/dist/types/endpoints/events.d.ts.map +1 -1
- package/dist/types/endpoints/locations.d.ts +5 -2
- package/dist/types/endpoints/locations.d.ts.map +1 -1
- package/dist/types/endpoints/menus.d.ts +6 -3
- package/dist/types/endpoints/menus.d.ts.map +1 -1
- package/dist/types/endpoints/navigation.d.ts +6 -3
- package/dist/types/endpoints/navigation.d.ts.map +1 -1
- package/dist/types/endpoints/pages.d.ts +8 -5
- package/dist/types/endpoints/pages.d.ts.map +1 -1
- package/dist/types/endpoints/press.d.ts +4 -1
- package/dist/types/endpoints/press.d.ts.map +1 -1
- package/dist/types/endpoints/website.d.ts +4 -1
- package/dist/types/endpoints/website.d.ts.map +1 -1
- package/dist/types/types/location.d.ts +2 -0
- package/dist/types/types/location.d.ts.map +1 -1
- package/dist/types/types/website.d.ts +1 -0
- package/dist/types/types/website.d.ts.map +1 -1
- package/dist/types/util/event.d.ts +8 -0
- package/dist/types/util/event.d.ts.map +1 -0
- package/dist/types/util/gtag.d.ts +23 -0
- package/dist/types/util/gtag.d.ts.map +1 -0
- package/dist/types/util/imgproxy-loader.d.ts +9 -0
- package/dist/types/util/imgproxy-loader.d.ts.map +1 -0
- package/dist/types/util/publishing.d.ts +2 -0
- package/dist/types/util/publishing.d.ts.map +1 -0
- package/dist/types/util/special-hours.d.ts +3 -0
- package/dist/types/util/special-hours.d.ts.map +1 -0
- package/package.json +31 -4
- package/src/client.ts +121 -0
- package/src/components/json-ld.tsx +9 -0
- package/src/config.ts +31 -0
- package/src/constants/google-events.ts +13 -0
- package/src/endpoints/alerts.ts +9 -0
- package/src/endpoints/base.ts +5 -0
- package/src/endpoints/events.ts +19 -0
- package/src/endpoints/locations.ts +27 -0
- package/src/endpoints/menus.ts +34 -0
- package/src/endpoints/navigation.ts +36 -0
- package/src/endpoints/pages.ts +24 -0
- package/src/endpoints/press.ts +9 -0
- package/src/endpoints/website.ts +9 -0
- package/src/index.ts +18 -0
- package/src/types/alert.ts +11 -0
- package/src/types/api.ts +12 -0
- package/src/types/event.ts +14 -0
- package/src/types/index.ts +13 -0
- package/src/types/location.ts +69 -0
- package/src/types/media-item.ts +10 -0
- package/src/types/menu-category-item.ts +18 -0
- package/src/types/menu-category.ts +15 -0
- package/src/types/menu-item.ts +15 -0
- package/src/types/menu.ts +12 -0
- package/src/types/navigation.ts +17 -0
- package/src/types/page.ts +24 -0
- package/src/types/press.ts +13 -0
- package/src/types/website.ts +76 -0
- package/src/util/event.ts +77 -0
- package/src/util/gtag.ts +40 -0
- package/src/util/imgproxy-loader.ts +22 -0
- package/src/util/publishing.ts +3 -0
- package/src/util/special-hours.ts +24 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { ApiCollectionResponse, Menu } from "../types";
|
|
2
|
+
import { BaseService } from "./base";
|
|
3
|
+
|
|
4
|
+
export class MenuService extends BaseService {
|
|
5
|
+
async getMenus(): Promise<Menu[]> {
|
|
6
|
+
const res = await this.client.get<ApiCollectionResponse<Menu>>("/menus");
|
|
7
|
+
const menus = res.data;
|
|
8
|
+
return menus;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async getMenu(id: string) {
|
|
12
|
+
const res = await this.client.get<ApiCollectionResponse<Menu>>(`/menus?filter[id]=${id}&include=categories.items`);
|
|
13
|
+
const data = res.data;
|
|
14
|
+
|
|
15
|
+
if (Array.isArray(data) && data.length > 0) {
|
|
16
|
+
return data[0];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return data;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async getMenuBySlug(slug: string) {
|
|
23
|
+
const res = await this.client.get<ApiCollectionResponse<Menu>>(
|
|
24
|
+
`/menus?filter[slug]=${slug}&include=categories.items`
|
|
25
|
+
);
|
|
26
|
+
const data = res.data;
|
|
27
|
+
|
|
28
|
+
if (Array.isArray(data) && data.length > 0) {
|
|
29
|
+
return data[0];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return data;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { ApiSingleResponse, ApiCollectionResponse, Navigation } from "../types";
|
|
2
|
+
import { BaseService } from "./base";
|
|
3
|
+
|
|
4
|
+
export class NavigationService extends BaseService {
|
|
5
|
+
async getNavigations(): Promise<Navigation[]> {
|
|
6
|
+
const res = await this.client.get<ApiCollectionResponse<Navigation>>("/navigations");
|
|
7
|
+
const navigations = res.data;
|
|
8
|
+
|
|
9
|
+
return Promise.all(
|
|
10
|
+
navigations.map(async (navigation: any) => {
|
|
11
|
+
const res = await this.client.get<ApiCollectionResponse<Navigation>>("/navigations/" + navigation.id);
|
|
12
|
+
return res.data[0];
|
|
13
|
+
})
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async getDefaultNavigation(): Promise<Navigation> {
|
|
18
|
+
const navigations = await this.getNavigations();
|
|
19
|
+
return navigations[0];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async getNavigation(id: string): Promise<Navigation> {
|
|
23
|
+
const res = await this.client.get<ApiSingleResponse<Navigation>>(`/navigations/${id}`);
|
|
24
|
+
const navigation = res.data;
|
|
25
|
+
|
|
26
|
+
const topLevelItems = navigation.items.filter((item: any) => item.parent_id === null);
|
|
27
|
+
|
|
28
|
+
topLevelItems.forEach((item: any) => {
|
|
29
|
+
item.children = navigation.items.filter((child: any) => child.parent_id === item.id);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
navigation.items = topLevelItems;
|
|
33
|
+
|
|
34
|
+
return navigation;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ApiCollectionResponse, Page } from "../types";
|
|
2
|
+
import { BaseService } from "./base";
|
|
3
|
+
|
|
4
|
+
export class PageService extends BaseService {
|
|
5
|
+
async getPages(): Promise<Page[]> {
|
|
6
|
+
const res = await this.client.get<ApiCollectionResponse<Page>>("/pages");
|
|
7
|
+
return res.data;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
async getPage(id: string): Promise<Page> {
|
|
11
|
+
const res = await this.client.get<ApiCollectionResponse<Page>>(`/pages/${id}`);
|
|
12
|
+
return res.data[0];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async getPageBySlug(slug: string): Promise<Page> {
|
|
16
|
+
const res = await this.client.get<ApiCollectionResponse<Page>>(`/pages?filter[slug]=${slug}`);
|
|
17
|
+
return res.data[0];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async getHomePage(): Promise<Page> {
|
|
21
|
+
const res = await this.client.get<ApiCollectionResponse<Page>>("/pages?filter[slug]=/");
|
|
22
|
+
return res.data[0];
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ApiCollectionResponse, Press } from "../types";
|
|
2
|
+
import { BaseService } from "./base";
|
|
3
|
+
|
|
4
|
+
export class PressService extends BaseService {
|
|
5
|
+
async getPress(): Promise<Press[]> {
|
|
6
|
+
const { data } = await this.client.get<ApiCollectionResponse<Press>>("/press");
|
|
7
|
+
return data;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ApiCollectionResponse, Website } from "../types";
|
|
2
|
+
import { BaseService } from "./base";
|
|
3
|
+
|
|
4
|
+
export class WebsiteService extends BaseService {
|
|
5
|
+
async getWebsite(): Promise<Website> {
|
|
6
|
+
const res = await this.client.get<ApiCollectionResponse<Website>>("/websites");
|
|
7
|
+
return res.data[0];
|
|
8
|
+
}
|
|
9
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// Re-export config
|
|
2
|
+
export { defineConfig, getGlobalConfig } from "./config";
|
|
3
|
+
|
|
4
|
+
// Re-export the client class
|
|
5
|
+
export { BackstageClient } from "./client";
|
|
6
|
+
|
|
7
|
+
// Re-export endpoints
|
|
8
|
+
export * from "./endpoints/alerts";
|
|
9
|
+
export * from "./endpoints/events";
|
|
10
|
+
export * from "./endpoints/locations";
|
|
11
|
+
export * from "./endpoints/menus";
|
|
12
|
+
export * from "./endpoints/navigation";
|
|
13
|
+
export * from "./endpoints/pages";
|
|
14
|
+
export * from "./endpoints/press";
|
|
15
|
+
export * from "./endpoints/website";
|
|
16
|
+
|
|
17
|
+
// Re-export domain types
|
|
18
|
+
export * from "./types";
|
package/src/types/api.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { MediaItem } from "./media-item";
|
|
2
|
+
|
|
3
|
+
export interface Event {
|
|
4
|
+
id: number;
|
|
5
|
+
title: string;
|
|
6
|
+
short_description: string;
|
|
7
|
+
description: string;
|
|
8
|
+
start_time: string; // or Date if the date is being converted before being used in TypeScript
|
|
9
|
+
end_time: string; // or Date if the date is being converted before being used in TypeScript
|
|
10
|
+
timezone: string;
|
|
11
|
+
cover_media_id: number;
|
|
12
|
+
cover_media: MediaItem; // Replace 'any' with the actual type of the cover_media
|
|
13
|
+
account_id: number;
|
|
14
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export * from "./alert";
|
|
2
|
+
export * from "./api";
|
|
3
|
+
export * from "./event";
|
|
4
|
+
export * from "./location";
|
|
5
|
+
export * from "./media-item";
|
|
6
|
+
export * from "./menu-category-item";
|
|
7
|
+
export * from "./menu-category";
|
|
8
|
+
export * from "./menu-item";
|
|
9
|
+
export * from "./menu";
|
|
10
|
+
export * from "./navigation";
|
|
11
|
+
export * from "./page";
|
|
12
|
+
export * from "./press";
|
|
13
|
+
export * from "./website";
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
export interface Location {
|
|
2
|
+
id: string;
|
|
3
|
+
account_id: string;
|
|
4
|
+
google_my_business_id: string | null;
|
|
5
|
+
name: string;
|
|
6
|
+
slug: string | null;
|
|
7
|
+
description: string | null;
|
|
8
|
+
featured_media_id: number;
|
|
9
|
+
address: string;
|
|
10
|
+
address2: string;
|
|
11
|
+
city: string;
|
|
12
|
+
state: string;
|
|
13
|
+
zip: string;
|
|
14
|
+
map_link: string | null;
|
|
15
|
+
map_embed: string | null;
|
|
16
|
+
latitude: number | null;
|
|
17
|
+
longitude: number | null;
|
|
18
|
+
phone: string;
|
|
19
|
+
email: string;
|
|
20
|
+
timezone: string | null;
|
|
21
|
+
hours: {
|
|
22
|
+
day: string;
|
|
23
|
+
openTime: string;
|
|
24
|
+
closeTime: string;
|
|
25
|
+
open24Hours: boolean;
|
|
26
|
+
closed24Hours: boolean;
|
|
27
|
+
notes: string;
|
|
28
|
+
}[];
|
|
29
|
+
special_hours: {
|
|
30
|
+
id: string;
|
|
31
|
+
date: string;
|
|
32
|
+
openTime: string;
|
|
33
|
+
closeTime: string;
|
|
34
|
+
open24Hours: boolean;
|
|
35
|
+
closed24Hours: boolean;
|
|
36
|
+
notes: string;
|
|
37
|
+
}[];
|
|
38
|
+
ordering_links: {
|
|
39
|
+
service: string;
|
|
40
|
+
url: string;
|
|
41
|
+
}[];
|
|
42
|
+
delivery_links: {
|
|
43
|
+
service: string;
|
|
44
|
+
url: string;
|
|
45
|
+
}[];
|
|
46
|
+
reservation_links: {
|
|
47
|
+
service: string;
|
|
48
|
+
url: string;
|
|
49
|
+
}[];
|
|
50
|
+
waitlist_links: {
|
|
51
|
+
service: string;
|
|
52
|
+
url: string;
|
|
53
|
+
}[];
|
|
54
|
+
loyalty_url: string | null;
|
|
55
|
+
created_at: string;
|
|
56
|
+
updated_at: string;
|
|
57
|
+
featured_media: {
|
|
58
|
+
id: number;
|
|
59
|
+
file_name: string;
|
|
60
|
+
url: string;
|
|
61
|
+
transform_url: string;
|
|
62
|
+
path: string;
|
|
63
|
+
width: number;
|
|
64
|
+
height: number;
|
|
65
|
+
alt: string;
|
|
66
|
+
};
|
|
67
|
+
status: string;
|
|
68
|
+
status_text: string;
|
|
69
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { MenuItem } from "./menu-item";
|
|
2
|
+
|
|
3
|
+
export interface MenuCategoryItem {
|
|
4
|
+
id: string;
|
|
5
|
+
menu_category_id: string;
|
|
6
|
+
menu_item_id: string;
|
|
7
|
+
title: string;
|
|
8
|
+
post_title: string | null;
|
|
9
|
+
subtitle: string | null;
|
|
10
|
+
description: string | null;
|
|
11
|
+
price: number | null;
|
|
12
|
+
order: number;
|
|
13
|
+
price2: number | null;
|
|
14
|
+
image_id: string | null;
|
|
15
|
+
created_at: string;
|
|
16
|
+
updated_at: string;
|
|
17
|
+
menu_item: MenuItem;
|
|
18
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { MenuCategoryItem } from "./menu-category-item";
|
|
2
|
+
|
|
3
|
+
export interface MenuCategory {
|
|
4
|
+
id: string;
|
|
5
|
+
title: string;
|
|
6
|
+
subtitle: string | null;
|
|
7
|
+
description: string | null;
|
|
8
|
+
after_description: string | null;
|
|
9
|
+
column_count: number | null;
|
|
10
|
+
menu_id: string;
|
|
11
|
+
order: number;
|
|
12
|
+
created_at: string;
|
|
13
|
+
updated_at: string;
|
|
14
|
+
items: MenuCategoryItem[];
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface MenuItem {
|
|
2
|
+
id: string;
|
|
3
|
+
account_id: string;
|
|
4
|
+
title: string;
|
|
5
|
+
post_title: string | null;
|
|
6
|
+
subtitle: string | null;
|
|
7
|
+
description: string | null;
|
|
8
|
+
price: number | null;
|
|
9
|
+
price2: number | null;
|
|
10
|
+
image_id: string | null;
|
|
11
|
+
type: string | null;
|
|
12
|
+
overrides: string | null;
|
|
13
|
+
created_at: string;
|
|
14
|
+
updated_at: string;
|
|
15
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface Menu {
|
|
2
|
+
id: string;
|
|
3
|
+
slug: string;
|
|
4
|
+
is_default: boolean;
|
|
5
|
+
title: string;
|
|
6
|
+
subtitle: string | null;
|
|
7
|
+
account_id: string;
|
|
8
|
+
pdf_url: string | null;
|
|
9
|
+
categories: string[]; // You can replace this with the actual type for categories if needed
|
|
10
|
+
created_at: string;
|
|
11
|
+
updated_at: string;
|
|
12
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface NavigationItem {
|
|
2
|
+
id: string;
|
|
3
|
+
text: string;
|
|
4
|
+
url: string;
|
|
5
|
+
html: string;
|
|
6
|
+
new_window: boolean;
|
|
7
|
+
type: string;
|
|
8
|
+
style: string;
|
|
9
|
+
parent_id: string;
|
|
10
|
+
children: NavigationItem[];
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface Navigation {
|
|
14
|
+
id: string;
|
|
15
|
+
name: string;
|
|
16
|
+
items: NavigationItem[];
|
|
17
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export interface Block {
|
|
2
|
+
id: string;
|
|
3
|
+
block: string;
|
|
4
|
+
data: any;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export interface Settings {
|
|
8
|
+
background_color: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface Meta {
|
|
12
|
+
title: string;
|
|
13
|
+
description: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface Page {
|
|
17
|
+
id: string;
|
|
18
|
+
title: string;
|
|
19
|
+
slug: string;
|
|
20
|
+
blocks: Block[];
|
|
21
|
+
settings: Settings;
|
|
22
|
+
meta: Meta;
|
|
23
|
+
is_home: boolean;
|
|
24
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
export interface SocialLink {
|
|
2
|
+
name: string;
|
|
3
|
+
url: string | null;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export interface FontFamily {
|
|
7
|
+
name: string;
|
|
8
|
+
value: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface ThemeColors {
|
|
12
|
+
primary?: string;
|
|
13
|
+
primaryForeground: string;
|
|
14
|
+
secondary?: string;
|
|
15
|
+
secondaryForeground: string;
|
|
16
|
+
tertiary?: string;
|
|
17
|
+
tertiaryForeground: string;
|
|
18
|
+
topbar?: string;
|
|
19
|
+
topbarForeground: string;
|
|
20
|
+
header?: string;
|
|
21
|
+
headerForeground: string;
|
|
22
|
+
footerLocation?: string;
|
|
23
|
+
footerLocationForeground: string;
|
|
24
|
+
footer?: string;
|
|
25
|
+
footerForeground: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface Theme {
|
|
29
|
+
name: string | null;
|
|
30
|
+
colors: ThemeColors;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface WebsiteMeta {
|
|
34
|
+
title: string | null;
|
|
35
|
+
description: string | null;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface OpenGraph {
|
|
39
|
+
title: string | null;
|
|
40
|
+
description: string | null;
|
|
41
|
+
image: string | null;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface Logo {
|
|
45
|
+
url: string;
|
|
46
|
+
width: number;
|
|
47
|
+
height: number;
|
|
48
|
+
thumb: string;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface Account {
|
|
52
|
+
id: string;
|
|
53
|
+
name: string;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface Website {
|
|
57
|
+
id: string;
|
|
58
|
+
app_name: string;
|
|
59
|
+
domain: string;
|
|
60
|
+
favicon_url: string | null;
|
|
61
|
+
logo: Logo | null;
|
|
62
|
+
account: Account;
|
|
63
|
+
meta: WebsiteMeta;
|
|
64
|
+
open_graph: OpenGraph;
|
|
65
|
+
theme: Theme;
|
|
66
|
+
google_analytics_id: string | null;
|
|
67
|
+
facebook_pixel_id: string | null;
|
|
68
|
+
font_urls: string[] | null;
|
|
69
|
+
font_families: FontFamily[] | null;
|
|
70
|
+
header_navigation_id: string | null;
|
|
71
|
+
footer_navigation_id: string | null;
|
|
72
|
+
social_links: SocialLink[];
|
|
73
|
+
home_cta_text: string | null;
|
|
74
|
+
home_cta_url: string | null;
|
|
75
|
+
has_accessibility_widget: boolean;
|
|
76
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { Event, Location, Website } from "../types";
|
|
2
|
+
import { Event as SchemaEvent, WithContext } from "schema-dts";
|
|
3
|
+
|
|
4
|
+
export function isMultipleDays(start: Date, end: Date) {
|
|
5
|
+
return start.getDate() !== end.getDate();
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function dateString(event: Event) {
|
|
9
|
+
const startTime = new Date(event.start_time);
|
|
10
|
+
const endTime = new Date(event.end_time);
|
|
11
|
+
|
|
12
|
+
if (isMultipleDays(startTime, endTime)) {
|
|
13
|
+
const startDayShort = startTime.toLocaleDateString("en-US", { weekday: "short" });
|
|
14
|
+
const startDate = startTime.toLocaleDateString("en-US", { month: "short", day: "numeric" });
|
|
15
|
+
const endDate = endTime.toLocaleDateString("en-US", { month: "short", day: "numeric" });
|
|
16
|
+
|
|
17
|
+
return `${startDayShort}, ${startDate} - ${endDate}`;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const startDay = startTime.toLocaleDateString("en-US", { weekday: "short" });
|
|
21
|
+
const startDate = startTime.toLocaleDateString("en-US", { month: "short", day: "numeric" });
|
|
22
|
+
const startTimeString = startTime.toLocaleTimeString("en-US", { hour: "numeric", minute: "numeric" });
|
|
23
|
+
const endTimeString = endTime.toLocaleTimeString("en-US", { hour: "numeric", minute: "numeric" });
|
|
24
|
+
|
|
25
|
+
return `${startDay}, ${startDate}`;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function timeString(event: Event) {
|
|
29
|
+
const startTime = new Date(event.start_time);
|
|
30
|
+
const endTime = new Date(event.end_time);
|
|
31
|
+
|
|
32
|
+
const startTimeString = startTime.toLocaleTimeString("en-US", { hour: "numeric", minute: "numeric" });
|
|
33
|
+
const endTimeString = endTime.toLocaleTimeString("en-US", { hour: "numeric", minute: "numeric" });
|
|
34
|
+
|
|
35
|
+
return `${startTimeString} - ${endTimeString}`;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function shortDescription(event: Event) {
|
|
39
|
+
// event.description is html
|
|
40
|
+
// strip html tags
|
|
41
|
+
// keep newlines
|
|
42
|
+
// return first 50 chars
|
|
43
|
+
|
|
44
|
+
const shortDescription = event.description.substring(0, 100);
|
|
45
|
+
return shortDescription;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function makeEventSchema(website: Website, event: Event, locations: Location[]): WithContext<SchemaEvent> {
|
|
49
|
+
return {
|
|
50
|
+
"@context": "https://schema.org",
|
|
51
|
+
"@type": "Event",
|
|
52
|
+
"@id": `https://${website.domain}/events/${event.id}//#event`,
|
|
53
|
+
eventAttendanceMode: "https://schema.org/OfflineEventAttendanceMode",
|
|
54
|
+
url: `https://${website.domain}/events/${event.id}`,
|
|
55
|
+
name: event.title,
|
|
56
|
+
description: event.description,
|
|
57
|
+
startDate: event.start_time,
|
|
58
|
+
endDate: event.end_time,
|
|
59
|
+
location: [
|
|
60
|
+
{
|
|
61
|
+
"@type": "Place",
|
|
62
|
+
address: {
|
|
63
|
+
"@type": "PostalAddress",
|
|
64
|
+
streetAddress: locations[0].address,
|
|
65
|
+
addressLocality: locations[0].city,
|
|
66
|
+
addressRegion: locations[0].state,
|
|
67
|
+
postalCode: locations[0].zip,
|
|
68
|
+
addressCountry: "US",
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
],
|
|
72
|
+
image: {
|
|
73
|
+
"@type": "ImageObject",
|
|
74
|
+
url: event.cover_media?.transform_url,
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
}
|
package/src/util/gtag.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { GAEvents, GALocations } from "../constants/google-events";
|
|
2
|
+
|
|
3
|
+
// Define gtag on window
|
|
4
|
+
declare global {
|
|
5
|
+
interface Window {
|
|
6
|
+
gtag?: (...args: any[]) => void;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function gtag(...args: any[]) {
|
|
11
|
+
if (typeof window !== "undefined" && window.gtag) {
|
|
12
|
+
window.gtag(...args);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface GtagEventParams {
|
|
17
|
+
category?: string;
|
|
18
|
+
label?: string;
|
|
19
|
+
value?: number;
|
|
20
|
+
page_url?: string;
|
|
21
|
+
|
|
22
|
+
// location is one of GALocations
|
|
23
|
+
location?: string;
|
|
24
|
+
|
|
25
|
+
// store is the slug of the store
|
|
26
|
+
store?: string | null | undefined;
|
|
27
|
+
|
|
28
|
+
/** @deprecated Use category instead */
|
|
29
|
+
event_category?: string;
|
|
30
|
+
/** @deprecated Use label instead */
|
|
31
|
+
event_label?: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
type GtagEventName = keyof typeof GAEvents | (string & {});
|
|
35
|
+
|
|
36
|
+
export function gtagEvent(name: GtagEventName, params: GtagEventParams = {}) {
|
|
37
|
+
if (typeof window === "undefined" || !window.gtag) return;
|
|
38
|
+
|
|
39
|
+
gtag("event", name, params);
|
|
40
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
interface ImgproxyLoaderProps {
|
|
2
|
+
src: string;
|
|
3
|
+
width?: number;
|
|
4
|
+
height?: number;
|
|
5
|
+
quality?: number;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export default function imgproxyLoader({ src, width, height, quality }: ImgproxyLoaderProps) {
|
|
9
|
+
const path =
|
|
10
|
+
`/size:${width ? width : 0}:${height ? height : 0}` +
|
|
11
|
+
`/resizing_type:fill` +
|
|
12
|
+
(quality ? `/quality:${quality}` : "") +
|
|
13
|
+
`/sharpen:0.5` +
|
|
14
|
+
`/plain/${src}` +
|
|
15
|
+
`@webp`;
|
|
16
|
+
|
|
17
|
+
const host = process.env.NEXT_PUBLIC_IMGPROXY_URL || "https://imgproxy.antlur.co";
|
|
18
|
+
|
|
19
|
+
const imgUrl = `${host}/insecure${path}`;
|
|
20
|
+
|
|
21
|
+
return imgUrl;
|
|
22
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Location } from "../types";
|
|
2
|
+
import { DateTime } from "luxon";
|
|
3
|
+
|
|
4
|
+
export function getSpecialHoursFromLocation(location: Location): any[] {
|
|
5
|
+
if (!location.special_hours) return [];
|
|
6
|
+
|
|
7
|
+
// filter out any special hours that are before today
|
|
8
|
+
const now = DateTime.now().startOf("day");
|
|
9
|
+
if (location.timezone) now.setZone(location.timezone);
|
|
10
|
+
|
|
11
|
+
const specialHours = location.special_hours.filter((specialHour) => {
|
|
12
|
+
const specialHourDate = DateTime.fromISO(specialHour.date);
|
|
13
|
+
return specialHourDate >= now;
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
// sort by date
|
|
17
|
+
specialHours.sort((a, b) => {
|
|
18
|
+
const aDate = DateTime.fromISO(a.date);
|
|
19
|
+
const bDate = DateTime.fromISO(b.date);
|
|
20
|
+
return aDate > bDate ? 1 : -1;
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
return specialHours;
|
|
24
|
+
}
|