From a85ab8da892c5dce25f3adc84dbdd29cbfbe9e83 Mon Sep 17 00:00:00 2001
From: Hampus Hallkvist
Date: Thu, 22 Feb 2024 17:03:02 +0100
Subject: [PATCH] feat: Add timeline
---
apps/dashboard/package.json | 2 +-
apps/dashboard/pnpm-lock.yaml | 56 +++---
apps/dashboard/src/components/ui/sonner.tsx | 2 +
.../src/screens/dashboard/DashboardError.tsx | 20 +-
.../src/screens/dashboard/screen.tsx | 173 +++++++++++-------
apps/dashboard/src/shared/Timeline.tsx | 61 ++++++
6 files changed, 214 insertions(+), 100 deletions(-)
create mode 100644 apps/dashboard/src/shared/Timeline.tsx
diff --git a/apps/dashboard/package.json b/apps/dashboard/package.json
index a178fcb82..85c6edba5 100644
--- a/apps/dashboard/package.json
+++ b/apps/dashboard/package.json
@@ -56,7 +56,7 @@
"eslint-plugin-react-refresh": "^0.4.3",
"postcss": "^8.4.27",
"tailwindcss": "^3.3.3",
- "typescript": "^5.0.2",
+ "typescript": "5.4.0-beta",
"vite": "^4.4.5"
}
}
diff --git a/apps/dashboard/pnpm-lock.yaml b/apps/dashboard/pnpm-lock.yaml
index 8f1320373..e3d9a8782 100644
--- a/apps/dashboard/pnpm-lock.yaml
+++ b/apps/dashboard/pnpm-lock.yaml
@@ -108,10 +108,10 @@ devDependencies:
version: 18.2.7
'@typescript-eslint/eslint-plugin':
specifier: ^6.0.0
- version: 6.0.0(@typescript-eslint/parser@6.0.0)(eslint@8.45.0)(typescript@5.0.2)
+ version: 6.0.0(@typescript-eslint/parser@6.0.0)(eslint@8.45.0)(typescript@5.4.0-beta)
'@typescript-eslint/parser':
specifier: ^6.0.0
- version: 6.0.0(eslint@8.45.0)(typescript@5.0.2)
+ version: 6.0.0(eslint@8.45.0)(typescript@5.4.0-beta)
'@vitejs/plugin-react':
specifier: ^4.0.3
version: 4.0.3(vite@4.4.5)
@@ -134,8 +134,8 @@ devDependencies:
specifier: ^3.3.3
version: 3.3.3
typescript:
- specifier: ^5.0.2
- version: 5.0.2
+ specifier: 5.4.0-beta
+ version: 5.4.0-beta
vite:
specifier: ^4.4.5
version: 4.4.5(@types/node@20.11.19)
@@ -1488,7 +1488,7 @@ packages:
resolution: {integrity: sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==}
dev: false
- /@typescript-eslint/eslint-plugin@6.0.0(@typescript-eslint/parser@6.0.0)(eslint@8.45.0)(typescript@5.0.2):
+ /@typescript-eslint/eslint-plugin@6.0.0(@typescript-eslint/parser@6.0.0)(eslint@8.45.0)(typescript@5.4.0-beta):
resolution: {integrity: sha512-xuv6ghKGoiq856Bww/yVYnXGsKa588kY3M0XK7uUW/3fJNNULKRfZfSBkMTSpqGG/8ZCXCadfh8G/z/B4aqS/A==}
engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies:
@@ -1500,10 +1500,10 @@ packages:
optional: true
dependencies:
'@eslint-community/regexpp': 4.6.2
- '@typescript-eslint/parser': 6.0.0(eslint@8.45.0)(typescript@5.0.2)
+ '@typescript-eslint/parser': 6.0.0(eslint@8.45.0)(typescript@5.4.0-beta)
'@typescript-eslint/scope-manager': 6.0.0
- '@typescript-eslint/type-utils': 6.0.0(eslint@8.45.0)(typescript@5.0.2)
- '@typescript-eslint/utils': 6.0.0(eslint@8.45.0)(typescript@5.0.2)
+ '@typescript-eslint/type-utils': 6.0.0(eslint@8.45.0)(typescript@5.4.0-beta)
+ '@typescript-eslint/utils': 6.0.0(eslint@8.45.0)(typescript@5.4.0-beta)
'@typescript-eslint/visitor-keys': 6.0.0
debug: 4.3.4
eslint: 8.45.0
@@ -1513,13 +1513,13 @@ packages:
natural-compare: 1.4.0
natural-compare-lite: 1.4.0
semver: 7.5.4
- ts-api-utils: 1.0.1(typescript@5.0.2)
- typescript: 5.0.2
+ ts-api-utils: 1.0.1(typescript@5.4.0-beta)
+ typescript: 5.4.0-beta
transitivePeerDependencies:
- supports-color
dev: true
- /@typescript-eslint/parser@6.0.0(eslint@8.45.0)(typescript@5.0.2):
+ /@typescript-eslint/parser@6.0.0(eslint@8.45.0)(typescript@5.4.0-beta):
resolution: {integrity: sha512-TNaufYSPrr1U8n+3xN+Yp9g31vQDJqhXzzPSHfQDLcaO4tU+mCfODPxCwf4H530zo7aUBE3QIdxCXamEnG04Tg==}
engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies:
@@ -1531,11 +1531,11 @@ packages:
dependencies:
'@typescript-eslint/scope-manager': 6.0.0
'@typescript-eslint/types': 6.0.0
- '@typescript-eslint/typescript-estree': 6.0.0(typescript@5.0.2)
+ '@typescript-eslint/typescript-estree': 6.0.0(typescript@5.4.0-beta)
'@typescript-eslint/visitor-keys': 6.0.0
debug: 4.3.4
eslint: 8.45.0
- typescript: 5.0.2
+ typescript: 5.4.0-beta
transitivePeerDependencies:
- supports-color
dev: true
@@ -1548,7 +1548,7 @@ packages:
'@typescript-eslint/visitor-keys': 6.0.0
dev: true
- /@typescript-eslint/type-utils@6.0.0(eslint@8.45.0)(typescript@5.0.2):
+ /@typescript-eslint/type-utils@6.0.0(eslint@8.45.0)(typescript@5.4.0-beta):
resolution: {integrity: sha512-ah6LJvLgkoZ/pyJ9GAdFkzeuMZ8goV6BH7eC9FPmojrnX9yNCIsfjB+zYcnex28YO3RFvBkV6rMV6WpIqkPvoQ==}
engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies:
@@ -1558,12 +1558,12 @@ packages:
typescript:
optional: true
dependencies:
- '@typescript-eslint/typescript-estree': 6.0.0(typescript@5.0.2)
- '@typescript-eslint/utils': 6.0.0(eslint@8.45.0)(typescript@5.0.2)
+ '@typescript-eslint/typescript-estree': 6.0.0(typescript@5.4.0-beta)
+ '@typescript-eslint/utils': 6.0.0(eslint@8.45.0)(typescript@5.4.0-beta)
debug: 4.3.4
eslint: 8.45.0
- ts-api-utils: 1.0.1(typescript@5.0.2)
- typescript: 5.0.2
+ ts-api-utils: 1.0.1(typescript@5.4.0-beta)
+ typescript: 5.4.0-beta
transitivePeerDependencies:
- supports-color
dev: true
@@ -1573,7 +1573,7 @@ packages:
engines: {node: ^16.0.0 || >=18.0.0}
dev: true
- /@typescript-eslint/typescript-estree@6.0.0(typescript@5.0.2):
+ /@typescript-eslint/typescript-estree@6.0.0(typescript@5.4.0-beta):
resolution: {integrity: sha512-2zq4O7P6YCQADfmJ5OTDQTP3ktajnXIRrYAtHM9ofto/CJZV3QfJ89GEaM2BNGeSr1KgmBuLhEkz5FBkS2RQhQ==}
engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies:
@@ -1588,13 +1588,13 @@ packages:
globby: 11.1.0
is-glob: 4.0.3
semver: 7.5.4
- ts-api-utils: 1.0.1(typescript@5.0.2)
- typescript: 5.0.2
+ ts-api-utils: 1.0.1(typescript@5.4.0-beta)
+ typescript: 5.4.0-beta
transitivePeerDependencies:
- supports-color
dev: true
- /@typescript-eslint/utils@6.0.0(eslint@8.45.0)(typescript@5.0.2):
+ /@typescript-eslint/utils@6.0.0(eslint@8.45.0)(typescript@5.4.0-beta):
resolution: {integrity: sha512-SOr6l4NB6HE4H/ktz0JVVWNXqCJTOo/mHnvIte1ZhBQ0Cvd04x5uKZa3zT6tiodL06zf5xxdK8COiDvPnQ27JQ==}
engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies:
@@ -1605,7 +1605,7 @@ packages:
'@types/semver': 7.5.0
'@typescript-eslint/scope-manager': 6.0.0
'@typescript-eslint/types': 6.0.0
- '@typescript-eslint/typescript-estree': 6.0.0(typescript@5.0.2)
+ '@typescript-eslint/typescript-estree': 6.0.0(typescript@5.4.0-beta)
eslint: 8.45.0
eslint-scope: 5.1.1
semver: 7.5.4
@@ -3170,13 +3170,13 @@ packages:
dependencies:
is-number: 7.0.0
- /ts-api-utils@1.0.1(typescript@5.0.2):
+ /ts-api-utils@1.0.1(typescript@5.4.0-beta):
resolution: {integrity: sha512-lC/RGlPmwdrIBFTX59wwNzqh7aR2otPNPR/5brHZm/XKFYKsfqxihXUe9pU3JI+3vGkl+vyCoNNnPhJn3aLK1A==}
engines: {node: '>=16.13.0'}
peerDependencies:
typescript: '>=4.2.0'
dependencies:
- typescript: 5.0.2
+ typescript: 5.4.0-beta
dev: true
/ts-interface-checker@0.1.13:
@@ -3198,9 +3198,9 @@ packages:
engines: {node: '>=10'}
dev: true
- /typescript@5.0.2:
- resolution: {integrity: sha512-wVORMBGO/FAs/++blGNeAVdbNKtIh1rbBL2EyQ1+J9lClJ93KiiKe8PmFIVdXhHcyv44SL9oglmfeSsndo0jRw==}
- engines: {node: '>=12.20'}
+ /typescript@5.4.0-beta:
+ resolution: {integrity: sha512-KgekV5JS7TQ7Bb8eO64QGxdM7MSBUUXOXq28OWX23d2MA8SiVtNYoo4s33tCTEGV8+6AGBRD2+KiXNNnexRRYw==}
+ engines: {node: '>=14.17'}
hasBin: true
dev: true
diff --git a/apps/dashboard/src/components/ui/sonner.tsx b/apps/dashboard/src/components/ui/sonner.tsx
index 31e21328c..a2e447150 100644
--- a/apps/dashboard/src/components/ui/sonner.tsx
+++ b/apps/dashboard/src/components/ui/sonner.tsx
@@ -11,6 +11,8 @@ const Toaster = ({ ...props }: ToasterProps) => {
theme={theme as ToasterProps["theme"]}
className="toaster group"
toastOptions={{
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore
classNames: {
toast:
"group toast group-[.toaster]:bg-white group-[.toaster]:text-stone-950 group-[.toaster]:border-stone-200 group-[.toaster]:shadow-lg dark:group-[.toaster]:bg-stone-950 dark:group-[.toaster]:text-stone-50 dark:group-[.toaster]:border-stone-800",
diff --git a/apps/dashboard/src/screens/dashboard/DashboardError.tsx b/apps/dashboard/src/screens/dashboard/DashboardError.tsx
index d62011571..7dbe18c5c 100644
--- a/apps/dashboard/src/screens/dashboard/DashboardError.tsx
+++ b/apps/dashboard/src/screens/dashboard/DashboardError.tsx
@@ -1,7 +1,7 @@
import { useSelector } from "react-redux"
-import { selectErrors } from "../../store/form/form_selectors"
import { PrimaryFormHeader } from "../../forms/primary/Header"
import { LogoutButton } from "../../shared/LogoutButton"
+import { selectErrors } from "../../store/form/form_selectors"
const ERRORS = {
not_authorized: (
@@ -12,18 +12,20 @@ const ERRORS = {
),
- user_did_not_sign_ir: (
-
- You have not completed Initial Registration.
-
- ),
+ user_did_not_sign_ir: You have not completed Initial Registration.
,
user_is_not_exhibitor: (
- You did not get picked for the fair this year.
+ Unfortunetly we are at full captity as of right now, we might get
+ space for more exhibitors later and will contact you then.
),
user_has_no_company: You are not associated with any company
,
- cr_not_open: We are working on this years final registration page, please come back later!
+ cr_not_open: (
+
+ We are working on this years final registration page, please come
+ back later!
+
+ )
}
export function DashboardError() {
@@ -35,7 +37,7 @@ export function DashboardError() {
Oups, something went wrong
-
{ERRORS[error]}
+
{ERRORS[error]}
)
diff --git a/apps/dashboard/src/screens/dashboard/screen.tsx b/apps/dashboard/src/screens/dashboard/screen.tsx
index 8258a88a9..6101756f6 100644
--- a/apps/dashboard/src/screens/dashboard/screen.tsx
+++ b/apps/dashboard/src/screens/dashboard/screen.tsx
@@ -9,6 +9,7 @@ import { isFormOpen, isFormVisible } from "@/forms/form_access"
import { ContactBubble } from "@/screens/dashboard/ContactBubble"
import { getTimelinePhaseMessage } from "@/screens/dashboard/timeline_steps"
import { LogoutButton } from "@/shared/LogoutButton"
+import { Timeline } from "@/shared/Timeline"
import { useRegistration } from "@/shared/hooks/useRegistration"
import { selectForms } from "@/store/form/form_selectors"
import { cx } from "@/utils/cx"
@@ -44,54 +45,50 @@ export function DashboardScreen() {
)
return (
-
-
{/* SIDEBAR */}
-
-
-
-
-
- {data.company.name}
-
-
- {data.contact?.first_name != null && (
-
-
-
- Welcome {data.contact.first_name}!
-
-
- From this dashboard you will be able to
- configure your Armada experience. You will
- be able to provide information, buy products
- and read about our procedures
-
-
-
- )}
- {getTimelinePhaseMessage(data.type) != null && (
-
-
-
-
- {getTimelinePhaseMessage(data.type)
- ?.title ?? (
-
- Current step:{" "}
- {data.type.split("_").join(" ")}
-
- )}
-
-
-
- {
- getTimelinePhaseMessage(data.type)
- ?.description
- }
-
-
- )}
- {/*
+
+
+
{/* SIDEBAR */}
+
+
+ {data.contact?.first_name != null && (
+
+
+
+ Welcome {data.contact.first_name}
+ !
+
+
+ From this dashboard you will be able to
+ configure your Armada experience. You
+ will be able to provide information, buy
+ products and read about our procedures
+
+
+
+ )}
+ {getTimelinePhaseMessage(data.type) != null && (
+
+
+
+
+ {getTimelinePhaseMessage(data.type)
+ ?.title ?? (
+
+ Current step:{" "}
+ {data.type.split("_").join(" ")}
+
+ )}
+
+
+
+ {
+ getTimelinePhaseMessage(data.type)
+ ?.description
+ }
+
+
+ )}
+ {/*
{companyProgress < 1
? "Company Progress"
@@ -105,24 +102,76 @@ export function DashboardScreen() {
)}
*/}
-
- {formCardsData.map(([key, formMeta]) => (
-
- ))}
+
+ {formCardsData.map(([key, formMeta]) => (
+
+ ))}
+
+
+
+
-
-
-
{/* Spacer */}
+
+
{companyContact != null && (
-
+
)}
diff --git a/apps/dashboard/src/shared/Timeline.tsx b/apps/dashboard/src/shared/Timeline.tsx
new file mode 100644
index 000000000..6420e0be9
--- /dev/null
+++ b/apps/dashboard/src/shared/Timeline.tsx
@@ -0,0 +1,61 @@
+import { Badge } from "@/components/ui/badge"
+import { RegistrationStatus } from "@/store/company/company_slice"
+import { cx } from "@/utils/cx"
+
+export interface TimelineStage {
+ id: RegistrationStatus | RegistrationStatus[]
+ title: string
+ badgeText?: string
+}
+
+export function Timeline(
+ props: {
+ stages: TimelineStage[]
+ current: RegistrationStatus
+ } & React.HTMLProps
+) {
+ const { stages, current, className, ...rest } = props
+
+ const currentIndex = stages.findIndex(stage =>
+ Array.isArray(stage.id)
+ ? stage.id.includes(current)
+ : stage.id === current
+ )
+ const currentPercentage = currentIndex / (stages.length - 1)
+
+ return (
+
+
+
+ {stages.map((stage, index) => (
+
+
currentIndex
+ }
+ )}
+ >
+ {stage.badgeText != null && (
+
+ {stage.badgeText}
+
+ )}
+
+ {stage.title}
+
+
+ ))}
+
+
+ )
+}