From ec759daa824b5bcf572e05119cd5fa155adb12b3 Mon Sep 17 00:00:00 2001 From: Koen van Meijeren Date: Fri, 8 Dec 2023 15:04:13 +0100 Subject: [PATCH] [US-206] Feat/us 206 theme item card (#155) * feat: :sparkles: Thematically done. * chore: :construction: Update title fonts * chore: :construction: Update translations * chore: :construction: Theme the see all button * bug: :ambulance: Fix home screen * chore: :construction: Improve namespacing of components and screens * feat: :sparkles: Implement the redesign of the theme items * chore: :construction: Remove unused imports * chore: :construction: Update translations * chore: :construction: Show the image of theme items * chore: :construction: Run eslint * chore: :construction: Fix E2E tests * feat: :sparkles: Show the theme cards on the home screen * feat: :sparkles: Add haptic feedback * chore: :construction: Optimize theme card on mobile screen * chore: :construction: Update translations * chore: :construction: Run eslint * chore: :construction: Fix ci * chore: :construction: Fix E2E tests * chore: :construction: Fix E2E tests * chore: :construction: Fix E2E tests * chore: :construction: Fix ci (2) * chore: :construction: Simplify using scrollable views * chore: :construction: Fix tests * chore: :construction: Simplify checking if an env setting is enabled --------- Co-authored-by: Yannick Bruintjes --- .env.example | 1 + .github/prepare-action/action.yml | 1 + App.tsx | 2 +- __tests__/components/wtr/Themes.test.tsx | 17 --- cypress/e2e/firstTimeUser.cy.ts | 4 +- cypress/e2e/home.cy.ts | 10 +- cypress/e2e/settings.cy.ts | 6 + cypress/e2e/wtr.cy.ts | 6 +- src/assets/fonts/{ => Inter}/Inter-Black.ttf | Bin src/assets/fonts/{ => Inter}/Inter-Bold.ttf | Bin .../fonts/{ => Inter}/Inter-ExtraBold.ttf | Bin .../fonts/{ => Inter}/Inter-ExtraLight.ttf | Bin src/assets/fonts/{ => Inter}/Inter-Light.ttf | Bin src/assets/fonts/{ => Inter}/Inter-Medium.ttf | Bin .../fonts/{ => Inter}/Inter-Regular.ttf | Bin .../fonts/{ => Inter}/Inter-SemiBold.ttf | Bin src/assets/fonts/{ => Inter}/Inter-Thin.ttf | Bin src/assets/fonts/Nunito/Nunito-Bold.ttf | Bin 0 -> 132152 bytes src/assets/fonts/Nunito/Nunito-Regular.ttf | Bin 0 -> 132204 bytes src/assets/fonts/OpenSans/OpenSans-Bold.ttf | Bin 0 -> 130864 bytes .../fonts/OpenSans/OpenSans-BoldItalic.ttf | Bin 0 -> 136412 bytes .../fonts/OpenSans/OpenSans-ExtraBold.ttf | Bin 0 -> 131248 bytes .../OpenSans/OpenSans-ExtraBoldItalic.ttf | Bin 0 -> 136980 bytes src/assets/fonts/OpenSans/OpenSans-Italic.ttf | Bin 0 -> 136656 bytes src/assets/fonts/OpenSans/OpenSans-Light.ttf | Bin 0 -> 130808 bytes .../fonts/OpenSans/OpenSans-LightItalic.ttf | Bin 0 -> 136948 bytes src/assets/fonts/OpenSans/OpenSans-Medium.ttf | Bin 0 -> 130980 bytes .../fonts/OpenSans/OpenSans-MediumItalic.ttf | Bin 0 -> 136848 bytes .../fonts/OpenSans/OpenSans-Regular.ttf | Bin 0 -> 130836 bytes .../fonts/OpenSans/OpenSans-SemiBold.ttf | Bin 0 -> 130764 bytes .../OpenSans/OpenSans-SemiBoldItalic.ttf | Bin 0 -> 136776 bytes src/components/WTR/Card/ThemeItemCard.tsx | 121 ++++++++++++++++ src/components/WTR/TechProviderItems.ts | 75 ++++++++++ src/components/WTR/TechProviders.tsx | 50 +------ src/components/WTR/Theme.tsx | 134 ------------------ src/components/WTR/ThemeItems.ts | 106 ++++++++++++++ src/components/WTR/Themes.tsx | 64 +++++++++ src/components/course/stages/AIBlock.tsx | 4 +- .../general/buttons/ReadMoreButton.tsx | 62 ++++++++ .../general/buttons/SeeAllButton.tsx | 9 +- .../general/error/ErrorBoundary.tsx | 4 +- .../general/views/PageScrollView.tsx | 6 +- src/lib/constants/Colors.ts | 105 +++++++++++++- src/lib/constants/Fonts.ts | 51 +++++-- src/lib/translations/languages/de.json | 12 +- src/lib/translations/languages/nl.json | 12 +- src/lib/utility/env/env.ts | 6 + src/lib/utility/env/env.values.ts | 4 + src/lib/utility/errorHandler.ts | 4 +- src/{screens => providers}/AppBehavior.tsx | 0 src/{screens => providers}/AppProviders.tsx | 0 src/routes/index.tsx | 4 +- src/screens/Home.tsx | 15 +- src/screens/{Settings => }/Settings.tsx | 18 +-- src/screens/WTR.tsx | 26 ++++ src/screens/WTR/WTR.tsx | 29 ---- 56 files changed, 679 insertions(+), 289 deletions(-) delete mode 100644 __tests__/components/wtr/Themes.test.tsx rename src/assets/fonts/{ => Inter}/Inter-Black.ttf (100%) rename src/assets/fonts/{ => Inter}/Inter-Bold.ttf (100%) rename src/assets/fonts/{ => Inter}/Inter-ExtraBold.ttf (100%) rename src/assets/fonts/{ => Inter}/Inter-ExtraLight.ttf (100%) rename src/assets/fonts/{ => Inter}/Inter-Light.ttf (100%) rename src/assets/fonts/{ => Inter}/Inter-Medium.ttf (100%) rename src/assets/fonts/{ => Inter}/Inter-Regular.ttf (100%) rename src/assets/fonts/{ => Inter}/Inter-SemiBold.ttf (100%) rename src/assets/fonts/{ => Inter}/Inter-Thin.ttf (100%) create mode 100644 src/assets/fonts/Nunito/Nunito-Bold.ttf create mode 100644 src/assets/fonts/Nunito/Nunito-Regular.ttf create mode 100644 src/assets/fonts/OpenSans/OpenSans-Bold.ttf create mode 100644 src/assets/fonts/OpenSans/OpenSans-BoldItalic.ttf create mode 100644 src/assets/fonts/OpenSans/OpenSans-ExtraBold.ttf create mode 100644 src/assets/fonts/OpenSans/OpenSans-ExtraBoldItalic.ttf create mode 100644 src/assets/fonts/OpenSans/OpenSans-Italic.ttf create mode 100644 src/assets/fonts/OpenSans/OpenSans-Light.ttf create mode 100644 src/assets/fonts/OpenSans/OpenSans-LightItalic.ttf create mode 100644 src/assets/fonts/OpenSans/OpenSans-Medium.ttf create mode 100644 src/assets/fonts/OpenSans/OpenSans-MediumItalic.ttf create mode 100644 src/assets/fonts/OpenSans/OpenSans-Regular.ttf create mode 100644 src/assets/fonts/OpenSans/OpenSans-SemiBold.ttf create mode 100644 src/assets/fonts/OpenSans/OpenSans-SemiBoldItalic.ttf create mode 100644 src/components/WTR/Card/ThemeItemCard.tsx create mode 100644 src/components/WTR/TechProviderItems.ts delete mode 100644 src/components/WTR/Theme.tsx create mode 100644 src/components/WTR/ThemeItems.ts create mode 100644 src/components/WTR/Themes.tsx create mode 100644 src/components/general/buttons/ReadMoreButton.tsx rename src/{screens => providers}/AppBehavior.tsx (100%) rename src/{screens => providers}/AppProviders.tsx (100%) rename src/screens/{Settings => }/Settings.tsx (67%) create mode 100644 src/screens/WTR.tsx delete mode 100644 src/screens/WTR/WTR.tsx diff --git a/.env.example b/.env.example index 758a636f..33bb6c37 100644 --- a/.env.example +++ b/.env.example @@ -5,3 +5,4 @@ WP_CONTENT_URL="https://www.windesheim.tech" WP_DATA_URL="https://www.windesheim.ai" WP_USERNAME= WP_PASSWORD= +USE_EXPERIMENTAL_COLORS= \ No newline at end of file diff --git a/.github/prepare-action/action.yml b/.github/prepare-action/action.yml index 7b22c390..46f08eff 100644 --- a/.github/prepare-action/action.yml +++ b/.github/prepare-action/action.yml @@ -38,4 +38,5 @@ runs: echo WP_DATA_URL="https://www.windesheim.ai" >> .env echo WP_USERNAME=${{ inputs.wp-username }} >> .env echo WP_PASSWORD=${{ inputs.wp-password }} >> .env + echo USE_EXPERIMENTAL_COLORS="false" >> .env cat .env diff --git a/App.tsx b/App.tsx index 00f83842..0b0fd777 100644 --- a/App.tsx +++ b/App.tsx @@ -8,8 +8,8 @@ import ErrorFallback from './src/components/general/error/ErrorBoundary'; import AppLoader from './src/components/loadingscreen/AppLoader'; import SplashScreenOrApp from './src/components/splashscreen/SplashScreenOrApp'; import { store } from './src/lib/redux/Store'; +import AppProviders from './src/providers/AppProviders'; import { RouteLinking } from './src/routes/routeLinking'; -import AppProviders from './src/screens/AppProviders'; export default function App() { return ( diff --git a/__tests__/components/wtr/Themes.test.tsx b/__tests__/components/wtr/Themes.test.tsx deleted file mode 100644 index e7a5a797..00000000 --- a/__tests__/components/wtr/Themes.test.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { render } from '@testing-library/react-native'; -import React from 'react'; - -import { themeItems, Themes } from '../../../src/components/WTR/Theme'; - -test('renders Themes component without crashing', () => { - render(); -}); - -test('displays all themes', () => { - const { getByText } = render(); - - themeItems.forEach((theme) => { - const themeName = getByText(theme.name); - expect(themeName).toBeTruthy(); - }); -}); diff --git a/cypress/e2e/firstTimeUser.cy.ts b/cypress/e2e/firstTimeUser.cy.ts index db162bdb..6fe716cc 100644 --- a/cypress/e2e/firstTimeUser.cy.ts +++ b/cypress/e2e/firstTimeUser.cy.ts @@ -18,7 +18,7 @@ describe('First time user tests', () => { cy.contains('Home'); cy.contains('Handige prompts'); - cy.contains('Tech Providers'); + cy.contains("Thema's"); }); it('can answer the background questions and progresses through it', () => { @@ -33,6 +33,6 @@ describe('First time user tests', () => { cy.contains('Overslaan').click(); cy.contains('Home'); cy.contains('Handige prompts'); - cy.contains('Tech Providers'); + cy.contains("Thema's"); }); }); diff --git a/cypress/e2e/home.cy.ts b/cypress/e2e/home.cy.ts index 250c2c11..64fb2a73 100644 --- a/cypress/e2e/home.cy.ts +++ b/cypress/e2e/home.cy.ts @@ -14,9 +14,13 @@ describe('Home page tests', () => { cy.contains('Home'); cy.contains('Useful Prompts'); - cy.contains('Tech Providers'); - //there should be 5 tech providers - cy.get('[data-testid="tech-provider-text"]').should('have.length', 5); + cy.contains('Themes'); + cy.contains('See All'); + + // There should be 3 themes. + cy.get('[data-testid="theme-card"]').should('have.length', 3); + + // There should be 3 prompts. cy.get('[data-testid="prompt-card"]').should('have.length', 3); }); diff --git a/cypress/e2e/settings.cy.ts b/cypress/e2e/settings.cy.ts index 42784b81..f7b1debf 100644 --- a/cypress/e2e/settings.cy.ts +++ b/cypress/e2e/settings.cy.ts @@ -1,3 +1,9 @@ +// Disable uncaught exception handling. +Cypress.on('uncaught:exception', () => { + // Returning false here prevents Cypress from failing the test. + return false; +}); + describe('App settings test', () => { beforeEach(() => { cy.visit('/'); diff --git a/cypress/e2e/wtr.cy.ts b/cypress/e2e/wtr.cy.ts index 91a35c6d..db4314a2 100644 --- a/cypress/e2e/wtr.cy.ts +++ b/cypress/e2e/wtr.cy.ts @@ -33,12 +33,12 @@ describe('WTR page tests', () => { cy.contains('Artificial Intelligence'); cy.contains('Next UI'); cy.contains('Green IT'); - cy.contains('Transaction to interaction'); + cy.contains('Transaction to Interaction'); cy.contains('Future of Work'); cy.contains('Cloud Everywhere'); - cy.contains('Future of programming'); + cy.contains('Future of Programming'); cy.contains('Building Trust'); - cy.contains('Quantum computing'); + cy.contains('Quantum Computing'); }); it('can view the tech provider Apple', () => { diff --git a/src/assets/fonts/Inter-Black.ttf b/src/assets/fonts/Inter/Inter-Black.ttf similarity index 100% rename from src/assets/fonts/Inter-Black.ttf rename to src/assets/fonts/Inter/Inter-Black.ttf diff --git a/src/assets/fonts/Inter-Bold.ttf b/src/assets/fonts/Inter/Inter-Bold.ttf similarity index 100% rename from src/assets/fonts/Inter-Bold.ttf rename to src/assets/fonts/Inter/Inter-Bold.ttf diff --git a/src/assets/fonts/Inter-ExtraBold.ttf b/src/assets/fonts/Inter/Inter-ExtraBold.ttf similarity index 100% rename from src/assets/fonts/Inter-ExtraBold.ttf rename to src/assets/fonts/Inter/Inter-ExtraBold.ttf diff --git a/src/assets/fonts/Inter-ExtraLight.ttf b/src/assets/fonts/Inter/Inter-ExtraLight.ttf similarity index 100% rename from src/assets/fonts/Inter-ExtraLight.ttf rename to src/assets/fonts/Inter/Inter-ExtraLight.ttf diff --git a/src/assets/fonts/Inter-Light.ttf b/src/assets/fonts/Inter/Inter-Light.ttf similarity index 100% rename from src/assets/fonts/Inter-Light.ttf rename to src/assets/fonts/Inter/Inter-Light.ttf diff --git a/src/assets/fonts/Inter-Medium.ttf b/src/assets/fonts/Inter/Inter-Medium.ttf similarity index 100% rename from src/assets/fonts/Inter-Medium.ttf rename to src/assets/fonts/Inter/Inter-Medium.ttf diff --git a/src/assets/fonts/Inter-Regular.ttf b/src/assets/fonts/Inter/Inter-Regular.ttf similarity index 100% rename from src/assets/fonts/Inter-Regular.ttf rename to src/assets/fonts/Inter/Inter-Regular.ttf diff --git a/src/assets/fonts/Inter-SemiBold.ttf b/src/assets/fonts/Inter/Inter-SemiBold.ttf similarity index 100% rename from src/assets/fonts/Inter-SemiBold.ttf rename to src/assets/fonts/Inter/Inter-SemiBold.ttf diff --git a/src/assets/fonts/Inter-Thin.ttf b/src/assets/fonts/Inter/Inter-Thin.ttf similarity index 100% rename from src/assets/fonts/Inter-Thin.ttf rename to src/assets/fonts/Inter/Inter-Thin.ttf diff --git a/src/assets/fonts/Nunito/Nunito-Bold.ttf b/src/assets/fonts/Nunito/Nunito-Bold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..886134dcfa3c784be09217fe57bf3aac9f059bf2 GIT binary patch literal 132152 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