From c834f9c768eba38d8619893b9f3adb634f025dbb Mon Sep 17 00:00:00 2001 From: Ivan Kiral Date: Tue, 5 Nov 2024 13:06:54 +0100 Subject: [PATCH 01/56] add colors and fonts to tailwind theme --- index.html | 3 +++ src/App.tsx | 1 + tailwind.config.js | 18 +++++++++++++++++- 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/index.html b/index.html index e4b78ea..03d8ca7 100644 --- a/index.html +++ b/index.html @@ -4,6 +4,9 @@ + + + Vite + React + TS diff --git a/src/App.tsx b/src/App.tsx index 0a32b06..11a3903 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,3 +1,4 @@ +import "./index.css"; function App() { return (

diff --git a/tailwind.config.js b/tailwind.config.js index d37737f..0500fe9 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -1,11 +1,27 @@ /** @type {import('tailwindcss').Config} */ + export default { content: [ "./index.html", "./src/**/*.{js,ts,jsx,tsx}", ], theme: { - extend: {}, + extend: { + colors: { + burgundy: "#993265", + azure: "#009edb", + white: '#ffffff', + gray: { + light: "#8e8e8e", + DEFAULT: "#3b3b3b" + }, + creme: "#fff7e7" + }, + fontFamily: { + sans: ["Source Sans 3", 'Arial', 'sans-serif'], + libre: ['"Abhaya Libre"', "Arial"] + } + }, }, plugins: [], } From 8c72f9fcd4075548e04f3071e258d5e831de810d Mon Sep 17 00:00:00 2001 From: Ivan Kiral Date: Tue, 5 Nov 2024 13:11:52 +0100 Subject: [PATCH 02/56] Add header and container components --- src/App.tsx | 8 +++++--- src/components/Container.tsx | 9 +++++++++ src/components/Header.tsx | 24 ++++++++++++++++++++++++ tailwind.config.js | 10 ++++++++++ 4 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 src/components/Container.tsx create mode 100644 src/components/Header.tsx diff --git a/src/App.tsx b/src/App.tsx index 11a3903..6c9e7b2 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,9 +1,11 @@ +import Header from "./components/Header"; import "./index.css"; + function App() { return ( -

- Hello world! -

+
+
+
); } diff --git a/src/components/Container.tsx b/src/components/Container.tsx new file mode 100644 index 0000000..b204c3e --- /dev/null +++ b/src/components/Container.tsx @@ -0,0 +1,9 @@ +import { FC, PropsWithChildren } from "react"; + +const Container: FC = ({ children }) => ( +
+ {children} +
+); + +export default Container; diff --git a/src/components/Header.tsx b/src/components/Header.tsx new file mode 100644 index 0000000..7c3148a --- /dev/null +++ b/src/components/Header.tsx @@ -0,0 +1,24 @@ +import Container from "./Container"; + +const Header: React.FC = () => { + const createMenuLink = (name: string) => ( +
  • + {name} +
  • + ); + + return ( + +
    +

    Karma Health

    + +
    +
    + ); +}; + +export default Header; diff --git a/tailwind.config.js b/tailwind.config.js index 0500fe9..c19ae13 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -22,6 +22,16 @@ export default { libre: ['"Abhaya Libre"', "Arial"] } }, + container: { + center: true, + padding: { + DEFAULT: '1rem', + sm: '2rem', + lg: '4rem', + xl: '5rem', + '2xl': '6rem', + } + } }, plugins: [], } From 5d87c978a2544cb840c38120a9c0b85b25b5cad3 Mon Sep 17 00:00:00 2001 From: Ivan Kiral Date: Tue, 5 Nov 2024 13:54:46 +0100 Subject: [PATCH 03/56] Add HeroImage component --- src/App.tsx | 2 ++ src/components/HeroImage.tsx | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 src/components/HeroImage.tsx diff --git a/src/App.tsx b/src/App.tsx index 6c9e7b2..d3e3395 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,10 +1,12 @@ import Header from "./components/Header"; +import HeroImage from "./components/HeroImage"; import "./index.css"; function App() { return (
    +
    ); } diff --git a/src/components/HeroImage.tsx b/src/components/HeroImage.tsx new file mode 100644 index 0000000..38c2c22 --- /dev/null +++ b/src/components/HeroImage.tsx @@ -0,0 +1,32 @@ +import { FC } from "react"; +import Container from "./Container"; + +const HeroImage: FC = () => { + return ( +
    + +
    +
    +

    + Welcome To Karma Health's Nutritional Services +

    +

    + At Karma Health, we believe that good nutrition is the foundation of a healthy, vibrant life. Our team of + expert nutritionists and registered dietitians is dedicated to helping you achieve your wellness goals + through personalized, evidence-based nutritional guidance. +

    +
    + + +
    +
    +
    + ); +}; + +export default HeroImage; From 0e0afc356136d1aefd29c69d405953c3e85d8950 Mon Sep 17 00:00:00 2001 From: Ivan Kiral Date: Wed, 6 Nov 2024 09:04:01 +0100 Subject: [PATCH 04/56] add video component --- src/components/Video.tsx | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/components/Video.tsx diff --git a/src/components/Video.tsx b/src/components/Video.tsx new file mode 100644 index 0000000..a006e7f --- /dev/null +++ b/src/components/Video.tsx @@ -0,0 +1,28 @@ +import { FC } from "react"; + +const Video: FC = () => { + return ( +
    +

    + Personalized Nutrition Plans +

    +

    + We create tailored nutrition plans that fit your unique lifestyle, health concerns, and dietary preferences. Our + experts work closely with you to develop realistic, achievable goals that promote long-term health and + well-being. +

    +
    + + +
    + How we optimize your performance +
    +
    +
    + ); +}; + +export default Video; From 801d5094f92609cccde95218d66500335a4a268a Mon Sep 17 00:00:00 2001 From: Ivan Kiral Date: Wed, 6 Nov 2024 13:35:59 +0100 Subject: [PATCH 05/56] add featured article and event --- src/App.tsx | 21 ++++++++++++++ src/components/Divider.tsx | 5 ++++ src/components/FeaturedArticle.tsx | 33 ++++++++++++++++++++++ src/components/FeaturedEvent.tsx | 44 ++++++++++++++++++++++++++++++ 4 files changed, 103 insertions(+) create mode 100644 src/components/Divider.tsx create mode 100644 src/components/FeaturedArticle.tsx create mode 100644 src/components/FeaturedEvent.tsx diff --git a/src/App.tsx b/src/App.tsx index d3e3395..ba4a7b5 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,5 +1,10 @@ +import Container from "./components/Container"; +import Divider from "./components/Divider"; +import FeaturedArticle from "./components/FeaturedArticle"; +import FeaturedEvent from "./components/FeaturedEvent"; import Header from "./components/Header"; import HeroImage from "./components/HeroImage"; +import Video from "./components/Video"; import "./index.css"; function App() { @@ -7,6 +12,22 @@ function App() {
    + +
    +
    +
    +
    + + + +
    + +
    + + + +
    ); } diff --git a/src/components/Divider.tsx b/src/components/Divider.tsx new file mode 100644 index 0000000..126b20c --- /dev/null +++ b/src/components/Divider.tsx @@ -0,0 +1,5 @@ +import { FC } from "react"; + +const Divider: FC = () =>
    ; + +export default Divider; diff --git a/src/components/FeaturedArticle.tsx b/src/components/FeaturedArticle.tsx new file mode 100644 index 0000000..eca7a0b --- /dev/null +++ b/src/components/FeaturedArticle.tsx @@ -0,0 +1,33 @@ +import React from "react"; + +const FeaturedArticle: React.FC = () => { + return ( +
    +
    + + FEATURED ARTICLE + + Article +
    +
    +
    +

    Article Title

    +

    Published on Dec 10, 2024

    +

    + Optimize your athletic performance with our sports nutrition services. We provide tailored advice on fueling + strategies, hydration, and nutrient timing to help you reach your peak potential. +

    +
    + + Read more + +
    +
    + ); +}; + +export default FeaturedArticle; diff --git a/src/components/FeaturedEvent.tsx b/src/components/FeaturedEvent.tsx new file mode 100644 index 0000000..9ba5d67 --- /dev/null +++ b/src/components/FeaturedEvent.tsx @@ -0,0 +1,44 @@ +import React from "react"; + +const FeaturedEvent: React.FC = () => { + const createTag = (text: string) => ( +
    +

    {text}

    +
    + ); + + return ( +
    +
    + + FEATURED EVENT + + Article +
    +
    +
    +

    Event Name

    +

    Jan 4, 2025 - Jan 6, 2025

    +
    + {createTag("SEMINAR")} + {createTag("STRENGTH TRAINING")} +
    +

    + Whether you're looking to lose weight, gain muscle, or maintain a healthy body composition, our + nutritionists can help. We offer comprehensive weight management programs that combine nutrition education, + meal planning, and behavioral strategies. +

    +
    + + Read more + +
    +
    + ); +}; + +export default FeaturedEvent; From b03fccf626ff13b9e6ed88d925fdd861fc4e8818 Mon Sep 17 00:00:00 2001 From: Ivan Kiral Date: Wed, 6 Nov 2024 13:36:08 +0100 Subject: [PATCH 06/56] remove padding from container --- tailwind.config.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/tailwind.config.js b/tailwind.config.js index c19ae13..82f3728 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -24,13 +24,6 @@ export default { }, container: { center: true, - padding: { - DEFAULT: '1rem', - sm: '2rem', - lg: '4rem', - xl: '5rem', - '2xl': '6rem', - } } }, plugins: [], From bb33beb87cc42a3ecae3e9f2c75ec8d6a38817d1 Mon Sep 17 00:00:00 2001 From: Ivan Kiral Date: Wed, 6 Nov 2024 16:01:34 +0100 Subject: [PATCH 07/56] extract logo an navigation into components --- src/components/Header.tsx | 16 ++++------------ src/components/Logo.tsx | 13 +++++++++++++ src/components/Navigation.tsx | 19 +++++++++++++++++++ 3 files changed, 36 insertions(+), 12 deletions(-) create mode 100644 src/components/Logo.tsx create mode 100644 src/components/Navigation.tsx diff --git a/src/components/Header.tsx b/src/components/Header.tsx index 7c3148a..62d372b 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -1,21 +1,13 @@ import Container from "./Container"; +import Logo from "./Logo"; +import Navigation from "./Navigation"; const Header: React.FC = () => { - const createMenuLink = (name: string) => ( -
  • - {name} -
  • - ); - return (
    -

    Karma Health

    - + +
    ); diff --git a/src/components/Logo.tsx b/src/components/Logo.tsx new file mode 100644 index 0000000..fb17adb --- /dev/null +++ b/src/components/Logo.tsx @@ -0,0 +1,13 @@ +import { FC } from "react"; + +const Logo: FC = () => ( +
    + + + + +

    Karma Health

    +
    +); + +export default Logo; diff --git a/src/components/Navigation.tsx b/src/components/Navigation.tsx new file mode 100644 index 0000000..ccaa506 --- /dev/null +++ b/src/components/Navigation.tsx @@ -0,0 +1,19 @@ +import { FC } from "react"; + +const Navigation: FC = () => { + const createMenuLink = (name: string) => ( +
  • + {name} +
  • + ); + + return ( + + ); +}; + +export default Navigation; From 52637636e664460eec854385e02159b0c04d2b1b Mon Sep 17 00:00:00 2001 From: Ivan Kiral Date: Wed, 6 Nov 2024 16:01:44 +0100 Subject: [PATCH 08/56] add footer --- src/App.tsx | 2 ++ src/components/Footer.tsx | 17 +++++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 src/components/Footer.tsx diff --git a/src/App.tsx b/src/App.tsx index ba4a7b5..22124fe 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -2,6 +2,7 @@ import Container from "./components/Container"; import Divider from "./components/Divider"; import FeaturedArticle from "./components/FeaturedArticle"; import FeaturedEvent from "./components/FeaturedEvent"; +import Footer from "./components/Footer"; import Header from "./components/Header"; import HeroImage from "./components/HeroImage"; import Video from "./components/Video"; @@ -28,6 +29,7 @@ function App() { +
    ); } diff --git a/src/components/Footer.tsx b/src/components/Footer.tsx new file mode 100644 index 0000000..1a4a582 --- /dev/null +++ b/src/components/Footer.tsx @@ -0,0 +1,17 @@ +import { FC } from "react"; +import Logo from "./Logo"; +import Navigation from "./Navigation"; +import Divider from "./Divider"; + +const Footer: FC = () => ( +
    +
    + + +
    + +

    ©2024 Karma Health, LLC. All Rights Reserved.

    +
    +); + +export default Footer; From 1a74b3cc13fc76766ca1cb98a90d9b6cc0b6cbe3 Mon Sep 17 00:00:00 2001 From: Ivan Kiral Date: Thu, 7 Nov 2024 11:00:15 +0100 Subject: [PATCH 09/56] Refactoring and responsive design --- src/App.tsx | 28 ++++++++++---------- src/components/FeaturedArticle.tsx | 27 +++++++------------- src/components/FeaturedContent.tsx | 29 +++++++++++++++++++++ src/components/FeaturedEvent.tsx | 29 ++++++++------------- src/components/Header.tsx | 2 +- src/components/HeroImage.tsx | 41 +++++++++++++----------------- src/components/Logo.tsx | 2 +- src/components/Navigation.tsx | 2 +- src/components/PageSection.tsx | 18 +++++++++++++ src/components/Video.tsx | 4 +-- 10 files changed, 102 insertions(+), 80 deletions(-) create mode 100644 src/components/FeaturedContent.tsx create mode 100644 src/components/PageSection.tsx diff --git a/src/App.tsx b/src/App.tsx index 22124fe..1f4ab86 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,10 +1,10 @@ -import Container from "./components/Container"; import Divider from "./components/Divider"; import FeaturedArticle from "./components/FeaturedArticle"; import FeaturedEvent from "./components/FeaturedEvent"; import Footer from "./components/Footer"; import Header from "./components/Header"; import HeroImage from "./components/HeroImage"; +import PageSection from "./components/PageSection"; import Video from "./components/Video"; import "./index.css"; @@ -12,23 +12,21 @@ function App() { return (
    - - -
    + + + + +
    - -
    - - - -
    +
    + + + -
    - - - -
    + + +
    ); diff --git a/src/components/FeaturedArticle.tsx b/src/components/FeaturedArticle.tsx index eca7a0b..0902fae 100644 --- a/src/components/FeaturedArticle.tsx +++ b/src/components/FeaturedArticle.tsx @@ -1,32 +1,23 @@ import React from "react"; +import FeaturedContent from "./FeaturedContent"; const FeaturedArticle: React.FC = () => { return ( -
    -
    - - FEATURED ARTICLE - - Article -
    -
    + + <>
    -

    Article Title

    -

    Published on Dec 10, 2024

    -

    +

    Article Title

    +

    Published on Dec 10, 2024

    +

    Optimize your athletic performance with our sports nutrition services. We provide tailored advice on fueling strategies, hydration, and nutrient timing to help you reach your peak potential.

    - + Read more -
    -
    + + ); }; diff --git a/src/components/FeaturedContent.tsx b/src/components/FeaturedContent.tsx new file mode 100644 index 0000000..553bbf8 --- /dev/null +++ b/src/components/FeaturedContent.tsx @@ -0,0 +1,29 @@ +import { FC, PropsWithChildren } from "react"; + +type FeaturedContentProps = PropsWithChildren< + Readonly<{ + type: "article" | "event"; + }> +>; + +const FeaturedContent: FC = ({ type, children }) => { + return ( +
    +
    + + {type === "event" ? "FEATURED EVENT" : "FEATURED ARTICLE"} + + Article +
    +
    + {children} +
    +
    + ); +}; + +export default FeaturedContent; diff --git a/src/components/FeaturedEvent.tsx b/src/components/FeaturedEvent.tsx index 9ba5d67..b66267f 100644 --- a/src/components/FeaturedEvent.tsx +++ b/src/components/FeaturedEvent.tsx @@ -1,4 +1,5 @@ import React from "react"; +import FeaturedContent from "./FeaturedContent"; const FeaturedEvent: React.FC = () => { const createTag = (text: string) => ( @@ -8,36 +9,26 @@ const FeaturedEvent: React.FC = () => { ); return ( -
    -
    - - FEATURED EVENT - - Article -
    -
    + + <>
    -

    Event Name

    -

    Jan 4, 2025 - Jan 6, 2025

    -
    +

    Event Name

    +

    Jan 4, 2025 - Jan 6, 2025

    +
    {createTag("SEMINAR")} {createTag("STRENGTH TRAINING")}
    -

    +

    Whether you're looking to lose weight, gain muscle, or maintain a healthy body composition, our nutritionists can help. We offer comprehensive weight management programs that combine nutrition education, meal planning, and behavioral strategies.

    - + Read more -
    -
    + + ); }; diff --git a/src/components/Header.tsx b/src/components/Header.tsx index 62d372b..abaa92d 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -5,7 +5,7 @@ import Navigation from "./Navigation"; const Header: React.FC = () => { return ( -
    +
    diff --git a/src/components/HeroImage.tsx b/src/components/HeroImage.tsx index 38c2c22..3aaf833 100644 --- a/src/components/HeroImage.tsx +++ b/src/components/HeroImage.tsx @@ -1,30 +1,25 @@ import { FC } from "react"; -import Container from "./Container"; const HeroImage: FC = () => { return ( -
    - -
    -
    -

    - Welcome To Karma Health's Nutritional Services -

    -

    - At Karma Health, we believe that good nutrition is the foundation of a healthy, vibrant life. Our team of - expert nutritionists and registered dietitians is dedicated to helping you achieve your wellness goals - through personalized, evidence-based nutritional guidance. -

    -
    - - -
    -
    +
    +
    +

    + Welcome To Karma Health's Nutritional Services +

    +

    + At Karma Health, we believe that good nutrition is the foundation of a healthy, vibrant life. Our team of + expert nutritionists and registered dietitians is dedicated to helping you achieve your wellness goals through + personalized, evidence-based nutritional guidance. +

    +
    +
    + + +
    ); }; diff --git a/src/components/Logo.tsx b/src/components/Logo.tsx index fb17adb..0acb061 100644 --- a/src/components/Logo.tsx +++ b/src/components/Logo.tsx @@ -6,7 +6,7 @@ const Logo: FC = () => ( -

    Karma Health

    +

    Karma Health

    ); diff --git a/src/components/Navigation.tsx b/src/components/Navigation.tsx index ccaa506..64f8efb 100644 --- a/src/components/Navigation.tsx +++ b/src/components/Navigation.tsx @@ -9,7 +9,7 @@ const Navigation: FC = () => { return ( diff --git a/src/components/PageSection.tsx b/src/components/PageSection.tsx new file mode 100644 index 0000000..12d3070 --- /dev/null +++ b/src/components/PageSection.tsx @@ -0,0 +1,18 @@ +import { FC, PropsWithChildren } from "react"; +import Container from "./Container"; + +type PageSectionProps = PropsWithChildren< + Readonly<{ + color: string; + }> +>; + +const PageSection: FC = ({ children, color }) => ( +
    + + {children} + +
    +); + +export default PageSection; diff --git a/src/components/Video.tsx b/src/components/Video.tsx index a006e7f..8ab0514 100644 --- a/src/components/Video.tsx +++ b/src/components/Video.tsx @@ -2,8 +2,8 @@ import { FC } from "react"; const Video: FC = () => { return ( -
    -

    +
    +

    Personalized Nutrition Plans

    From 1c59d2f0fb1c4bbae60c42fd7d547c66ee36342e Mon Sep 17 00:00:00 2001 From: Ivan Kiral Date: Thu, 7 Nov 2024 12:08:29 +0100 Subject: [PATCH 10/56] add delivery sdk and add options to for formatting --- package-lock.json | 476 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 7 + 2 files changed, 483 insertions(+) diff --git a/package-lock.json b/package-lock.json index ec8a995..86b646b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,12 +8,17 @@ "name": "kickstart-react-app", "version": "0.0.0", "dependencies": { + "@kontent-ai/delivery-sdk": "^15.2.0", + "@tanstack/react-query": "^5.59.20", + "dotenv": "^16.4.5", "react": "^18.3.1", "react-dom": "^18.3.1" }, "devDependencies": { "@eslint/js": "^8.57.1", "@kontent-ai/eslint-config": "^1.0.2", + "@kontent-ai/model-generator": "^8.0.0-8", + "@types/node": "^22.9.0", "@types/react": "^18.3.11", "@types/react-dom": "^18.3.1", "@vitejs/plugin-react": "^4.3.3", @@ -1085,6 +1090,32 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@kontent-ai/core-sdk": { + "version": "10.8.0", + "resolved": "https://registry.npmjs.org/@kontent-ai/core-sdk/-/core-sdk-10.8.0.tgz", + "integrity": "sha512-6o5kn+ANhJ7vCucWXunxy1qCSSDsN3F86zdLXzPnFaK/qOf4BJGnPda81Alvnt4N7n4e1m9J7uP0tm3tQ/W25Q==", + "license": "MIT", + "dependencies": { + "axios": "1.7.7" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@kontent-ai/delivery-sdk": { + "version": "15.2.0", + "resolved": "https://registry.npmjs.org/@kontent-ai/delivery-sdk/-/delivery-sdk-15.2.0.tgz", + "integrity": "sha512-ozo7L9TWDlh3Zo3ZsIL9plj7r1QmrMKMLUz4JpTc5nyNF9ZYws3EUjydUpUvjKR7MYm9OeqQcCgiOTSvc9wwdQ==", + "license": "MIT", + "dependencies": { + "@kontent-ai/core-sdk": "10.8.0", + "url-parse": "1.5.10", + "uuid": "10.0.0" + }, + "engines": { + "node": ">= 20" + } + }, "node_modules/@kontent-ai/eslint-config": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@kontent-ai/eslint-config/-/eslint-config-1.0.2.tgz", @@ -1104,6 +1135,54 @@ "eslint-plugin-simple-import-sort": "^10.0.0" } }, + "node_modules/@kontent-ai/management-sdk": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@kontent-ai/management-sdk/-/management-sdk-7.5.0.tgz", + "integrity": "sha512-/yYTg+els2qstXZbT2QqI2waNuwc3rhgJMy1F1fceQhXJh5wXuThp5O+KUfjGJEfVfzu7vg1cx4pm8R3G6YtkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@kontent-ai/core-sdk": "10.8.0", + "mime": "3.0.0" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@kontent-ai/model-generator": { + "version": "8.0.0-8", + "resolved": "https://registry.npmjs.org/@kontent-ai/model-generator/-/model-generator-8.0.0-8.tgz", + "integrity": "sha512-QOjiOADlzsMmkixp2ieujWl6c9v6KVoMel9MEtBOAD9pCeBaiYH2e5I35ScsIYSD/nWCByIoT/Udg3gfoPNLig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@kontent-ai/delivery-sdk": "15.2.0", + "@kontent-ai/management-sdk": "7.5.0", + "chalk": "5.3.0", + "prettier": "3.3.3", + "ts-pattern": "5.4.0", + "yargs": "17.7.2" + }, + "bin": { + "kontent-generate": "dist/lib/code/app.js" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@kontent-ai/model-generator/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -1385,6 +1464,32 @@ "license": "MIT", "peer": true }, + "node_modules/@tanstack/query-core": { + "version": "5.59.20", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.59.20.tgz", + "integrity": "sha512-e8vw0lf7KwfGe1if4uPFhvZRWULqHjFcz3K8AebtieXvnMOz5FSzlZe3mTLlPuUBcydCnBRqYs2YJ5ys68wwLg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/react-query": { + "version": "5.59.20", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.59.20.tgz", + "integrity": "sha512-Zly0egsK0tFdfSbh5/mapSa+Zfc3Et0Zkar7Wo5sQkFzWyB3p3uZWOHR2wrlAEEV2L953eLuDBtbgFvMYiLvUw==", + "license": "MIT", + "dependencies": { + "@tanstack/query-core": "5.59.20" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^18 || ^19" + } + }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -1453,6 +1558,16 @@ "license": "MIT", "peer": true }, + "node_modules/@types/node": { + "version": "22.9.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.9.0.tgz", + "integrity": "sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.8" + } + }, "node_modules/@types/prop-types": { "version": "15.7.13", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz", @@ -2448,6 +2563,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, "node_modules/autoprefixer": { "version": "10.4.20", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", @@ -2503,6 +2624,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/axios": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -2695,6 +2827,97 @@ "node": ">= 6" } }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/cliui/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/cliui/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -2712,6 +2935,18 @@ "dev": true, "license": "MIT" }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/commander": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", @@ -2891,6 +3126,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/didyoumean": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", @@ -2931,6 +3175,18 @@ "node": ">=6.0.0" } }, + "node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, "node_modules/dprint": { "version": "0.47.4", "resolved": "https://registry.npmjs.org/dprint/-/dprint-0.47.4.tgz", @@ -3980,6 +4236,26 @@ "dev": true, "license": "ISC" }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -4008,6 +4284,20 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/form-data": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fraction.js": { "version": "4.3.7", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", @@ -4095,6 +4385,16 @@ "node": ">=6.9.0" } }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, "node_modules/get-intrinsic": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", @@ -5079,6 +5379,40 @@ "node": ">=8.6" } }, + "node_modules/mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -5696,6 +6030,22 @@ "node": ">= 0.8.0" } }, + "node_modules/prettier": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", + "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", @@ -5709,6 +6059,12 @@ "react-is": "^16.13.1" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -5719,6 +6075,12 @@ "node": ">=6" } }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "license": "MIT" + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -5849,6 +6211,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "license": "MIT" + }, "node_modules/resolve": { "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", @@ -6548,6 +6926,13 @@ "dev": true, "license": "Apache-2.0" }, + "node_modules/ts-pattern": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/ts-pattern/-/ts-pattern-5.4.0.tgz", + "integrity": "sha512-hgfOMfjlrARCnYtGD/xEAkFHDXuSyuqjzFSltyQCbN689uNvoQL20TVN2XFcLMjfNuwSsQGU+xtH6MrjIwhwUg==", + "dev": true, + "license": "MIT" + }, "node_modules/tsconfig-paths": { "version": "3.15.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", @@ -6851,6 +7236,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "dev": true, + "license": "MIT" + }, "node_modules/update-browserslist-db": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", @@ -6892,6 +7284,16 @@ "punycode": "^2.1.0" } }, + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "license": "MIT", + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -6899,6 +7301,19 @@ "dev": true, "license": "MIT" }, + "node_modules/uuid": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/vite": { "version": "5.4.10", "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.10.tgz", @@ -7216,6 +7631,16 @@ "dev": true, "license": "ISC" }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", @@ -7236,6 +7661,57 @@ "node": ">= 14" } }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/package.json b/package.json index f434fc0..3da7354 100644 --- a/package.json +++ b/package.json @@ -7,15 +7,22 @@ "dev": "vite", "build": "tsc -b && vite build", "lint": "eslint .", + "fmt": "dprint fmt", + "fmt:check": "dprint check", "preview": "vite preview" }, "dependencies": { + "@kontent-ai/delivery-sdk": "^15.2.0", + "@tanstack/react-query": "^5.59.20", + "dotenv": "^16.4.5", "react": "^18.3.1", "react-dom": "^18.3.1" }, "devDependencies": { "@eslint/js": "^8.57.1", "@kontent-ai/eslint-config": "^1.0.2", + "@kontent-ai/model-generator": "^8.0.0-8", + "@types/node": "^22.9.0", "@types/react": "^18.3.11", "@types/react-dom": "^18.3.1", "@vitejs/plugin-react": "^4.3.3", From 8b449a938602020b78b84d8ae934237fd5ee25d2 Mon Sep 17 00:00:00 2001 From: Ivan Kiral Date: Thu, 7 Nov 2024 12:08:57 +0100 Subject: [PATCH 11/56] add generated model from environment --- .env.template | 5 + .gitignore | 2 + generateModel.ts | 30 +++ src/model/content-type-snippets/index.ts | 16 ++ src/model/content-types/article.ts | 79 ++++++ src/model/content-types/event.ts | 98 ++++++++ src/model/content-types/index.ts | 19 ++ src/model/content-types/landing_page.ts | 80 ++++++ src/model/content-types/video.ts | 61 +++++ src/model/index.ts | 19 ++ src/model/project/assetFolders.ts | 4 + src/model/project/collections.ts | 13 + src/model/project/contentTypeSnippets.ts | 4 + src/model/project/contentTypes.ts | 302 +++++++++++++++++++++++ src/model/project/index.ts | 9 + src/model/project/languages.ts | 17 ++ src/model/project/roles.ts | 13 + src/model/project/taxonomies.ts | 122 +++++++++ src/model/project/webhooks.ts | 4 + src/model/project/workflows.ts | 37 +++ src/model/system/core.type.ts | 31 +++ src/model/system/delivery.codenames.ts | 63 +++++ src/model/system/index.ts | 17 ++ src/model/taxonomies/event_type.ts | 22 ++ src/model/taxonomies/index.ts | 17 ++ src/model/taxonomies/topics.ts | 31 +++ 26 files changed, 1115 insertions(+) create mode 100644 .env.template create mode 100644 generateModel.ts create mode 100644 src/model/content-type-snippets/index.ts create mode 100644 src/model/content-types/article.ts create mode 100644 src/model/content-types/event.ts create mode 100644 src/model/content-types/index.ts create mode 100644 src/model/content-types/landing_page.ts create mode 100644 src/model/content-types/video.ts create mode 100644 src/model/index.ts create mode 100644 src/model/project/assetFolders.ts create mode 100644 src/model/project/collections.ts create mode 100644 src/model/project/contentTypeSnippets.ts create mode 100644 src/model/project/contentTypes.ts create mode 100644 src/model/project/index.ts create mode 100644 src/model/project/languages.ts create mode 100644 src/model/project/roles.ts create mode 100644 src/model/project/taxonomies.ts create mode 100644 src/model/project/webhooks.ts create mode 100644 src/model/project/workflows.ts create mode 100644 src/model/system/core.type.ts create mode 100644 src/model/system/delivery.codenames.ts create mode 100644 src/model/system/index.ts create mode 100644 src/model/taxonomies/event_type.ts create mode 100644 src/model/taxonomies/index.ts create mode 100644 src/model/taxonomies/topics.ts diff --git a/.env.template b/.env.template new file mode 100644 index 0000000..b50ee2e --- /dev/null +++ b/.env.template @@ -0,0 +1,5 @@ +VITE_ENVIRONMENT_ID= +VITE_DELIVERY_API_KEY= + +# used only for model generation +VITE_MAPI_API_KEY= \ No newline at end of file diff --git a/.gitignore b/.gitignore index a547bf3..3b0b403 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,5 @@ dist-ssr *.njsproj *.sln *.sw? + +.env \ No newline at end of file diff --git a/generateModel.ts b/generateModel.ts new file mode 100644 index 0000000..c9867cd --- /dev/null +++ b/generateModel.ts @@ -0,0 +1,30 @@ +import dotenv from 'dotenv'; +import {generateDeliveryModelsAsync} from "@kontent-ai/model-generator"; + + +dotenv.config(); + +const {VITE_ENVIRONMENT_ID, VITE_MAPI_API_KEY} = process.env; + +if(!VITE_ENVIRONMENT_ID){ + throw new Error("VITE_ENVIRONMENT_ID cannot be empty!"); +} + +if(!VITE_MAPI_API_KEY){ + throw new Error("VITE_DELIVERY_API_KEY cannot be empty!"); +} + +await generateDeliveryModelsAsync( + { + environmentId: VITE_ENVIRONMENT_ID, + apiKey: VITE_MAPI_API_KEY, + addTimestamp: false, + outputDir: "./src/model", + moduleFileExtension: "ts", + fileResolvers: { + taxonomy: "camelCase", + contentType: "camelCase", + snippet: "camelCase" + } + } +); \ No newline at end of file diff --git a/src/model/content-type-snippets/index.ts b/src/model/content-type-snippets/index.ts new file mode 100644 index 0000000..20e84c3 --- /dev/null +++ b/src/model/content-type-snippets/index.ts @@ -0,0 +1,16 @@ + +/** +* This file has been auto-generated by '@kontent-ai/model-generator@8.0.0-5'. +* +* (c) Kontent.ai +* +* ------------------------------------------------------------------------------- +* +* Project: Kontent.ai Kickstart +* Environment: Production +* Id: 7cf79e13-fcde-01b6-f508-14ca05d794b8 +* +* ------------------------------------------------------------------------------- +**/ + +export {}; diff --git a/src/model/content-types/article.ts b/src/model/content-types/article.ts new file mode 100644 index 0000000..3076ea9 --- /dev/null +++ b/src/model/content-types/article.ts @@ -0,0 +1,79 @@ + +/** +* This file has been auto-generated by '@kontent-ai/model-generator@8.0.0-5'. +* +* (c) Kontent.ai +* +* ------------------------------------------------------------------------------- +* +* Project: Kontent.ai Kickstart +* Environment: Production +* Id: 7cf79e13-fcde-01b6-f508-14ca05d794b8 +* +* ------------------------------------------------------------------------------- +**/ + +import type { Elements } from '@kontent-ai/delivery-sdk'; +import type { CoreContentType } from '../system/index.ts'; + +/** + * Type representing all available element codenames for Article + */ +export type ArticleElementCodenames = 'title' | 'introduction' | 'image' | 'body_copy' | 'publish_date'; + +/** + * Article + * + * Id: decfd6d7-5392-4740-bdb7-f689264713bb + * Codename: article + */ +export type Article = CoreContentType< + { + /** + * Title + * + * Type: text + * Required: false + * Codename: title + * Id: 6715c085-15e3-411f-adb6-94f2b08013cc + */ + readonly title: Elements.TextElement; + /** + * Introduction + * + * Type: text + * Required: false + * Codename: introduction + * Id: 05ec475e-bb61-4572-8ce0-5eec942925dd + */ + readonly introduction: Elements.TextElement; + /** + * Image + * + * Type: asset + * Required: false + * Codename: image + * Id: f9763b82-4733-4a4e-8aac-e695ea97412e + */ + readonly image: Elements.AssetsElement; + /** + * Body Copy + * + * Type: rich_text + * Required: false + * Codename: body_copy + * Id: f538ae1c-2d68-40a8-91f8-f276b0237152 + */ + readonly body_copy: Elements.RichTextElement; + /** + * Publish Date + * + * Type: date_time + * Required: false + * Codename: publish_date + * Id: 0e33b980-1d7a-405e-b02a-3ab76fcffc3b + */ + readonly publish_date: Elements.DateTimeElement; + }, + 'article' +>; diff --git a/src/model/content-types/event.ts b/src/model/content-types/event.ts new file mode 100644 index 0000000..5b82d90 --- /dev/null +++ b/src/model/content-types/event.ts @@ -0,0 +1,98 @@ + +/** +* This file has been auto-generated by '@kontent-ai/model-generator@8.0.0-5'. +* +* (c) Kontent.ai +* +* ------------------------------------------------------------------------------- +* +* Project: Kontent.ai Kickstart +* Environment: Production +* Id: 7cf79e13-fcde-01b6-f508-14ca05d794b8 +* +* ------------------------------------------------------------------------------- +**/ + +import type { Elements } from '@kontent-ai/delivery-sdk'; +import type { CoreContentType } from '../system/index.ts'; +import type { EventType, Topics } from '../taxonomies/index.ts'; + +/** + * Type representing all available element codenames for Event + */ +export type EventElementCodenames = 'name' | 'description' | 'asset' | 'start_date' | 'end_date' | 'event_type' | 'event_topic'; + +/** + * Event + * + * Id: 446d4c1e-5049-4e45-ae1c-4284e660fe68 + * Codename: event + */ +export type Event = CoreContentType< + { + /** + * Name + * + * Type: text + * Required: false + * Codename: name + * Id: 42ee07e2-3b03-4795-9843-da0731645a20 + */ + readonly name: Elements.TextElement; + /** + * Description + * + * Type: rich_text + * Required: false + * Codename: description + * Id: a30856f6-4700-48ec-b009-f1b24f4b41c2 + */ + readonly description: Elements.RichTextElement; + /** + * Asset + * + * Type: asset + * Required: false + * Codename: asset + * Id: 3e1b3668-0605-4f19-a689-a088448d49c0 + */ + readonly asset: Elements.AssetsElement; + /** + * Start date + * + * Type: date_time + * Required: false + * Codename: start_date + * Id: 980d800f-cd12-43a0-ab4c-5c0e50cea0b9 + */ + readonly start_date: Elements.DateTimeElement; + /** + * End Date + * + * Type: date_time + * Required: false + * Codename: end_date + * Id: c33d2553-e161-4b2f-81e2-43f06c945f08 + */ + readonly end_date: Elements.DateTimeElement; + /** + * Event Type + * + * Type: taxonomy + * Required: false + * Codename: event_type + * Id: b36909a0-b8f2-4f09-9676-795ea5ce49f7 + */ + readonly event_type: Elements.TaxonomyElement; + /** + * Topics + * + * Type: taxonomy + * Required: false + * Codename: event_topic + * Id: 6ab84c72-0db5-4c09-88f8-d9bdefbc9849 + */ + readonly event_topic: Elements.TaxonomyElement; + }, + 'event' +>; diff --git a/src/model/content-types/index.ts b/src/model/content-types/index.ts new file mode 100644 index 0000000..04cb031 --- /dev/null +++ b/src/model/content-types/index.ts @@ -0,0 +1,19 @@ + +/** +* This file has been auto-generated by '@kontent-ai/model-generator@8.0.0-5'. +* +* (c) Kontent.ai +* +* ------------------------------------------------------------------------------- +* +* Project: Kontent.ai Kickstart +* Environment: Production +* Id: 7cf79e13-fcde-01b6-f508-14ca05d794b8 +* +* ------------------------------------------------------------------------------- +**/ + +export * from './article.ts'; +export * from './event.ts'; +export * from './landing_page.ts'; +export * from './video.ts'; diff --git a/src/model/content-types/landing_page.ts b/src/model/content-types/landing_page.ts new file mode 100644 index 0000000..8f1df41 --- /dev/null +++ b/src/model/content-types/landing_page.ts @@ -0,0 +1,80 @@ + +/** +* This file has been auto-generated by '@kontent-ai/model-generator@8.0.0-5'. +* +* (c) Kontent.ai +* +* ------------------------------------------------------------------------------- +* +* Project: Kontent.ai Kickstart +* Environment: Production +* Id: 7cf79e13-fcde-01b6-f508-14ca05d794b8 +* +* ------------------------------------------------------------------------------- +**/ + +import type { Elements } from '@kontent-ai/delivery-sdk'; +import type { CoreContentType } from '../system/index.ts'; +import type { Video, Event, Article } from './index.ts'; + +/** + * Type representing all available element codenames for Landing Page + */ +export type LandingPageElementCodenames = 'headline' | 'subheadline' | 'hero_image' | 'body_copy' | 'featured_content'; + +/** + * Landing Page + * + * Id: 9c8cf106-199f-4535-856b-a66e97399b42 + * Codename: landing_page + */ +export type LandingPage = CoreContentType< + { + /** + * Headline + * + * Type: text + * Required: false + * Codename: headline + * Id: 3c5fca8b-a024-42fe-b2ec-eb2d2f8e6ca8 + */ + readonly headline: Elements.TextElement; + /** + * Subheadline + * + * Type: text + * Required: false + * Codename: subheadline + * Id: a19250b6-c8e1-4871-bf83-956e95782d7c + */ + readonly subheadline: Elements.TextElement; + /** + * Hero Image + * + * Type: asset + * Required: false + * Codename: hero_image + * Id: 9f33cab3-4496-489a-8b36-0a602b3b41a3 + */ + readonly hero_image: Elements.AssetsElement; + /** + * Body Copy + * + * Type: rich_text + * Required: false + * Codename: body_copy + * Id: d52b6c00-2b3d-4978-b5d8-f80703601f20 + */ + readonly body_copy: Elements.RichTextElement

    -
    - - - - -
    -
    -
    - - - - - - - -
    -
    - ); -} - -export default App; diff --git a/src/LandingPage.tsx b/src/LandingPage.tsx new file mode 100644 index 0000000..22d9809 --- /dev/null +++ b/src/LandingPage.tsx @@ -0,0 +1,64 @@ +import Divider from "./components/Divider"; +import FeaturedArticle from "./components/FeaturedArticle"; +import FeaturedEvent from "./components/FeaturedEvent"; +import Footer from "./components/Footer"; +import Header from "./components/Header"; +import HeroImage from "./components/HeroImage"; +import PageSection from "./components/PageSection"; +import Video from "./components/Video"; +import "./index.css"; +import type { Article, Event, LandingPage } from "./model"; +import { createClient } from "./utils/client"; +import { useQuery } from "@tanstack/react-query"; + +const LandingPage = () => { + const landingPage = useQuery({ + queryKey: ["landing_page"], + queryFn: () => + createClient( + import.meta.env.VITE_ENVIRONMENT_ID!, + import.meta.env.VITE_DELIVERY_API_KEY!, + ) + .item("landing_page") + .toPromise() + .then(res => res.data.item), + }); + + if (landingPage.isPending) { + return
    Loading...
    ; + } + + if (landingPage.isError) { + return
    Error {landingPage.error.message}
    ; + } + + return ( +
    +
    + + + + +
    +
    +
    + + + + + + + +
    +
    + ); +}; + +export default LandingPage; diff --git a/src/components/FeaturedArticle.tsx b/src/components/FeaturedArticle.tsx index 0902fae..c2d7ada 100644 --- a/src/components/FeaturedArticle.tsx +++ b/src/components/FeaturedArticle.tsx @@ -1,16 +1,28 @@ import React from "react"; import FeaturedContent from "./FeaturedContent"; +import { Article } from "../model"; -const FeaturedArticle: React.FC = () => { +type FeaturedArticleProps = Readonly<{ + article: Article; +}>; + +const FeaturedArticle: React.FC = ({ article }) => { return ( - + <>
    -

    Article Title

    -

    Published on Dec 10, 2024

    +

    + {article.elements.title.value} +

    +

    + Published on {new Date(article.elements.publish_date.value!).toLocaleDateString("en-US", { + month: "short", + year: "numeric", + day: "numeric", + })} +

    - Optimize your athletic performance with our sports nutrition services. We provide tailored advice on fueling - strategies, hydration, and nutrient timing to help you reach your peak potential. + {article.elements.introduction.value}

    diff --git a/src/components/FeaturedContent.tsx b/src/components/FeaturedContent.tsx index 553bbf8..e909a09 100644 --- a/src/components/FeaturedContent.tsx +++ b/src/components/FeaturedContent.tsx @@ -1,12 +1,14 @@ +import { Elements } from "@kontent-ai/delivery-sdk"; import { FC, PropsWithChildren } from "react"; type FeaturedContentProps = PropsWithChildren< Readonly<{ type: "article" | "event"; + image: Elements.AssetsElement; }> >; -const FeaturedContent: FC = ({ type, children }) => { +const FeaturedContent: FC = ({ type, image, children }) => { return (
    @@ -14,8 +16,8 @@ const FeaturedContent: FC = ({ type, children }) => { {type === "event" ? "FEATURED EVENT" : "FEATURED ARTICLE"} Article
    diff --git a/src/components/FeaturedEvent.tsx b/src/components/FeaturedEvent.tsx index b66267f..4e1ec1c 100644 --- a/src/components/FeaturedEvent.tsx +++ b/src/components/FeaturedEvent.tsx @@ -1,7 +1,13 @@ -import React from "react"; +import { FC } from "react"; import FeaturedContent from "./FeaturedContent"; +import { Event } from "../model"; +import { formatDate } from "../utils/date"; -const FeaturedEvent: React.FC = () => { +type FeaturedEventProps = Readonly<{ + data: Event; +}>; + +const FeaturedEvent: FC = ({ data }) => { const createTag = (text: string) => (

    {text}

    @@ -9,19 +15,21 @@ const FeaturedEvent: React.FC = () => { ); return ( - + <>
    -

    Event Name

    -

    Jan 4, 2025 - Jan 6, 2025

    +

    {data.elements.name.value}

    +

    + {`${formatDate(data.elements.start_date.value as string)} - ${ + formatDate(data.elements.end_date.value as string) + }`} +

    - {createTag("SEMINAR")} - {createTag("STRENGTH TRAINING")} + {data.elements.event_type.value.map(t => createTag(t.name.toUpperCase()))} + {data.elements.event_topic.value.map(t => createTag(t.name.toUpperCase()))}

    - Whether you're looking to lose weight, gain muscle, or maintain a healthy body composition, our - nutritionists can help. We offer comprehensive weight management programs that combine nutrition education, - meal planning, and behavioral strategies. + {data.elements.description.value}

    diff --git a/src/components/HeroImage.tsx b/src/components/HeroImage.tsx index 3aaf833..1dd1430 100644 --- a/src/components/HeroImage.tsx +++ b/src/components/HeroImage.tsx @@ -1,22 +1,28 @@ import { FC } from "react"; -const HeroImage: FC = () => { +type HeroImageProps = Readonly<{ + data: { + headline: string; + subheadline: string; + heroImage: string; + }; +}>; + +const HeroImage: FC = ({ data }) => { return (

    - Welcome To Karma Health's Nutritional Services + {data.headline}

    - At Karma Health, we believe that good nutrition is the foundation of a healthy, vibrant life. Our team of - expert nutritionists and registered dietitians is dedicated to helping you achieve your wellness goals through - personalized, evidence-based nutritional guidance. + {data.subheadline}

    diff --git a/src/main.tsx b/src/main.tsx index 4aff025..52d7497 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,9 +1,14 @@ -import { StrictMode } from 'react' -import { createRoot } from 'react-dom/client' -import App from './App.tsx' +import { StrictMode } from "react"; +import { createRoot } from "react-dom/client"; +import LandingPage from "./LandingPage.tsx"; +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; -createRoot(document.getElementById('root')!).render( +const queryClient = new QueryClient(); + +createRoot(document.getElementById("root")!).render( - + + + , -) +); diff --git a/src/utils/client.ts b/src/utils/client.ts new file mode 100644 index 0000000..dd5313f --- /dev/null +++ b/src/utils/client.ts @@ -0,0 +1,10 @@ +import { createDeliveryClient } from "@kontent-ai/delivery-sdk"; + +export const createClient = (environmentId: string, previewApiKey: string) => + createDeliveryClient({ + environmentId, + previewApiKey: previewApiKey, + defaultQueryConfig: { + usePreviewMode: true, + }, + }); diff --git a/src/utils/date.ts b/src/utils/date.ts new file mode 100644 index 0000000..71d5966 --- /dev/null +++ b/src/utils/date.ts @@ -0,0 +1,6 @@ +export const formatDate = (date: string) => + new Date(date).toLocaleDateString("en-US", { + month: "short", + year: "numeric", + day: "numeric", + }); From ef1a1c862fc53c7b58eef20d7e4151d0bda9fd8e Mon Sep 17 00:00:00 2001 From: Ivan Kiral Date: Mon, 11 Nov 2024 11:10:56 +0100 Subject: [PATCH 13/56] fix typography --- tailwind.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tailwind.config.js b/tailwind.config.js index 82f3728..c702fbe 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -18,7 +18,7 @@ export default { creme: "#fff7e7" }, fontFamily: { - sans: ["Source Sans 3", 'Arial', 'sans-serif'], + sans: ['"Source Sans 3"', 'Arial', 'sans-serif'], libre: ['"Abhaya Libre"', "Arial"] } }, From 0f2c0673e05add96aa37f18c8c033d5b80608187 Mon Sep 17 00:00:00 2001 From: Ivan Kiral Date: Mon, 11 Nov 2024 11:13:54 +0100 Subject: [PATCH 14/56] use rich text resolver for rich text elements --- package-lock.json | 206 +++++++++++++++++++++++++++++++ package.json | 2 + src/LandingPage.tsx | 8 +- src/components/FeaturedEvent.tsx | 30 +++-- src/components/PageContent.tsx | 38 ++++++ src/components/Video.tsx | 22 ++-- 6 files changed, 283 insertions(+), 23 deletions(-) create mode 100644 src/components/PageContent.tsx diff --git a/package-lock.json b/package-lock.json index 86b646b..562e85c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,8 @@ "version": "0.0.0", "dependencies": { "@kontent-ai/delivery-sdk": "^15.2.0", + "@kontent-ai/rich-text-resolver": "^1.2.1", + "@portabletext/react": "^3.1.0", "@tanstack/react-query": "^5.59.20", "dotenv": "^16.4.5", "react": "^18.3.1", @@ -1183,6 +1185,18 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/@kontent-ai/rich-text-resolver": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@kontent-ai/rich-text-resolver/-/rich-text-resolver-1.2.1.tgz", + "integrity": "sha512-ck3LMxbComoz+UXqoDvHuRJ8WAxWJAeKRCuhqMUY0k0cF+9pV4p2Z6kuUFrCEq0qtyfirTq0akAHhM13zNz/ww==", + "license": "MIT", + "dependencies": { + "@portabletext/to-html": "^2.0.13", + "@portabletext/types": "^2.0.13", + "node-html-parser": "^6.1.13", + "short-unique-id": "^5.2.0" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -1232,6 +1246,56 @@ "node": ">=14" } }, + "node_modules/@portabletext/react": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@portabletext/react/-/react-3.1.0.tgz", + "integrity": "sha512-ZGHlvS+NvId9RSqnflN8xF2KVZgAgD399dK1GaycurnGNZGZYTd5nZmc8by1yL76Ar8n/dbVtouUDJIkO4Tupw==", + "license": "MIT", + "dependencies": { + "@portabletext/toolkit": "^2.0.15", + "@portabletext/types": "^2.0.13" + }, + "engines": { + "node": "^14.13.1 || >=16.0.0" + }, + "peerDependencies": { + "react": "^17 || ^18 || >=19.0.0-rc" + } + }, + "node_modules/@portabletext/to-html": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@portabletext/to-html/-/to-html-2.0.13.tgz", + "integrity": "sha512-T3zL+2RcPCPGCp7rRrGrNJnGAqkdlpiOZnb/wh4tjDYJevteGY+5hmA0/5idLXzLiPv6vT8Gld852Sc0aFXwUA==", + "license": "MIT", + "dependencies": { + "@portabletext/toolkit": "^2.0.15", + "@portabletext/types": "^2.0.13" + }, + "engines": { + "node": "^14.13.1 || >=16.0.0" + } + }, + "node_modules/@portabletext/toolkit": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/@portabletext/toolkit/-/toolkit-2.0.16.tgz", + "integrity": "sha512-aBvnD8MscoAlEIuZBn0Aksd+oCuoMGFOT3CtHIgRBaac0Vu4YnnMUF45xo/B/T5vmwWcnDXoJEJdn+SKDg1m+A==", + "license": "MIT", + "dependencies": { + "@portabletext/types": "^2.0.13" + }, + "engines": { + "node": "^14.13.1 || >=16.0.0" + } + }, + "node_modules/@portabletext/types": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@portabletext/types/-/types-2.0.13.tgz", + "integrity": "sha512-5xk5MSyQU9CrDho3Rsguj38jhijhD36Mk8S6mZo3huv6PM+t4M/5kJN2KFIxgvt4ONpvOEs1pVIZAV0cL0Vi+Q==", + "license": "MIT", + "engines": { + "node": "^14.13.1 || >=16.0.0 || >=18.0.0" + } + }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.24.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.0.tgz", @@ -2655,6 +2719,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "license": "ISC" + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -2986,6 +3056,34 @@ "node": ">= 8" } }, + "node_modules/css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, "node_modules/cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", @@ -3175,6 +3273,61 @@ "node": ">=6.0.0" } }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, "node_modules/dotenv": { "version": "16.4.5", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", @@ -3229,6 +3382,18 @@ "dev": true, "license": "MIT" }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/es-abstract": { "version": "1.23.3", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", @@ -4636,6 +4801,15 @@ "node": ">= 0.4" } }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "license": "MIT", + "bin": { + "he": "bin/he" + } + }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -5492,6 +5666,16 @@ "dev": true, "license": "MIT" }, + "node_modules/node-html-parser": { + "version": "6.1.13", + "resolved": "https://registry.npmjs.org/node-html-parser/-/node-html-parser-6.1.13.tgz", + "integrity": "sha512-qIsTMOY4C/dAa5Q5vsobRpOOvPfC4pB61UVW2uSwZNUp0QU/jCekTal1vMmbO0DgdHeLUJpv/ARmDqErVxA3Sg==", + "license": "MIT", + "dependencies": { + "css-select": "^5.1.0", + "he": "1.2.0" + } + }, "node_modules/node-releases": { "version": "2.0.18", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", @@ -5519,6 +5703,18 @@ "node": ">=0.10.0" } }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -6460,6 +6656,16 @@ "node": ">=8" } }, + "node_modules/short-unique-id": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/short-unique-id/-/short-unique-id-5.2.0.tgz", + "integrity": "sha512-cMGfwNyfDZ/nzJ2k2M+ClthBIh//GlZl1JEf47Uoa9XR11bz8Pa2T2wQO4bVrRdH48LrIDWJahQziKo3MjhsWg==", + "license": "Apache-2.0", + "bin": { + "short-unique-id": "bin/short-unique-id", + "suid": "bin/short-unique-id" + } + }, "node_modules/side-channel": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", diff --git a/package.json b/package.json index 3da7354..7abbe45 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,8 @@ }, "dependencies": { "@kontent-ai/delivery-sdk": "^15.2.0", + "@kontent-ai/rich-text-resolver": "^1.2.1", + "@portabletext/react": "^3.1.0", "@tanstack/react-query": "^5.59.20", "dotenv": "^16.4.5", "react": "^18.3.1", diff --git a/src/LandingPage.tsx b/src/LandingPage.tsx index 22d9809..d847f45 100644 --- a/src/LandingPage.tsx +++ b/src/LandingPage.tsx @@ -4,8 +4,8 @@ import FeaturedEvent from "./components/FeaturedEvent"; import Footer from "./components/Footer"; import Header from "./components/Header"; import HeroImage from "./components/HeroImage"; +import PageContent from "./components/PageContent"; import PageSection from "./components/PageSection"; -import Video from "./components/Video"; import "./index.css"; import type { Article, Event, LandingPage } from "./model"; import { createClient } from "./utils/client"; @@ -45,16 +45,14 @@ const LandingPage = () => { /> -
    -
    +
    - +
    diff --git a/src/components/FeaturedEvent.tsx b/src/components/FeaturedEvent.tsx index 4e1ec1c..50e8c97 100644 --- a/src/components/FeaturedEvent.tsx +++ b/src/components/FeaturedEvent.tsx @@ -2,12 +2,22 @@ import { FC } from "react"; import FeaturedContent from "./FeaturedContent"; import { Event } from "../model"; import { formatDate } from "../utils/date"; +import { browserParse, transformToPortableText } from "@kontent-ai/rich-text-resolver"; +import { PortableText, PortableTextComponents } from "@portabletext/react"; type FeaturedEventProps = Readonly<{ - data: Event; + event: Event; }>; -const FeaturedEvent: FC = ({ data }) => { +const portableTextComponents: PortableTextComponents = { + block: { + normal: ({ children }) =>

    {children}

    , + }, +}; + +const FeaturedEvent: FC = ({ event }) => { + const descriptionPortableText = transformToPortableText(browserParse(event.elements.description.value)); + const createTag = (text: string) => (

    {text}

    @@ -15,22 +25,20 @@ const FeaturedEvent: FC = ({ data }) => { ); return ( - + <>
    -

    {data.elements.name.value}

    +

    {event.elements.name.value}

    - {`${formatDate(data.elements.start_date.value as string)} - ${ - formatDate(data.elements.end_date.value as string) + {`${formatDate(event.elements.start_date.value as string)} - ${ + formatDate(event.elements.end_date.value as string) }`}

    - {data.elements.event_type.value.map(t => createTag(t.name.toUpperCase()))} - {data.elements.event_topic.value.map(t => createTag(t.name.toUpperCase()))} + {event.elements.event_type.value.map(t => createTag(t.name.toUpperCase()))} + {event.elements.event_topic.value.map(t => createTag(t.name.toUpperCase()))}
    -

    - {data.elements.description.value} -

    +
    Read more diff --git a/src/components/PageContent.tsx b/src/components/PageContent.tsx new file mode 100644 index 0000000..8c6ea7f --- /dev/null +++ b/src/components/PageContent.tsx @@ -0,0 +1,38 @@ +import { FC } from "react"; +import { PortableText, PortableTextReactComponents, PortableTextTypeComponentProps } from "@portabletext/react"; +import { Elements } from "@kontent-ai/delivery-sdk"; +import { Video as VideoElement } from "../model"; +import Video from "./Video"; +import { browserParse, PortableTextComponent, transformToPortableText } from "@kontent-ai/rich-text-resolver"; + +type PageContentProps = { + body: Elements.RichTextElement; +}; + +const PageContent: FC = ({ body }) => { + const parsedTree = browserParse(body.value); + const portableText = transformToPortableText(parsedTree); + + return ( +
    + +
    + ); +}; + +const createPortableTextComponents = ( + element: Elements.RichTextElement, +): Partial => ({ + types: { + component: ({ value }: PortableTextTypeComponentProps) => { + const item = element.linkedItems.find(item => item.system.codename === value.component._ref); + if (!item) { + return
    Did not find any item with codename{value.component._ref}
    ; + } + + return