weg-shared-layout 0.0.46 → 0.0.47

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/readme.md CHANGED
@@ -1,108 +1,121 @@
1
- [![Built With Stencil](https://img.shields.io/badge/-Built%20With%20Stencil-16161d.svg?logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDE5LjIuMSwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IgoJIHZpZXdCb3g9IjAgMCA1MTIgNTEyIiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCA1MTIgNTEyOyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI%2BCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI%2BCgkuc3Qwe2ZpbGw6I0ZGRkZGRjt9Cjwvc3R5bGU%2BCjxwYXRoIGNsYXNzPSJzdDAiIGQ9Ik00MjQuNywzNzMuOWMwLDM3LjYtNTUuMSw2OC42LTkyLjcsNjguNkgxODAuNGMtMzcuOSwwLTkyLjctMzAuNy05Mi43LTY4LjZ2LTMuNmgzMzYuOVYzNzMuOXoiLz4KPHBhdGggY2xhc3M9InN0MCIgZD0iTTQyNC43LDI5Mi4xSDE4MC40Yy0zNy42LDAtOTIuNy0zMS05Mi43LTY4LjZ2LTMuNkgzMzJjMzcuNiwwLDkyLjcsMzEsOTIuNyw2OC42VjI5Mi4xeiIvPgo8cGF0aCBjbGFzcz0ic3QwIiBkPSJNNDI0LjcsMTQxLjdIODcuN3YtMy42YzAtMzcuNiw1NC44LTY4LjYsOTIuNy02OC42SDMzMmMzNy45LDAsOTIuNywzMC43LDkyLjcsNjguNlYxNDEuN3oiLz4KPC9zdmc%2BCg%3D%3D&colorA=16161d&style=flat-square)](https://stenciljs.com)
2
-
3
- # weg-shared-layout
4
-
5
- > Shared layout Web Components.
6
-
7
- ## Install
8
-
9
- ```bash
10
- npm i weg-shared-layout
11
- ```
12
-
13
- ## How it works
14
-
15
- `<weg-header>` and `<weg-footer>` are **presentational** Web Components: they do **not** fetch data.
16
-
17
- Load layout JSON from your CMS/API (e.g. [`GET /api/layout`](https://weg-payload-test.vercel.app/api/layout) from WEG CMS) or import [`dummy-data.json`](src/assets/dummy-data.json), then pass it to `layout` on each tag.
18
-
19
- ### Layout shape (abbreviated)
20
-
21
- Full reference: [`src/assets/dummy-data.json`](src/assets/dummy-data.json). Sign-in is a normal `header.menu` link (label **Sign in** or login `href`); `<weg-header>` recognizes it automatically. Signed-in nav is built into `<weg-header>` when `signed-in` is true.
22
-
23
- ```json
24
- {
25
- "header": {
26
- "menu": [
27
- { "label": "Find a job", "items": [{ "label": "Graduates", "href": "…" }] },
28
- { "label": "Career advice", "href": "…" },
29
- { "label": "Sign in", "href": "…" }
30
- ]
31
- },
32
- "footer": {
33
- "menu": [[{ "label": "About WEG", "href": "…" }]],
34
- "social": [{ "platform": "LinkedIn", "href": "…" }],
35
- "credits": "…",
36
- "copyright": "…"
37
- }
38
- }
39
- ```
40
-
41
- | Field | Used when | Notes |
42
- | --- | --- | --- |
43
- | `header.logoSrc` | Signed out | Optional CMS logo URL; bundled PNG if omitted |
44
- | `header.logoHref` | Always | Optional logo link URL; WEG homepage if omitted |
45
- | `header.menu` | Signed out | Groups use `items`; flat links use `href` |
46
- | `footer.menu` | Always | `LayoutLink[][]` — one column per inner array |
47
- | `footer.social` | Always | LinkedIn, Instagram, TikTok, or YouTube |
48
- | `footer.credits` / `footer.copyright` | Always | Legal copy |
49
-
50
- ### Auth (Sign in / Sign out)
51
-
52
- **Signed out**: renders `header.menu`. Sign-in is a normal link — add `{ "label": "Sign in", "href": "…" }` like Register or Career advice. The header recognizes it by label or login URL and follows `href` on click.
53
-
54
- **Signed in** (`signed-in` true): ignores CMS `header.menu` and shows built-in Find a job, Dashboard, Manage Account, and Sign out.
55
-
56
- Set **`signed-in`** from your app session state. Pass **`user-name`** for Manage Account. Pass **`account-base-url`** when account links should point at a non-production portal. Pass **`current-path`** (e.g. `/career-advice/my-article`) to highlight the active nav item. **Sign out** emits **`wegAuthClick`** — the host must call `event.preventDefault()` and run your logout flow (API call, clear session, redirect).
57
-
58
- ### Nav active state
59
-
60
- | Link type | Match rule |
61
- | --- | --- |
62
- | Flat nav link | Prefix — `/career-advice` matches `/career-advice/foo` |
63
- | Dropdown child | Exact pathname (+ query when href includes `?`) |
64
- | Dropdown parent | Active background when any child matches |
65
- | Sign in / Sign out | Never highlighted |
66
-
67
- Active links use **`weg-purple-200`** (`#CDCFF8`). Omit `current-path` to disable active styling.
68
-
69
- ```js
70
- header.addEventListener('wegAuthClick', async (event) => {
71
- if (event.detail.action !== 'sign-out') return;
72
- event.preventDefault();
73
- await logout();
74
- window.location.assign('/');
75
- });
76
- ```
77
-
78
- - **From npm:** `import layout from 'weg-shared-layout/dummy-data.json'` — in TypeScript set `resolveJsonModule` and `moduleResolution` to `bundler` or `node16` (see [docs/angular.md](./docs/angular.md)).
79
- - **In this repo:** [`src/assets/dummy-data.json`](src/assets/dummy-data.json)
80
-
81
- ### Package imports (TypeScript / bundlers)
82
-
83
- | Subpath | Use |
84
- | --- | --- |
85
- | `weg-shared-layout/loader` | `defineCustomElements()` — **recommended** |
86
- | `weg-shared-layout/dummy-data.json` | Sample layout + `typeof` for app types |
87
- | `weg-shared-layout/layout-data` | Types only (`LayoutData`, …) |
88
- | `weg-shared-layout/weg-header` / `weg-footer` | Side-effect tag registration |
89
- | `weg-shared-layout/styles/container.css` | Shared `.container` width and gutter utility |
90
-
91
- ## Documentation
92
-
93
- Full index: **[docs/README.md](./docs/README.md)**.
94
-
95
- | Guide | Doc |
96
- | --- | --- |
97
- | Angular 16 | [docs/angular.md](./docs/angular.md) |
98
- | Angular 16 demo (runnable) | [demo/angular16/README.md](./demo/angular16/README.md) |
99
- | React (SPA, client-only) | [docs/react.md](./docs/react.md) |
100
- | Next.js (App Router) | [docs/nextjs.md](./docs/nextjs.md) |
101
- | Plain HTML / vanilla JS | [docs/vanilla.md](./docs/vanilla.md) |
102
- | Publishing (maintainers) | [docs/publishing.md](./docs/publishing.md) |
103
-
104
- ## Publishing (maintainers)
105
-
106
- **`npm publish` does not run `npm run build` by itself** — it packs what is on disk. This package uses a **`prepack`** script so a full Stencil build runs before every `npm pack` / `npm publish`, avoiding incomplete tarballs.
107
-
108
- Details, checklist, and CI notes: **[docs/publishing.md](./docs/publishing.md)**.
1
+ # weg-shared-layout
2
+
3
+ > Shared layout Web Components.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm i weg-shared-layout
9
+ ```
10
+
11
+ ## How it works
12
+
13
+ `<weg-header>` and `<weg-footer>` are **presentational** Web Components: they do **not** fetch data.
14
+
15
+ Load layout from the **WEG CMS WEG21 API**, then pass the mapped object to `layout` on each tag:
16
+
17
+ | Endpoint | Purpose |
18
+ | --- | --- |
19
+ | `GET https://warwickemploymentgroup.com/api/v1/weg21` | Logo URLs, footer social + legal copy |
20
+ | `GET …/api/v1/weg21/menus` | Header (`ext` / `int`) and footer link columns |
21
+
22
+ Both require the `wcms-api-key` header. Use `fetchWeg21Layout` from `weg-shared-layout/menus`:
23
+
24
+ ```ts
25
+ import { fetchWeg21Layout } from 'weg-shared-layout/menus';
26
+
27
+ const layout = await fetchWeg21Layout({
28
+ apiKey: process.env.WCMS_API_KEY,
29
+ });
30
+ // layout.header.menu, layout.footer.menu, layout.footer.social, …
31
+ ```
32
+
33
+ [`weg21-bootstrap.json`](src/assets/weg21-bootstrap.json) and [`weg21-menus.json`](src/assets/weg21-menus.json) mirror the **WEG21 API response schemas** (`GET /api/v1/weg21` and `/menus`). Map to `layout` with `dummyWeg21LayoutData()` or `menusToLayoutData`.
34
+
35
+ ### Layout shape (abbreviated)
36
+
37
+ ```json
38
+ {
39
+ "header": {
40
+ "menu": [
41
+ { "label": "Find a job", "items": [{ "label": "Graduates", "href": "…" }] },
42
+ { "label": "Sign in", "href": "…" }
43
+ ]
44
+ },
45
+ "footer": {
46
+ "menu": [[{ "label": "About WEG", "href": "…" }]],
47
+ "social": [{ "platform": "LinkedIn", "href": "…" }],
48
+ "credits": "…",
49
+ "copyright": "…"
50
+ }
51
+ }
52
+ ```
53
+
54
+ | Field | Used when | Notes |
55
+ | --- | --- | --- |
56
+ | `header.logoSrc` | Signed out | Optional CMS logo URL; bundled PNG if omitted |
57
+ | `header.logoHref` | Always | Optional logo link URL; WEG homepage if omitted |
58
+ | `header.menu` | Signed out | Groups use `items`; flat links use `href` |
59
+ | `footer.menu` | Always | `LayoutLink[][]` — one column per inner array |
60
+ | `footer.social` | Always | LinkedIn, Instagram, TikTok, or YouTube |
61
+ | `footer.credits` / `footer.copyright` | Always | Legal copy |
62
+
63
+ ### Auth (Sign in / Sign out)
64
+
65
+ **Signed out**: renders `header.menu`. Sign-in is a normal link — add `{ "label": "Sign in", "href": "…" }` like Register or Career advice. The header recognizes it by label or login URL and follows `href` on click.
66
+
67
+ **Signed in** (`signed-in` true): ignores CMS `header.menu` and shows built-in Find a job, Dashboard, Manage Account, and Sign out.
68
+
69
+ Set **`signed-in`** from your app session state. Pass **`user-name`** for Manage Account. Pass **`account-base-url`** when account links should point at a non-production portal. Pass **`current-path`** (e.g. `/career-advice/my-article`) to highlight the active nav item. **Sign out** emits **`wegAuthClick`** — the host must call `event.preventDefault()` and run your logout flow (API call, clear session, redirect).
70
+
71
+ ### Nav active state
72
+
73
+ | Link type | Match rule |
74
+ | --- | --- |
75
+ | Flat nav link | Prefix — `/career-advice` matches `/career-advice/foo` |
76
+ | Dropdown child | Exact pathname (+ query when href includes `?`) |
77
+ | Dropdown parent | Active background when any child matches |
78
+ | Sign in / Sign out | Never highlighted |
79
+
80
+ Active links use **`weg-purple-200`** (`#CDCFF8`). Omit `current-path` to disable active styling.
81
+
82
+ ```js
83
+ header.addEventListener('wegAuthClick', async (event) => {
84
+ if (event.detail.action !== 'sign-out') return;
85
+ event.preventDefault();
86
+ await logout();
87
+ window.location.assign('/');
88
+ });
89
+ ```
90
+
91
+ ### Package imports (TypeScript / bundlers)
92
+
93
+ | Subpath | Use |
94
+ | --- | --- |
95
+ | `weg-shared-layout/loader` | `defineCustomElements()` — **recommended** |
96
+ | `weg-shared-layout/menus` | `fetchWeg21Layout`, `menusToLayoutData` |
97
+ | `weg-shared-layout/menus-data` | WEG21 API types (`MenusData`, …) |
98
+ | `weg-shared-layout/layout-data` | `<weg-header>` / `<weg-footer>` types (`LayoutData`, …) |
99
+ | `weg-shared-layout/weg21-bootstrap.json` | `GET /api/v1/weg21` schema sample |
100
+ | `weg-shared-layout/weg21-menus.json` | `GET /api/v1/weg21/menus` schema sample |
101
+ | `weg-shared-layout/weg-header` / `weg-footer` | Side-effect tag registration |
102
+ | `weg-shared-layout/styles/container.css` | Shared `.container` width and gutter utility |
103
+
104
+ ## Documentation
105
+
106
+ Full index: **[docs/README.md](./docs/README.md)**.
107
+
108
+ | Guide | Doc |
109
+ | --- | --- |
110
+ | Angular 16 | [docs/angular.md](./docs/angular.md) |
111
+ | Angular 16 demo (runnable) | [demo/angular16/README.md](./demo/angular16/README.md) |
112
+ | React (SPA, client-only) | [docs/react.md](./docs/react.md) |
113
+ | Next.js (App Router) | [docs/nextjs.md](./docs/nextjs.md) |
114
+ | Plain HTML / vanilla JS | [docs/vanilla.md](./docs/vanilla.md) |
115
+ | Publishing (maintainers) | [docs/publishing.md](./docs/publishing.md) |
116
+
117
+ ## Publishing (maintainers)
118
+
119
+ **`npm publish` does not run `npm run build` by itself** — it packs what is on disk. This package uses a **`prepack`** script so a full Stencil build runs before every `npm pack` / `npm publish`, avoiding incomplete tarballs.
120
+
121
+ Details, checklist, and CI notes: **[docs/publishing.md](./docs/publishing.md)**.
@@ -0,0 +1,12 @@
1
+ {
2
+ "logo": "https://warwickemploymentgroup.com/api/logo.png",
3
+ "favicon": "https://warwickemploymentgroup.com/favicon.ico",
4
+ "menus": "https://warwickemploymentgroup.com/api/v1/weg21/menus",
5
+ "footer": {
6
+ "social_links": [
7
+ { "platform": "LinkedIn", "href": "https://www.linkedin.com/company/warwickemploymentgroup/" }
8
+ ],
9
+ "credit": "Warwick Employment Group is a department of the Campus and Commercial Services Group at the University of Warwick.",
10
+ "copyright": "Copyright © Warwick Employment Group."
11
+ }
12
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "header": {
3
+ "ext": [
4
+ {
5
+ "label": "Find a job",
6
+ "items": [
7
+ { "label": "Graduates", "href": "https://www.warwickemploymentgroup.com/find-a-job/graduates" }
8
+ ]
9
+ },
10
+ { "label": "Sign in", "href": "https://account.warwickemploymentgroup.com/account/login" }
11
+ ],
12
+ "int": [
13
+ { "label": "Dashboard", "href": "https://account.warwickemploymentgroup.com/dashboard" }
14
+ ]
15
+ },
16
+ "footer": [
17
+ [{ "label": "About WEG", "href": "https://www.warwickemploymentgroup.com/about" }]
18
+ ]
19
+ }
@@ -0,0 +1,44 @@
1
+ /**
2
+ * WEG21 API types — mirrors wegcms-v2 `src/weg-shared-layout/menus-types.ts`.
3
+ * @see GET /api/v1/weg21
4
+ * @see GET /api/v1/weg21/menus
5
+ */
6
+ export type LayoutPlatform = 'LinkedIn' | 'Instagram' | 'TikTok' | 'YouTube';
7
+
8
+ export type LayoutSocialLink = {
9
+ platform: LayoutPlatform;
10
+ href: string;
11
+ };
12
+
13
+ export type MenuItemProps = {
14
+ label: string;
15
+ href?: string;
16
+ items?: MenuItemProps[];
17
+ };
18
+
19
+ export type HeaderMenuProps = {
20
+ ext: MenuItemProps[];
21
+ int: MenuItemProps[];
22
+ };
23
+
24
+ export type FooterMenuProps = MenuItemProps[][];
25
+
26
+ /** `GET /api/v1/weg21/menus` response body. */
27
+ export type MenusProps = {
28
+ header: HeaderMenuProps;
29
+ footer: FooterMenuProps;
30
+ };
31
+
32
+ export type Weg21FooterProps = {
33
+ social_links: LayoutSocialLink[];
34
+ credit: string;
35
+ copyright: string;
36
+ };
37
+
38
+ /** `GET /api/v1/weg21` response body. */
39
+ export type Weg21BootstrapProps = {
40
+ logo: string;
41
+ favicon: string;
42
+ menus: string;
43
+ footer: Weg21FooterProps;
44
+ };
@@ -0,0 +1,65 @@
1
+ import type { LayoutData } from '../types/layout-data';
2
+ import type { MenusProps, Weg21BootstrapProps } from '../types/menus-data';
3
+ import bootstrapDummy from '../assets/weg21-bootstrap.json';
4
+ import menusDummy from '../assets/weg21-menus.json';
5
+
6
+ export const DEFAULT_WEG21_API_BASE = 'https://warwickemploymentgroup.com/api/v1/weg21';
7
+
8
+ export const WEG21_BOOTSTRAP_DUMMY = bootstrapDummy as Weg21BootstrapProps;
9
+ export const WEG21_MENUS_DUMMY = menusDummy as MenusProps;
10
+
11
+ export type MenusToLayoutOptions = {
12
+ /** Which header nav slice maps to `header.menu`. Default: `ext` (public marketing nav). */
13
+ headerMenu?: 'ext' | 'int';
14
+ };
15
+
16
+ export function menusToLayoutData(
17
+ bootstrap: Pick<Weg21BootstrapProps, 'footer'>,
18
+ menus: MenusProps,
19
+ options: MenusToLayoutOptions = {},
20
+ ): LayoutData {
21
+ const headerMenu = options.headerMenu === 'int' ? menus.header.int : menus.header.ext;
22
+ const { credit, copyright, social_links } = bootstrap.footer;
23
+
24
+ return {
25
+ header: { menu: headerMenu },
26
+ footer: {
27
+ menu: menus.footer,
28
+ social: social_links,
29
+ credits: credit.trim() || undefined,
30
+ copyright: copyright.trim() || undefined,
31
+ },
32
+ };
33
+ }
34
+
35
+ /** Offline layout from package WEG21 dummy fixtures (`weg21-bootstrap.json` + `weg21-menus.json`). */
36
+ export function dummyWeg21LayoutData(options: MenusToLayoutOptions = {}): LayoutData {
37
+ return menusToLayoutData(WEG21_BOOTSTRAP_DUMMY, WEG21_MENUS_DUMMY, options);
38
+ }
39
+
40
+ export type FetchWeg21LayoutOptions = MenusToLayoutOptions & {
41
+ apiBase?: string;
42
+ apiKey?: string;
43
+ fetch?: typeof fetch;
44
+ };
45
+
46
+ export async function fetchWeg21Layout(options: FetchWeg21LayoutOptions = {}): Promise<LayoutData> {
47
+ const apiBase = (options.apiBase ?? DEFAULT_WEG21_API_BASE).replace(/\/$/, '');
48
+ const fetchFn = options.fetch ?? globalThis.fetch;
49
+ const headers: Record<string, string> = { accept: 'application/json' };
50
+ if (options.apiKey) headers['wcms-api-key'] = options.apiKey;
51
+
52
+ const [bootstrapRes, menusRes] = await Promise.all([
53
+ fetchFn(apiBase, { headers }),
54
+ fetchFn(`${apiBase}/menus`, { headers }),
55
+ ]);
56
+
57
+ if (!bootstrapRes.ok || !menusRes.ok) {
58
+ throw new Error(`WEG21 API error: bootstrap=${bootstrapRes.status} menus=${menusRes.status}`);
59
+ }
60
+
61
+ const bootstrap = (await bootstrapRes.json()) as Weg21BootstrapProps;
62
+ const menus = (await menusRes.json()) as MenusProps;
63
+
64
+ return menusToLayoutData(bootstrap, menus, options);
65
+ }
@@ -1,221 +0,0 @@
1
- {
2
- "header": {
3
- "menu": [
4
- {
5
- "label": "Find a job",
6
- "items": [
7
- {
8
- "label": "Professional & operational services",
9
- "href": "https://www.warwickemploymentgroup.com/find-a-job/professional-and-operational-services"
10
- },
11
- {
12
- "label": "Engineering & technology",
13
- "href": "https://www.warwickemploymentgroup.com/find-a-job/engineering-and-technology"
14
- },
15
- {
16
- "label": "Graduates",
17
- "href": "https://www.warwickemploymentgroup.com/find-a-job/graduates"
18
- },
19
- {
20
- "label": "Senior & leadership",
21
- "href": "https://www.warwickemploymentgroup.com/find-a-job/senior-and-leadership"
22
- }
23
- ]
24
- },
25
- {
26
- "label": "Hire talent",
27
- "items": [
28
- {
29
- "label": "Professional & operational services",
30
- "href": "https://www.warwickemploymentgroup.com/hire-talent/professional-and-operational-services"
31
- },
32
- {
33
- "label": "Engineering & technology",
34
- "href": "https://www.warwickemploymentgroup.com/hire-talent/engineering-and-technology"
35
- },
36
- {
37
- "label": "Graduates",
38
- "href": "https://www.warwickemploymentgroup.com/hire-talent/graduates"
39
- },
40
- {
41
- "label": "Executive search & selection",
42
- "href": "https://www.warwickemploymentgroup.com/hire-talent/executive-search-and-selection"
43
- }
44
- ]
45
- },
46
- {
47
- "label": "HE solutions",
48
- "items": [
49
- {
50
- "label": "Franchise solution",
51
- "href": "https://www.warwickemploymentgroup.com/he-solutions/unitemps-franchise"
52
- },
53
- {
54
- "label": "Disability support solution",
55
- "href": "https://www.warwickemploymentgroup.com/he-solutions/disabillity-support"
56
- },
57
- {
58
- "label": "Payroll bureau",
59
- "href": "https://www.warwickemploymentgroup.com/he-solutions/payroll-bureau"
60
- }
61
- ]
62
- },
63
- {
64
- "label": "Career advice",
65
- "href": "https://www.warwickemploymentgroup.com/career-advice"
66
- },
67
- {
68
- "label": "Register",
69
- "href": "https://account.warwickemploymentgroup.com/account/register"
70
- },
71
- {
72
- "label": "Sign in",
73
- "href": "https://account.warwickemploymentgroup.com/account/login"
74
- }
75
- ]
76
- },
77
- "footer": {
78
- "menu": [
79
- [
80
- {
81
- "label": "Find a job",
82
- "href": "https://www.warwickemploymentgroup.com/find-a-job"
83
- },
84
- {
85
- "label": "Professional & operational services",
86
- "href": "https://www.warwickemploymentgroup.com/find-a-job/professional-and-operational-services"
87
- },
88
- {
89
- "label": "Engineering & technology",
90
- "href": "https://www.warwickemploymentgroup.com/find-a-job/engineering-and-technology"
91
- },
92
- {
93
- "label": "Graduates",
94
- "href": "https://www.warwickemploymentgroup.com/find-a-job/graduates"
95
- },
96
- {
97
- "label": "Senior & leadership",
98
- "href": "https://www.warwickemploymentgroup.com/find-a-job/senior-and-leadership"
99
- }
100
- ],
101
- [
102
- {
103
- "label": "Hire talent",
104
- "href": "https://www.warwickemploymentgroup.com/hire-talent"
105
- },
106
- {
107
- "label": "Professional & operational services",
108
- "href": "https://www.warwickemploymentgroup.com/hire-talent/professional-and-operational-services"
109
- },
110
- {
111
- "label": "Engineering & technology",
112
- "href": "https://www.warwickemploymentgroup.com/hire-talent/engineering-and-technology"
113
- },
114
- {
115
- "label": "Graduates",
116
- "href": "https://www.warwickemploymentgroup.com/hire-talent/graduates"
117
- },
118
- {
119
- "label": "Executive search & selection",
120
- "href": "https://www.warwickemploymentgroup.com/hire-talent/executive-search-and-selection"
121
- }
122
- ],
123
- [
124
- {
125
- "label": "HE solutions",
126
- "href": "https://www.warwickemploymentgroup.com/he-solutions"
127
- },
128
- {
129
- "label": "Franchise solution",
130
- "href": "https://www.warwickemploymentgroup.com/he-solutions/unitemps-franchise"
131
- },
132
- {
133
- "label": "Payroll bureau",
134
- "href": "https://www.warwickemploymentgroup.com/he-solutions/payroll-bureau"
135
- },
136
- {
137
- "label": "Disability support solution",
138
- "href": "https://www.warwickemploymentgroup.com/he-solutions/disabillity-support"
139
- }
140
- ],
141
- [
142
- {
143
- "label": "Career advice",
144
- "href": "https://www.warwickemploymentgroup.com/career-advice"
145
- },
146
- {
147
- "label": "News & events",
148
- "href": "https://www.warwickemploymentgroup.com/news"
149
- },
150
- {
151
- "label": "Insights",
152
- "href": "https://www.warwickemploymentgroup.com/insights"
153
- }
154
- ],
155
- [
156
- {
157
- "label": "About WEG",
158
- "href": "https://www.warwickemploymentgroup.com/about"
159
- },
160
- {
161
- "label": "Our brands",
162
- "href": "https://www.warwickemploymentgroup.com/brands"
163
- },
164
- {
165
- "label": "Careers at WEG",
166
- "href": "https://www.warwickemploymentgroup.com/careers"
167
- },
168
- {
169
- "label": "Contact us",
170
- "href": "https://www.warwickemploymentgroup.com/contact"
171
- }
172
- ],
173
- [
174
- {
175
- "label": "Privacy policy",
176
- "href": "https://www.warwickemploymentgroup.com/privacy"
177
- },
178
- {
179
- "label": "Terms of use",
180
- "href": "https://www.warwickemploymentgroup.com/terms"
181
- },
182
- {
183
- "label": "Cookie policy",
184
- "href": "https://www.warwickemploymentgroup.com/cookies"
185
- },
186
- {
187
- "label": "Accessibility statement",
188
- "href": "https://www.warwickemploymentgroup.com/accessibility"
189
- },
190
- {
191
- "label": "Diversity & inclusion",
192
- "href": "https://www.warwickemploymentgroup.com/diversity"
193
- },
194
- {
195
- "label": "Modern slavery",
196
- "href": "https://www.warwickemploymentgroup.com/modern-slavery"
197
- }
198
- ]
199
- ],
200
- "social": [
201
- {
202
- "platform": "LinkedIn",
203
- "href": "https://www.linkedin.com/company/warwickemploymentgroup/"
204
- },
205
- {
206
- "platform": "TikTok",
207
- "href": "https://www.tiktok.com/@weg_updates"
208
- },
209
- {
210
- "platform": "Instagram",
211
- "href": "https://www.instagram.com/warwickemploymentgroup/"
212
- },
213
- {
214
- "platform": "YouTube",
215
- "href": "https://www.youtube.com/@WarwickEmploymentGroup"
216
- }
217
- ],
218
- "credits": "Warwick Employment Group is a department of the Campus and Commercial Services Group at the University of Warwick.",
219
- "copyright": "Copyright © Warwick Employment Group."
220
- }
221
- }