From de6099e923d022bf9b19a6524877a2389f51da24 Mon Sep 17 00:00:00 2001 From: Davide Bizzi Date: Wed, 15 Oct 2025 16:11:59 +0200 Subject: [PATCH 01/37] feat: update manual links and improve layout in translation and preview components --- src/locales/es/translation.json | 2 +- src/locales/fr/translation.json | 2 +- src/locales/it/translation.json | 2 +- src/pages/Manual/ManualContent.tsx | 52 +++++++++++-------- .../Preview/SelectionBox/AlreadySelected.tsx | 36 +++++++++---- src/pages/Preview/index.tsx | 4 +- 6 files changed, 61 insertions(+), 37 deletions(-) diff --git a/src/locales/es/translation.json b/src/locales/es/translation.json index bd043840..e6c67456 100644 --- a/src/locales/es/translation.json +++ b/src/locales/es/translation.json @@ -713,7 +713,7 @@ "PAYMENTS_MODAL_AUTOMATIC_STEP_1_RECAP": "Siguiente paso\n" }, "available tags: ": { - "_FORM_MESSAGES_ALREADY-SELECTED_": "Ir al Manual! Allí encontrarás toda la información que necesitas para completar las tareas." + "_FORM_MESSAGES_ALREADY-SELECTED_": "En el Manual encontrarás toda la información que necesitas para completar las tareas.¡Ve al Manual!" }, "available tags: , ": { "LOGIN_SIGNUP_LINK": "¿Primera vez aquí? Regístrate" diff --git a/src/locales/fr/translation.json b/src/locales/fr/translation.json index bbbd9cff..b44b5483 100644 --- a/src/locales/fr/translation.json +++ b/src/locales/fr/translation.json @@ -713,7 +713,7 @@ "PAYMENTS_MODAL_AUTOMATIC_STEP_1_RECAP": "Ce que vous devez faire maintenant\n
    \n
  • Choisissez le mode de paiement et vérifiez que votre type fiscal est correct
  • \n
  • Insérez vos informations personnelles et acceptez les conditions
  • \n
  • Envoyez votre demande de paiement
  • \n
" }, "available tags: ": { - "_FORM_MESSAGES_ALREADY-SELECTED_": "Consultez le Manuel ! Vous y trouverez toutes les informations nécessaires pour compléter les tâches." + "_FORM_MESSAGES_ALREADY-SELECTED_": "Dans le manuel, vous trouverez toutes les informations dont vous avez besoin pour accomplir les tâches.Allez au Manuel !" }, "available tags: , ": { "LOGIN_SIGNUP_LINK": "Nouveau sur TRYBER ? Inscrivez-vous" diff --git a/src/locales/it/translation.json b/src/locales/it/translation.json index b40fc6b3..e183c5fe 100644 --- a/src/locales/it/translation.json +++ b/src/locales/it/translation.json @@ -713,7 +713,7 @@ "PAYMENTS_MODAL_AUTOMATIC_STEP_1_RECAP": "Cosa farai ora\n
    \n
  • Scegli il metodo di pagamento e controlla che il tuo regime fiscale sia corretto
  • \n
  • Inserisci i dati richiesti e accetta le condizioni di pagamento
  • \n
  • Invia la richiesta
  • \n
" }, "available tags: ": { - "_FORM_MESSAGES_ALREADY-SELECTED_": "Vai al Manuale! Lì troverai tutte le informazioni di cui hai bisogno per completare i compiti." + "_FORM_MESSAGES_ALREADY-SELECTED_": "Nel manuale troverai tutte le informazioni di cui hai bisogno per completare i compiti.Vai al Manuale!" }, "available tags: , ": { "LOGIN_SIGNUP_LINK": "Prima volta su TRYBER? Registrati" diff --git a/src/pages/Manual/ManualContent.tsx b/src/pages/Manual/ManualContent.tsx index a110539d..9afdbcf3 100644 --- a/src/pages/Manual/ManualContent.tsx +++ b/src/pages/Manual/ManualContent.tsx @@ -1,4 +1,10 @@ -import { BSCol, BSGrid, Tab, Tabs } from "@appquality/appquality-design-system"; +import { + BSCol, + BSGrid, + Card, + Tab, + Tabs, +} from "@appquality/appquality-design-system"; import { useTranslation } from "react-i18next"; import { useGetUsersMeCampaignsByCampaignIdPreviewQuery, @@ -33,26 +39,30 @@ const ManualContent = ({ id }: { id: string }) => { <> - - -
- -
-
- {tasks && tasks.length > 0 && ( - -
- -
-
- )} -
+ +
+ + +
+ +
+
+ {tasks && tasks.length > 0 && ( + +
+ +
+
+ )} +
+
+
diff --git a/src/pages/Preview/SelectionBox/AlreadySelected.tsx b/src/pages/Preview/SelectionBox/AlreadySelected.tsx index a7552008..ad77e02e 100644 --- a/src/pages/Preview/SelectionBox/AlreadySelected.tsx +++ b/src/pages/Preview/SelectionBox/AlreadySelected.tsx @@ -1,7 +1,29 @@ -import { Text, Toastr } from "@appquality/appquality-design-system"; +import { Button, Text, Toastr } from "@appquality/appquality-design-system"; import { Trans, useTranslation } from "react-i18next"; import { Link } from "react-router-dom"; +const ManualLink = ({ + manualRoute, + children, +}: { + manualRoute: string; + children?: React.ReactNode; +}) => { + return ( + + ); +}; + const AlreadySelected = ({ manualRoute }: { manualRoute: string }) => { const { t } = useTranslation(); return ( @@ -15,18 +37,10 @@ const AlreadySelected = ({ manualRoute }: { manualRoute: string }) => { i18nKey="available tags: :::_FORM_MESSAGES_ALREADY-SELECTED_" components={{ strong: , - manualLink: ( - - ), + manualLink: , }} defaults={ - "Go to the Manual! There you will find all the information you need to complete the tasks." + "In the Manual you will find all the information you need to complete the tasks.Go to the Manual!" } />

diff --git a/src/pages/Preview/index.tsx b/src/pages/Preview/index.tsx index f2bd2fd7..69657596 100644 --- a/src/pages/Preview/index.tsx +++ b/src/pages/Preview/index.tsx @@ -50,7 +50,7 @@ const Preview = () => { -
+ { > {data.content} -
+
From 360549e31ee5f6d7315f65aac612c862d038e332 Mon Sep 17 00:00:00 2001 From: Davide Bizzi Date: Wed, 15 Oct 2025 16:14:08 +0200 Subject: [PATCH 02/37] feat: refactor BugTypeDescription to conditionally display Bug Parade message --- .../BugTypeDescription/Component/index.tsx | 11 +------- .../Component/useDescription.tsx | 27 +++++++++++++++---- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/pages/Preview/Editor/extensions/SlashCommands/nodes/BugTypeDescription/Component/index.tsx b/src/pages/Preview/Editor/extensions/SlashCommands/nodes/BugTypeDescription/Component/index.tsx index 295c19f0..57564b0e 100644 --- a/src/pages/Preview/Editor/extensions/SlashCommands/nodes/BugTypeDescription/Component/index.tsx +++ b/src/pages/Preview/Editor/extensions/SlashCommands/nodes/BugTypeDescription/Component/index.tsx @@ -1,28 +1,19 @@ import { Text } from "@appquality/appquality-design-system"; import { NodeViewWrapper } from "@tiptap/react"; import { Node as PMNode } from "prosemirror-model"; +import { useTranslation } from "react-i18next"; import { useParams } from "react-router-dom"; import { useDescription } from "./useDescription"; -import { useGetUsersMeCampaignsByCampaignIdQuery } from "src/services/tryberApi"; -import { useTranslation } from "react-i18next"; export default function MyComponent({ node }: { node: PMNode }) { const { t } = useTranslation(); const { id } = useParams<{ id: string }>(); - const { data: campaign } = useGetUsersMeCampaignsByCampaignIdQuery({ - campaignId: id, - }); const description = useDescription(id!); return ( {description} - {campaign?.hasBugParade === 1 && ( - - {t("_PAGE_PREVIEW__BUG_PARADE_ACTIVE", "The Bug Parade is active")} - - )} ); } diff --git a/src/pages/Preview/Editor/extensions/SlashCommands/nodes/BugTypeDescription/Component/useDescription.tsx b/src/pages/Preview/Editor/extensions/SlashCommands/nodes/BugTypeDescription/Component/useDescription.tsx index 0f726bfc..9eb926f8 100644 --- a/src/pages/Preview/Editor/extensions/SlashCommands/nodes/BugTypeDescription/Component/useDescription.tsx +++ b/src/pages/Preview/Editor/extensions/SlashCommands/nodes/BugTypeDescription/Component/useDescription.tsx @@ -1,9 +1,18 @@ -import { Title } from "@appquality/appquality-design-system"; +import { Text, Title } from "@appquality/appquality-design-system"; import { ReactNode } from "react"; import { Trans, useTranslation } from "react-i18next"; -import { useGetUsersMeCampaignsByCampaignIdPreviewQuery } from "src/services/tryberApi"; +import { + useGetUsersMeCampaignsByCampaignIdPreviewQuery, + useGetUsersMeCampaignsByCampaignIdQuery, +} from "src/services/tryberApi"; -const MethodologyWrapper = ({ children }: { children: ReactNode }) => { +const MethodologyWrapper = ({ + children, + hasBugParade, +}: { + children: ReactNode; + hasBugParade?: boolean; +}) => { const { t } = useTranslation(); return (
@@ -11,6 +20,11 @@ const MethodologyWrapper = ({ children }: { children: ReactNode }) => { {t("__PREVIEW_METHODOLOGY_TITLE", "METHODOLOGY ")} {children} + {hasBugParade && ( + + {t("_PAGE_PREVIEW__BUG_PARADE_ACTIVE", "The Bug Parade is active")} + + )}
); }; @@ -20,6 +34,9 @@ export const useDescription = (id: string) => { { campaignId: id }, { skip: !id } ); + const { data: campaign } = useGetUsersMeCampaignsByCampaignIdQuery({ + campaignId: id, + }); const typeName = data?.type?.name; @@ -30,7 +47,7 @@ export const useDescription = (id: string) => { case "Explorative Testing": case "Bug verification": return ( - + { ); case "Usability Test": return ( - + Date: Mon, 20 Oct 2025 16:37:33 +0200 Subject: [PATCH 03/37] feat: add FileDropzonePage route to Page component --- src/Page.tsx | 5 +++++ src/locales/en/translation.json | 2 ++ src/locales/es/translation.json | 2 ++ src/locales/fr/translation.json | 2 ++ src/locales/it/translation.json | 2 ++ 5 files changed, 13 insertions(+) diff --git a/src/Page.tsx b/src/Page.tsx index 94524087..3f9553dd 100644 --- a/src/Page.tsx +++ b/src/Page.tsx @@ -26,6 +26,7 @@ import { import BugForm from "./pages/BugForm"; import Manual from "./pages/Manual"; import Preview from "./pages/Preview"; +import FileDropzonePage from "./pages/UsecaseMediaDropzone"; import SignupSuccess from "./pages/SignupSuccess"; import ThankYouPage from "./pages/ThankYou"; import VdpPage from "./pages/VDP"; @@ -219,6 +220,10 @@ function Page() { + diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index 5e60fbf4..368e8e36 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -545,6 +545,8 @@ "Try again.": "Try again.", "Type": "Type", "Type to search your city": "Type to search your city", + "USECASE_MEDIA_DROPZONE_MISSING_PARAMS": "Missing campaign or task information.", + "USECASE_MEDIA_DROPZONE_TITLE": "Uploading media", "Update your device list": "Update your device list", "Upload a minimum number of {{num}} files": { "BUGFORM_UPLOAD_TXT": "Upload at least {{num}} media", diff --git a/src/locales/es/translation.json b/src/locales/es/translation.json index e6c67456..599f5c65 100644 --- a/src/locales/es/translation.json +++ b/src/locales/es/translation.json @@ -545,6 +545,8 @@ "Try again.": "Inténtelo de nuevo.", "Type": "Tipo", "Type to search your city": "Escriba para buscar tu ciudad", + "USECASE_MEDIA_DROPZONE_MISSING_PARAMS": "Faltan información de campaña o tarea.", + "USECASE_MEDIA_DROPZONE_TITLE": "Subiendo medios", "Update your device list": "Actualizar tu lista de dispositivos", "Upload a minimum number of {{num}} files": { "BUGFORM_UPLOAD_TXT": "Sube al menos {{num}} archivo", diff --git a/src/locales/fr/translation.json b/src/locales/fr/translation.json index b44b5483..b34b6a35 100644 --- a/src/locales/fr/translation.json +++ b/src/locales/fr/translation.json @@ -545,6 +545,8 @@ "Try again.": "Réessayez.", "Type": "Type", "Type to search your city": "Tapez pour rechercher votre ville", + "USECASE_MEDIA_DROPZONE_MISSING_PARAMS": "Informations de campagne ou de tâche manquantes.", + "USECASE_MEDIA_DROPZONE_TITLE": "Téléchargement des médias", "Update your device list": "Mettez à jour votre liste d'appareils", "Upload a minimum number of {{num}} files": { "BUGFORM_UPLOAD_TXT": "Téléchargez au moins {{num}} médias", diff --git a/src/locales/it/translation.json b/src/locales/it/translation.json index e183c5fe..7729774d 100644 --- a/src/locales/it/translation.json +++ b/src/locales/it/translation.json @@ -545,6 +545,8 @@ "Try again.": "Riprova", "Type": "Tipo", "Type to search your city": "Digita per cercare la tua città", + "USECASE_MEDIA_DROPZONE_MISSING_PARAMS": "Informazioni mancanti su task o campagna", + "USECASE_MEDIA_DROPZONE_TITLE": "Upload dei media", "Update your device list": "Aggiorna la tua lista dispositivi", "Upload a minimum number of {{num}} files": { "BUGFORM_UPLOAD_TXT": "Carica almeno {{num}} file", From ee23efc8ab03f2204e7414fcc373d54540a49983 Mon Sep 17 00:00:00 2001 From: Kariamos Date: Mon, 20 Oct 2025 16:38:32 +0200 Subject: [PATCH 04/37] feat: add FileDropzonePage component for media uploads --- src/pages/UsecaseMediaDropzone/index.tsx | 76 ++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 src/pages/UsecaseMediaDropzone/index.tsx diff --git a/src/pages/UsecaseMediaDropzone/index.tsx b/src/pages/UsecaseMediaDropzone/index.tsx new file mode 100644 index 00000000..44c752bb --- /dev/null +++ b/src/pages/UsecaseMediaDropzone/index.tsx @@ -0,0 +1,76 @@ +import { Card, Text } from "@appquality/appquality-design-system"; +import { useEffect, useMemo } from "react"; +import { useTranslation } from "react-i18next"; +import { useLocation, useParams } from "react-router-dom"; +import styled from "styled-components"; + +import { MediaDropzone as UsecaseMediaDropzone } from "src/pages/Manual/UseCases/MediaDropzone"; +import { setMediaList } from "src/pages/Manual/UseCases/mediaSlice"; +import { useAppDispatch } from "src/store"; + +/* +/campaign//file-dropzone?taskId= +*/ + +const Wrapper = styled.main` + min-height: 100vh; + display: flex; + align-items: center; + justify-content: center; + padding: ${(p) => p.theme.grid.gutter}; + background: ${(p) => p.theme.colors.white}; +`; + +const InnerCard = styled(Card)` + width: 100%; + max-width: 680px; +`; + +const FileDropzonePage = () => { + const { t } = useTranslation(); + const dispatch = useAppDispatch(); + const { id: campaignIdParam } = useParams<{ id?: string }>(); + const location = useLocation(); + + const searchParams = useMemo( + () => new URLSearchParams(location.search), + [location.search] + ); + const taskId = searchParams.get("taskId") ?? ""; + const campaignId = campaignIdParam ?? ""; + + useEffect(() => { + dispatch(setMediaList([])); + return () => { + dispatch(setMediaList([])); + }; + }, [dispatch, campaignId, taskId]); + + if (!campaignId || !taskId) { + return ( + + + + {t("USECASE_MEDIA_DROPZONE_MISSING_PARAMS", { + defaultValue: "Missing campaign or task information.", + })} + + + + ); + } + + return ( + + + + + + ); +}; + +export default FileDropzonePage; From 29237340ff99ba7be3ac31c51bd2a101e1060b27 Mon Sep 17 00:00:00 2001 From: Kariamos Date: Mon, 20 Oct 2025 16:39:24 +0200 Subject: [PATCH 05/37] feat: media dropzone translation keys in multiple languages From 419b8ec50bb1526ed706db45acde93dbb334cb07 Mon Sep 17 00:00:00 2001 From: Kariamos Date: Tue, 21 Oct 2025 10:23:45 +0200 Subject: [PATCH 06/37] refactor: simplify error handling in FileDropzonePage component --- src/locales/en/translation.json | 2 +- src/locales/es/translation.json | 2 +- src/locales/fr/translation.json | 2 +- src/locales/it/translation.json | 2 +- src/pages/UsecaseMediaDropzone/index.tsx | 26 ++++++------------------ 5 files changed, 10 insertions(+), 24 deletions(-) diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index 368e8e36..0492f9bd 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -546,7 +546,6 @@ "Type": "Type", "Type to search your city": "Type to search your city", "USECASE_MEDIA_DROPZONE_MISSING_PARAMS": "Missing campaign or task information.", - "USECASE_MEDIA_DROPZONE_TITLE": "Uploading media", "Update your device list": "Update your device list", "Upload a minimum number of {{num}} files": { "BUGFORM_UPLOAD_TXT": "Upload at least {{num}} media", @@ -794,6 +793,7 @@ "BUGFORM_UPLOAD_PROGRESS": "{{num}} uploaded", "BUGFORM_UPLOAD_PROGRESS_plural": "{{num}} uploaded" }, + "USECASE_MEDIA_DROPZONE_TITLE": "Uploading media", "Report a Bug": "", "Page Preview": "", "/my-account/": "/my-account/", diff --git a/src/locales/es/translation.json b/src/locales/es/translation.json index 599f5c65..d48fc5f4 100644 --- a/src/locales/es/translation.json +++ b/src/locales/es/translation.json @@ -546,7 +546,6 @@ "Type": "Tipo", "Type to search your city": "Escriba para buscar tu ciudad", "USECASE_MEDIA_DROPZONE_MISSING_PARAMS": "Faltan información de campaña o tarea.", - "USECASE_MEDIA_DROPZONE_TITLE": "Subiendo medios", "Update your device list": "Actualizar tu lista de dispositivos", "Upload a minimum number of {{num}} files": { "BUGFORM_UPLOAD_TXT": "Sube al menos {{num}} archivo", @@ -794,6 +793,7 @@ "BUGFORM_UPLOAD_PROGRESS": "{{num}} subido", "BUGFORM_UPLOAD_PROGRESS_plural": "{{num}} subidos" }, + "USECASE_MEDIA_DROPZONE_TITLE": "Subiendo medios", "Report a Bug": "", "Page Preview": "Page Preview", "/my-account/": "/perfil/", diff --git a/src/locales/fr/translation.json b/src/locales/fr/translation.json index b34b6a35..7c581fd7 100644 --- a/src/locales/fr/translation.json +++ b/src/locales/fr/translation.json @@ -546,7 +546,6 @@ "Type": "Type", "Type to search your city": "Tapez pour rechercher votre ville", "USECASE_MEDIA_DROPZONE_MISSING_PARAMS": "Informations de campagne ou de tâche manquantes.", - "USECASE_MEDIA_DROPZONE_TITLE": "Téléchargement des médias", "Update your device list": "Mettez à jour votre liste d'appareils", "Upload a minimum number of {{num}} files": { "BUGFORM_UPLOAD_TXT": "Téléchargez au moins {{num}} médias", @@ -794,6 +793,7 @@ "BUGFORM_UPLOAD_PROGRESS": "{{num}} téléchargé", "BUGFORM_UPLOAD_PROGRESS_plural": "{{num}} téléchargés" }, + "USECASE_MEDIA_DROPZONE_TITLE": "Téléchargement des médias", "Report a Bug": "", "{{date}} {{at_time}} {{time}}": "", "Page Preview": "Page Preview", diff --git a/src/locales/it/translation.json b/src/locales/it/translation.json index 7729774d..3c4f8f40 100644 --- a/src/locales/it/translation.json +++ b/src/locales/it/translation.json @@ -546,7 +546,6 @@ "Type": "Tipo", "Type to search your city": "Digita per cercare la tua città", "USECASE_MEDIA_DROPZONE_MISSING_PARAMS": "Informazioni mancanti su task o campagna", - "USECASE_MEDIA_DROPZONE_TITLE": "Upload dei media", "Update your device list": "Aggiorna la tua lista dispositivi", "Upload a minimum number of {{num}} files": { "BUGFORM_UPLOAD_TXT": "Carica almeno {{num}} file", @@ -794,6 +793,7 @@ "BUGFORM_UPLOAD_PROGRESS": "{{num}} caricato", "BUGFORM_UPLOAD_PROGRESS_plural": "{{num}} caricati" }, + "USECASE_MEDIA_DROPZONE_TITLE": "Upload dei media", "Report a Bug": "Carica un Bug", "Page Preview": "Pagina di preview", "/my-account/": "/it/il-mio-account/", diff --git a/src/pages/UsecaseMediaDropzone/index.tsx b/src/pages/UsecaseMediaDropzone/index.tsx index 44c752bb..b1f0a6b0 100644 --- a/src/pages/UsecaseMediaDropzone/index.tsx +++ b/src/pages/UsecaseMediaDropzone/index.tsx @@ -48,29 +48,15 @@ const FileDropzonePage = () => { if (!campaignId || !taskId) { return ( - - - - {t("USECASE_MEDIA_DROPZONE_MISSING_PARAMS", { - defaultValue: "Missing campaign or task information.", - })} - - - + + {t("USECASE_MEDIA_DROPZONE_MISSING_PARAMS", { + defaultValue: "Missing campaign or task information.", + })} + ); } - return ( - - - - - - ); + return ; }; export default FileDropzonePage; From f989f62934b150f32d053c87c1cf029d1b3b2df7 Mon Sep 17 00:00:00 2001 From: Kariamos Date: Tue, 21 Oct 2025 11:01:46 +0200 Subject: [PATCH 07/37] feat: update FileDropzonePage route to include taskId as a URL parameter --- src/Page.tsx | 2 +- src/pages/UsecaseMediaDropzone/index.tsx | 37 +++++++----------------- 2 files changed, 11 insertions(+), 28 deletions(-) diff --git a/src/Page.tsx b/src/Page.tsx index 3f9553dd..01c08b2a 100644 --- a/src/Page.tsx +++ b/src/Page.tsx @@ -221,7 +221,7 @@ function Page() { diff --git a/src/pages/UsecaseMediaDropzone/index.tsx b/src/pages/UsecaseMediaDropzone/index.tsx index b1f0a6b0..c0d71257 100644 --- a/src/pages/UsecaseMediaDropzone/index.tsx +++ b/src/pages/UsecaseMediaDropzone/index.tsx @@ -1,42 +1,25 @@ -import { Card, Text } from "@appquality/appquality-design-system"; -import { useEffect, useMemo } from "react"; +import { Text } from "@appquality/appquality-design-system"; +import { useEffect } from "react"; import { useTranslation } from "react-i18next"; -import { useLocation, useParams } from "react-router-dom"; -import styled from "styled-components"; +import { useParams } from "react-router-dom"; import { MediaDropzone as UsecaseMediaDropzone } from "src/pages/Manual/UseCases/MediaDropzone"; import { setMediaList } from "src/pages/Manual/UseCases/mediaSlice"; import { useAppDispatch } from "src/store"; /* -/campaign//file-dropzone?taskId= +/campaign//file-dropzone/ */ -const Wrapper = styled.main` - min-height: 100vh; - display: flex; - align-items: center; - justify-content: center; - padding: ${(p) => p.theme.grid.gutter}; - background: ${(p) => p.theme.colors.white}; -`; - -const InnerCard = styled(Card)` - width: 100%; - max-width: 680px; -`; - const FileDropzonePage = () => { const { t } = useTranslation(); const dispatch = useAppDispatch(); - const { id: campaignIdParam } = useParams<{ id?: string }>(); - const location = useLocation(); - - const searchParams = useMemo( - () => new URLSearchParams(location.search), - [location.search] - ); - const taskId = searchParams.get("taskId") ?? ""; + const { id: campaignIdParam, taskId: taskIdParam } = useParams<{ + id?: string; + taskId?: string; + }>(); + + const taskId = taskIdParam ?? ""; const campaignId = campaignIdParam ?? ""; useEffect(() => { From 3999f0fd396e047fc8caf9a5659df3ccac88a9b3 Mon Sep 17 00:00:00 2001 From: Kariamos Date: Tue, 21 Oct 2025 11:12:12 +0200 Subject: [PATCH 08/37] refactor: remove USECASE_MEDIA_DROPZONE_TITLE from translation files --- src/locales/en/translation.json | 1 - src/locales/es/translation.json | 1 - src/locales/fr/translation.json | 1 - src/locales/it/translation.json | 1 - 4 files changed, 4 deletions(-) diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index 0492f9bd..7ab51b84 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -793,7 +793,6 @@ "BUGFORM_UPLOAD_PROGRESS": "{{num}} uploaded", "BUGFORM_UPLOAD_PROGRESS_plural": "{{num}} uploaded" }, - "USECASE_MEDIA_DROPZONE_TITLE": "Uploading media", "Report a Bug": "", "Page Preview": "", "/my-account/": "/my-account/", diff --git a/src/locales/es/translation.json b/src/locales/es/translation.json index d48fc5f4..112cf3db 100644 --- a/src/locales/es/translation.json +++ b/src/locales/es/translation.json @@ -793,7 +793,6 @@ "BUGFORM_UPLOAD_PROGRESS": "{{num}} subido", "BUGFORM_UPLOAD_PROGRESS_plural": "{{num}} subidos" }, - "USECASE_MEDIA_DROPZONE_TITLE": "Subiendo medios", "Report a Bug": "", "Page Preview": "Page Preview", "/my-account/": "/perfil/", diff --git a/src/locales/fr/translation.json b/src/locales/fr/translation.json index 7c581fd7..59603ee0 100644 --- a/src/locales/fr/translation.json +++ b/src/locales/fr/translation.json @@ -793,7 +793,6 @@ "BUGFORM_UPLOAD_PROGRESS": "{{num}} téléchargé", "BUGFORM_UPLOAD_PROGRESS_plural": "{{num}} téléchargés" }, - "USECASE_MEDIA_DROPZONE_TITLE": "Téléchargement des médias", "Report a Bug": "", "{{date}} {{at_time}} {{time}}": "", "Page Preview": "Page Preview", diff --git a/src/locales/it/translation.json b/src/locales/it/translation.json index 3c4f8f40..0e1bc2a0 100644 --- a/src/locales/it/translation.json +++ b/src/locales/it/translation.json @@ -793,7 +793,6 @@ "BUGFORM_UPLOAD_PROGRESS": "{{num}} caricato", "BUGFORM_UPLOAD_PROGRESS_plural": "{{num}} caricati" }, - "USECASE_MEDIA_DROPZONE_TITLE": "Upload dei media", "Report a Bug": "Carica un Bug", "Page Preview": "Pagina di preview", "/my-account/": "/it/il-mio-account/", From 1bf54c35443ea995ace076fb28560d78668a8318 Mon Sep 17 00:00:00 2001 From: Kariamos Date: Wed, 22 Oct 2025 11:19:13 +0200 Subject: [PATCH 09/37] feat: add translations for "Expired Earnings" and "Payment History" in Italian --- src/locales/en/translation.json | 2 ++ src/locales/es/translation.json | 2 ++ src/locales/fr/translation.json | 2 ++ src/locales/it/translation.json | 2 ++ 4 files changed, 8 insertions(+) diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index 5e60fbf4..3794bd50 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -683,6 +683,8 @@ "__WALLET_CARD-REQUEST_DISCLAIMER-PROCESSING MAX: 150": "You can request only one payment at a time: you alreay have a payment in process, this may take up to 20 working days.", "__WALLET_CARD-REQUEST_TITLE MAX: 40": "Manage your payment", "__WALLET_CARD-YOUR_WALLET_MAX: 15": "Your wallet", + "__WALLET_EXPIRED_TAB": "", + "__WALLET_HISTORY_TAB": "", "__WALLET_HOME-EMPTY_STATE_MAX: 105": "Your payment history is now empty. When you start requesting your payments, you will view them here.", "__WALLET_TABLE-HEADER_CTA-ICON-DETAILS MAX:": "View details", "__WALLET_TABLE-HEADER_CTA-ICON-PDF MAX:": "Download receipt", diff --git a/src/locales/es/translation.json b/src/locales/es/translation.json index e6c67456..d0a0c39f 100644 --- a/src/locales/es/translation.json +++ b/src/locales/es/translation.json @@ -683,6 +683,8 @@ "__WALLET_CARD-REQUEST_DISCLAIMER-PROCESSING MAX: 150": "Solo puedes solicitar un pago a la vez: ya tienes una solicitud pendiente, ésta puede tardar hasta 20 días laborables.", "__WALLET_CARD-REQUEST_TITLE MAX: 40": "Gestiona el pago", "__WALLET_CARD-YOUR_WALLET_MAX: 15": "Tu monedero", + "__WALLET_EXPIRED_TAB": "", + "__WALLET_HISTORY_TAB": "", "__WALLET_HOME-EMPTY_STATE_MAX: 105": "Aún no has solicitado ningun pago. Cuando lo harás, podrás ver tus pagos aquí.", "__WALLET_TABLE-HEADER_CTA-ICON-DETAILS MAX:": "Ver detalles", "__WALLET_TABLE-HEADER_CTA-ICON-PDF MAX:": "Descargar recibo", diff --git a/src/locales/fr/translation.json b/src/locales/fr/translation.json index b44b5483..15b52785 100644 --- a/src/locales/fr/translation.json +++ b/src/locales/fr/translation.json @@ -683,6 +683,8 @@ "__WALLET_CARD-REQUEST_DISCLAIMER-PROCESSING MAX: 150": "Vous ne pouvez demander qu'un paiement à la fois : vous avez déjà un paiement en cours, cela peut prendre jusqu'à 20 jours ouvrables.", "__WALLET_CARD-REQUEST_TITLE MAX: 40": "Gérez votre paiement", "__WALLET_CARD-YOUR_WALLET_MAX: 15": "Votre portefeuille", + "__WALLET_EXPIRED_TAB": "", + "__WALLET_HISTORY_TAB": "", "__WALLET_HOME-EMPTY_STATE_MAX: 105": "Votre historique de paiement est actuellement vide. Lorsque vous commencerez à demander vos paiements, vous les verrez ici.", "__WALLET_TABLE-HEADER_CTA-ICON-DETAILS MAX:": "Voir les détails", "__WALLET_TABLE-HEADER_CTA-ICON-PDF MAX:": "Télécharger le reçu", diff --git a/src/locales/it/translation.json b/src/locales/it/translation.json index e183c5fe..91b4c5db 100644 --- a/src/locales/it/translation.json +++ b/src/locales/it/translation.json @@ -683,6 +683,8 @@ "__WALLET_CARD-REQUEST_DISCLAIMER-PROCESSING MAX: 150": "Puoi richiedere solo un pagamento alla volta: hai già una richiesta in lavorazione, la procedura può durare fino a 20 giorni lavorativi.", "__WALLET_CARD-REQUEST_TITLE MAX: 40": "Gestisci il pagamento", "__WALLET_CARD-YOUR_WALLET_MAX: 15": "Il tuo portafoglio", + "__WALLET_EXPIRED_TAB": "Guadagni scaduti", + "__WALLET_HISTORY_TAB": "Cronologia pagamenti", "__WALLET_HOME-EMPTY_STATE_MAX: 105": "Per ora non hai ancora richiesto un pagamento. Quando inizierai a richiederne, compariranno qui.", "__WALLET_TABLE-HEADER_CTA-ICON-DETAILS MAX:": "Vedi dettagli", "__WALLET_TABLE-HEADER_CTA-ICON-PDF MAX:": "Scarica ricevuta", From b473fc51f071bebeafca08c8ec8d0d46c797d3e8 Mon Sep 17 00:00:00 2001 From: Kariamos Date: Wed, 22 Oct 2025 11:19:37 +0200 Subject: [PATCH 10/37] feat: implement useTabFragment hook for managing active tab state --- src/pages/Wallet/WalletTabFragment.tsx | 28 ++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/pages/Wallet/WalletTabFragment.tsx diff --git a/src/pages/Wallet/WalletTabFragment.tsx b/src/pages/Wallet/WalletTabFragment.tsx new file mode 100644 index 00000000..51b7e72a --- /dev/null +++ b/src/pages/Wallet/WalletTabFragment.tsx @@ -0,0 +1,28 @@ +import { useEffect, useState } from "react"; + +const useTabFragment = () => { + const urlParams = new URLSearchParams(window.location.search); + const tabParam = urlParams.get("tab") || "history"; + const currentTab = ["history", "expired"].includes(tabParam) + ? tabParam + : "history"; + + const [activeTab, setActiveTab] = useState(currentTab); + + useEffect(() => { + const currentParams = new URLSearchParams(window.location.search); + currentParams.set("tab", activeTab); + window.history.pushState( + {}, + "", + window.location.origin + + window.location.pathname + + "?" + + currentParams.toString() + ); + }, [activeTab]); + + return { activeTab, setActiveTab }; +}; + +export default useTabFragment; From 5682e1945d7419fa9bc27fef09f90653b21b603a Mon Sep 17 00:00:00 2001 From: Kariamos Date: Wed, 22 Oct 2025 11:20:01 +0200 Subject: [PATCH 11/37] feat: add tabbed interface for wallet history and expired payments --- src/pages/Wallet/WalletTable.tsx | 83 ++++++++++++++++++++++++-------- 1 file changed, 62 insertions(+), 21 deletions(-) diff --git a/src/pages/Wallet/WalletTable.tsx b/src/pages/Wallet/WalletTable.tsx index 4f144105..5d706918 100644 --- a/src/pages/Wallet/WalletTable.tsx +++ b/src/pages/Wallet/WalletTable.tsx @@ -1,8 +1,10 @@ import { Pagination, SortTableSelect, + Tab, Table, TableType, + Tabs, } from "@appquality/appquality-design-system"; import { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; @@ -21,6 +23,7 @@ import { openPaymentDetailsModal } from "src/redux/wallet/actions/openPaymentDet import { currencyTable, getPaidDate } from "src/redux/wallet/utils"; import { useGetUsersMePaymentsQuery } from "src/services/tryberApi"; import styled from "styled-components"; +import useTabFragment from "src/pages/Wallet/WalletTabFragment"; const ActionsCell = styled.div` display: flex; @@ -100,6 +103,7 @@ export const WalletTable = () => { const dispatch = useAppDispatch(); const [columns, setcolumns] = useState([]); const [rows, setRows] = useState([]); + const { activeTab, setActiveTab } = useTabFragment(); const { requestsList } = useSelector( (state: GeneralState) => state.wallet, @@ -228,27 +232,64 @@ export const WalletTable = () => { }; return ( <> - {columns.length > 0 && ( - - )} - + + {t("__WALLET_HISTORY_TAB")} + } + > + {columns.length > 0 && ( + + )} +
+ + {t("__WALLET_EXPIRED_TAB")} + } + > + {columns.length > 0 && ( + + )} +
+ + Date: Wed, 22 Oct 2025 16:18:07 +0200 Subject: [PATCH 12/37] feat: add expired tab columns for wallet with sortable options --- src/locales/en/translation.json | 4 +++ src/locales/es/translation.json | 4 +++ src/locales/fr/translation.json | 4 +++ src/locales/it/translation.json | 4 +++ src/pages/Wallet/expiredTabColumns.ts | 51 +++++++++++++++++++++++++++ 5 files changed, 67 insertions(+) create mode 100644 src/pages/Wallet/expiredTabColumns.ts diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index 3794bd50..315268ac 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -216,6 +216,7 @@ "SignupFrom Step1": "Date of birth" }, "Dashboard": "Dashboard", + "Data attribuzione": "", "Date": "Date", "Delete": "Delete", "Delete account": "Delete account", @@ -244,6 +245,7 @@ "Employment": "Employment", "End Date": "End Date", "Experience Points": "Experience Points", + "Expired On": "", "Extra Award": "Extra Award", "FAQ": "FAQ", "Facebook": "Facebook", @@ -538,10 +540,12 @@ "This is an invalid format. Should be formatted as +11000000000 or 0011000000000": "This is an invalid format. Should be formatted as +11000000000 or 0011000000000", "This is your personal dashboard. From here you can check out your stats, keep an eye on the progress of your work and find new campaigns to apply for. Have fun!": "This is your personal dashboard. From here you can check out your stats, keep an eye on the progress of your work and find new campaigns to apply for. Have fun!", "This value is invalid, you need to select a city with a province": "This value is invalid, you need to select a city with a province", + "Tipo attività": "", "Title": "Title", "Top 3 | level {{level}}": { "__RANKING_TITLE_LABEL_TOP_LEVEL_MAX: 25": "Top 3 | {{level}} level" }, + "Tot. lordo": "", "Try again.": "Try again.", "Type": "Type", "Type to search your city": "Type to search your city", diff --git a/src/locales/es/translation.json b/src/locales/es/translation.json index d0a0c39f..45c5e00e 100644 --- a/src/locales/es/translation.json +++ b/src/locales/es/translation.json @@ -216,6 +216,7 @@ "SignupFrom Step1": "Fecha de nacimiento" }, "Dashboard": "Dashboard", + "Data attribuzione": "", "Date": "Fecha", "Delete": "Eliminar", "Delete account": "Elímina account", @@ -244,6 +245,7 @@ "Employment": "Empleo", "End Date": "Fecha Final", "Experience Points": "Puntos de Experiencia", + "Expired On": "", "Extra Award": "Recompensa Extra", "FAQ": "Preguntas Frecuentes", "Facebook": "Facebook", @@ -538,10 +540,12 @@ "This is an invalid format. Should be formatted as +11000000000 or 0011000000000": "Este es un formato no válido. Tiene que ser formateado como +11000000000 o 0011000000000", "This is your personal dashboard. From here you can check out your stats, keep an eye on the progress of your work and find new campaigns to apply for. Have fun!": "Este es tu dashboard personal. Desde aquí puedes consultar tus estadísticas, el progreso de tu trabajo y encontrar nuevas Campañas a las que postularte. ¡Diviértete!", "This value is invalid, you need to select a city with a province": "Este valor no es válido, es necesario seleccionar una ciudad con una provincia", + "Tipo attività": "", "Title": "Título", "Top 3 | level {{level}}": { "__RANKING_TITLE_LABEL_TOP_LEVEL_MAX: 25": "Top 3 | Nivel {{level}}" }, + "Tot. lordo": "", "Try again.": "Inténtelo de nuevo.", "Type": "Tipo", "Type to search your city": "Escriba para buscar tu ciudad", diff --git a/src/locales/fr/translation.json b/src/locales/fr/translation.json index 15b52785..768de788 100644 --- a/src/locales/fr/translation.json +++ b/src/locales/fr/translation.json @@ -216,6 +216,7 @@ "SignupFrom Step1": "Date de naissance" }, "Dashboard": "Tableau de bord", + "Data attribuzione": "", "Date": "Date", "Delete": "Supprimer", "Delete account": "Supprimer le compte", @@ -244,6 +245,7 @@ "Employment": "Emploi", "End Date": "Date de fin", "Experience Points": "Points d'expérience", + "Expired On": "", "Extra Award": "Récompense supplémentaire", "FAQ": "FAQ", "Facebook": "Facebook", @@ -538,10 +540,12 @@ "This is an invalid format. Should be formatted as +11000000000 or 0011000000000": "Ce format est invalide. Il doit être formaté comme +11000000000 ou 0011000000000", "This is your personal dashboard. From here you can check out your stats, keep an eye on the progress of your work and find new campaigns to apply for. Have fun!": "Ceci est votre tableau de bord personnel. D'ici, vous pouvez consulter vos statistiques, surveiller l'avancement de votre travail et trouver de nouvelles campagnes pour lesquelles postuler. Amusez-vous bien !", "This value is invalid, you need to select a city with a province": "Cette valeur est invalide, vous devez sélectionner une ville avec une province", + "Tipo attività": "", "Title": "Titre", "Top 3 | level {{level}}": { "__RANKING_TITLE_LABEL_TOP_LEVEL_MAX: 25": "Top 3 | niveau {{level}}" }, + "Tot. lordo": "", "Try again.": "Réessayez.", "Type": "Type", "Type to search your city": "Tapez pour rechercher votre ville", diff --git a/src/locales/it/translation.json b/src/locales/it/translation.json index 91b4c5db..43c06761 100644 --- a/src/locales/it/translation.json +++ b/src/locales/it/translation.json @@ -216,6 +216,7 @@ "SignupFrom Step1": "Data di nascita" }, "Dashboard": "Dashboard", + "Data attribuzione": "", "Date": "Data", "Delete": "Rimuovi", "Delete account": "Elimina account", @@ -244,6 +245,7 @@ "Employment": "Occupazione", "End Date": "Fine", "Experience Points": "Punti esperienza", + "Expired On": "", "Extra Award": "Premio extra", "FAQ": "Domande frequenti", "Facebook": "Facebook", @@ -538,10 +540,12 @@ "This is an invalid format. Should be formatted as +11000000000 or 0011000000000": "Formato invalido. Deve essere formattato come +11000000000 o 0011000000000", "This is your personal dashboard. From here you can check out your stats, keep an eye on the progress of your work and find new campaigns to apply for. Have fun!": "Questa è la tua dashboard personale. Da qui puoi controllare le tue statistiche, tenere d'occhio lo stato di avanzamento del tuo lavoro e trovare nuove campagne a cui candidarti. Divertiti!", "This value is invalid, you need to select a city with a province": "Questo valore è invalido, devi selezionare una città con una provincia", + "Tipo attività": "", "Title": "Titolo", "Top 3 | level {{level}}": { "__RANKING_TITLE_LABEL_TOP_LEVEL_MAX: 25": "Top 3 | Livello {{level}}" }, + "Tot. lordo": "", "Try again.": "Riprova", "Type": "Tipo", "Type to search your city": "Digita per cercare la tua città", diff --git a/src/pages/Wallet/expiredTabColumns.ts b/src/pages/Wallet/expiredTabColumns.ts new file mode 100644 index 00000000..19baa4c6 --- /dev/null +++ b/src/pages/Wallet/expiredTabColumns.ts @@ -0,0 +1,51 @@ +import { Column } from "@appquality/appquality-design-system/dist/stories/table/_types"; +import { TFunction } from "react-i18next"; +import { updateSortingOptions } from "src/redux/wallet/actionCreator"; + +export const expiredTabColumns = ( + dispatch: AppDispatch, + t: TFunction<"translation"> +): Column[] => { + return [ + { + title: "Nome attività", + dataIndex: "activityName", + key: "activityName", + maxWidth: "max-content", + }, + { + title: t("Tipo attività"), + dataIndex: "activityType", + key: "activityType", + role: "overline", + hideIndex: true, + }, + { + title: t("Data attribuzione"), + dataIndex: "attributionDate", + key: "attributionDate", + isSortable: true, + onSort: (newOrder) => { + // dispatch(updateSortingOptions(newOrder, "attributionDate")); + }, + }, + { + title: t("Tot. lordo"), + dataIndex: "gross", + key: "gross", + isSortable: true, + onSort: (newOrder) => { + dispatch(updateSortingOptions(newOrder, "gross")); + }, + }, + { + title: t("Expired On"), + dataIndex: "expiredDate", + key: "expiredDate", + isSortable: true, + onSort: (newOrder: OrderType) => { + // dispatch(updateSortingOptions(newOrder, "expiredDate")); + }, + }, + ]; +}; From 8d3a2e19e1f38f67fba24adbc1b5b987694a1480 Mon Sep 17 00:00:00 2001 From: Kariamos Date: Wed, 22 Oct 2025 16:25:20 +0200 Subject: [PATCH 13/37] wip: implement expired tab --- src/pages/Wallet/WalletTable.tsx | 36 ++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/src/pages/Wallet/WalletTable.tsx b/src/pages/Wallet/WalletTable.tsx index 5d706918..35e6b5d7 100644 --- a/src/pages/Wallet/WalletTable.tsx +++ b/src/pages/Wallet/WalletTable.tsx @@ -21,9 +21,13 @@ import { useAppDispatch } from "src/redux/provider"; import { updatePagination } from "src/redux/wallet/actionCreator"; import { openPaymentDetailsModal } from "src/redux/wallet/actions/openPaymentDetailsModal"; import { currencyTable, getPaidDate } from "src/redux/wallet/utils"; -import { useGetUsersMePaymentsQuery } from "src/services/tryberApi"; +import { + useGetUsersMePaymentsQuery, + useGetUsersMePendingBootyQuery, +} from "src/services/tryberApi"; import styled from "styled-components"; import useTabFragment from "src/pages/Wallet/WalletTabFragment"; +import { expiredTabColumns } from "./expiredTabColumns"; const ActionsCell = styled.div` display: flex; @@ -102,7 +106,11 @@ export const WalletTable = () => { const { t } = useTranslation(); const dispatch = useAppDispatch(); const [columns, setcolumns] = useState([]); + const [expiredColumns, setExpiredColumns] = useState([]); + const [rows, setRows] = useState([]); + const [expiredRows, setExpiredRows] = useState([]); + const { activeTab, setActiveTab } = useTabFragment(); const { requestsList } = useSelector( @@ -116,10 +124,15 @@ export const WalletTable = () => { order, orderBy, }); + + const { data: expiredBootyData, isLoading: isExpiredBootyLoading } = + useGetUsersMePendingBootyQuery({ filterBy: { isExpired: 0 } }); // initial requests useEffect(() => { const cols = walletColumns(dispatch, t); setcolumns(cols); + const expiredCols = expiredTabColumns(dispatch, t); + setExpiredColumns(expiredCols); }, []); // update datasource for the table useEffect(() => { @@ -226,6 +239,21 @@ export const WalletTable = () => { ); } }, [data]); + + /* useEffect(() => { + if (typeof expiredBootyData?.results !== "undefined") { + setExpiredRows( + expiredBootyData.results.map((req) => { + return { + activity: req.activity, + amount: req.amount.gross.value, + attributionDate: req.attributionDate, + name: req.name, + }; + }) + ); + } + }, [data]); */ const changePagination = (newPage: number) => { const newStart = limit * (newPage - 1); dispatch(updatePagination(newStart)); @@ -271,14 +299,14 @@ export const WalletTable = () => { )}
Date: Thu, 23 Oct 2025 10:07:51 +0200 Subject: [PATCH 14/37] feat: enhance FileDropzonePage with styled template for improved layout --- src/pages/UsecaseMediaDropzone/index.tsx | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/pages/UsecaseMediaDropzone/index.tsx b/src/pages/UsecaseMediaDropzone/index.tsx index c0d71257..a67de447 100644 --- a/src/pages/UsecaseMediaDropzone/index.tsx +++ b/src/pages/UsecaseMediaDropzone/index.tsx @@ -1,4 +1,4 @@ -import { Text } from "@appquality/appquality-design-system"; +import { aqBootstrapTheme, Text } from "@appquality/appquality-design-system"; import { useEffect } from "react"; import { useTranslation } from "react-i18next"; import { useParams } from "react-router-dom"; @@ -6,11 +6,20 @@ import { useParams } from "react-router-dom"; import { MediaDropzone as UsecaseMediaDropzone } from "src/pages/Manual/UseCases/MediaDropzone"; import { setMediaList } from "src/pages/Manual/UseCases/mediaSlice"; import { useAppDispatch } from "src/store"; +import styled from "styled-components"; /* /campaign//file-dropzone/ */ +const StyledPageTemplate = styled.div` + background-color: ${aqBootstrapTheme.colors.gray50}; + .preview-selection-form { + max-width: 100%; + padding: 0 16px; + } +`; + const FileDropzonePage = () => { const { t } = useTranslation(); const dispatch = useAppDispatch(); @@ -39,7 +48,11 @@ const FileDropzonePage = () => { ); } - return ; + return ( + + + + ); }; export default FileDropzonePage; From 97edb0763fa81047d27922399a3b7845e76177c4 Mon Sep 17 00:00:00 2001 From: Kariamos Date: Thu, 23 Oct 2025 10:22:17 +0200 Subject: [PATCH 15/37] refactor: remove unused styles from StyledPageTemplate in FileDropzonePage --- src/pages/UsecaseMediaDropzone/index.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/pages/UsecaseMediaDropzone/index.tsx b/src/pages/UsecaseMediaDropzone/index.tsx index a67de447..3ad82203 100644 --- a/src/pages/UsecaseMediaDropzone/index.tsx +++ b/src/pages/UsecaseMediaDropzone/index.tsx @@ -14,9 +14,6 @@ import styled from "styled-components"; const StyledPageTemplate = styled.div` background-color: ${aqBootstrapTheme.colors.gray50}; - .preview-selection-form { - max-width: 100%; - padding: 0 16px; } `; From 4f535b13c925ffb2cb4a8fafeaa462459f20748b Mon Sep 17 00:00:00 2001 From: Kariamos Date: Thu, 23 Oct 2025 10:50:32 +0200 Subject: [PATCH 16/37] fix: update background color of StyledPageTemplate in UsecaseMediaDropzone --- src/pages/UsecaseMediaDropzone/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/UsecaseMediaDropzone/index.tsx b/src/pages/UsecaseMediaDropzone/index.tsx index 3ad82203..96774ad1 100644 --- a/src/pages/UsecaseMediaDropzone/index.tsx +++ b/src/pages/UsecaseMediaDropzone/index.tsx @@ -13,7 +13,7 @@ import styled from "styled-components"; */ const StyledPageTemplate = styled.div` - background-color: ${aqBootstrapTheme.colors.gray50}; + background-color: ${aqBootstrapTheme.colors.white}; } `; From 9ab3afda39af0714d9cbc534389a29d55cc4763a Mon Sep 17 00:00:00 2001 From: ZecD Date: Thu, 23 Oct 2025 12:13:01 +0200 Subject: [PATCH 17/37] Implement code structure updates and remove redundant sections --- src/locales/en/translation.json | 1 + src/locales/es/translation.json | 1 + src/locales/fr/translation.json | 1 + src/locales/it/translation.json | 1 + .../BootyDetailsModal/BootyDetailsModal.tsx | 7 + src/pages/Wallet/BootyDetailsModal/columns.ts | 6 + src/pages/Wallet/WalletTable.tsx | 42 +- src/services/tryberApi/index.ts | 4 + src/utils/schema.ts | 3749 ++++++++++------- 9 files changed, 2336 insertions(+), 1476 deletions(-) diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index 315268ac..08a1e450 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -245,6 +245,7 @@ "Employment": "Employment", "End Date": "End Date", "Experience Points": "Experience Points", + "Expiration date": "", "Expired On": "", "Extra Award": "Extra Award", "FAQ": "FAQ", diff --git a/src/locales/es/translation.json b/src/locales/es/translation.json index 45c5e00e..b10e4fbf 100644 --- a/src/locales/es/translation.json +++ b/src/locales/es/translation.json @@ -245,6 +245,7 @@ "Employment": "Empleo", "End Date": "Fecha Final", "Experience Points": "Puntos de Experiencia", + "Expiration date": "", "Expired On": "", "Extra Award": "Recompensa Extra", "FAQ": "Preguntas Frecuentes", diff --git a/src/locales/fr/translation.json b/src/locales/fr/translation.json index 768de788..20ef7be8 100644 --- a/src/locales/fr/translation.json +++ b/src/locales/fr/translation.json @@ -245,6 +245,7 @@ "Employment": "Emploi", "End Date": "Date de fin", "Experience Points": "Points d'expérience", + "Expiration date": "", "Expired On": "", "Extra Award": "Récompense supplémentaire", "FAQ": "FAQ", diff --git a/src/locales/it/translation.json b/src/locales/it/translation.json index 43c06761..6fdf07b2 100644 --- a/src/locales/it/translation.json +++ b/src/locales/it/translation.json @@ -245,6 +245,7 @@ "Employment": "Occupazione", "End Date": "Fine", "Experience Points": "Punti esperienza", + "Expiration date": "", "Expired On": "", "Extra Award": "Premio extra", "FAQ": "Domande frequenti", diff --git a/src/pages/Wallet/BootyDetailsModal/BootyDetailsModal.tsx b/src/pages/Wallet/BootyDetailsModal/BootyDetailsModal.tsx index 679e8294..2c2c63c9 100644 --- a/src/pages/Wallet/BootyDetailsModal/BootyDetailsModal.tsx +++ b/src/pages/Wallet/BootyDetailsModal/BootyDetailsModal.tsx @@ -53,6 +53,9 @@ export const BootyDetailsModal = () => { if (typeof results !== "undefined") { setRows( results?.map((r) => { + const attributionDate = new Date(r.attributionDate); + const expiredDate = new Date(attributionDate); + expiredDate.setMonth(expiredDate.getMonth() + 12); const formattedAmount = `${ r.amount.net?.currency && r.amount.net?.currency in currencyTable ? currencyTable[r.amount.net?.currency] @@ -101,6 +104,10 @@ export const BootyDetailsModal = () => { ), }, + expirationDate: { + title: expiredDate.toISOString().split("T")[0], + content: {expiredDate.toLocaleDateString()}, + }, }; }) ); diff --git a/src/pages/Wallet/BootyDetailsModal/columns.ts b/src/pages/Wallet/BootyDetailsModal/columns.ts index f77ef3be..f9c95b8c 100644 --- a/src/pages/Wallet/BootyDetailsModal/columns.ts +++ b/src/pages/Wallet/BootyDetailsModal/columns.ts @@ -50,5 +50,11 @@ export const bootyDetailsColumns = ( dispatch(updateBootyDetailsSortingOptions(newOrder, "gross")); }, }, + { + title: t("Expiration date"), + dataIndex: "expirationDate", + key: "expirationDate", + hideIndex: true, + }, ]; }; diff --git a/src/pages/Wallet/WalletTable.tsx b/src/pages/Wallet/WalletTable.tsx index 35e6b5d7..68c5128f 100644 --- a/src/pages/Wallet/WalletTable.tsx +++ b/src/pages/Wallet/WalletTable.tsx @@ -126,7 +126,7 @@ export const WalletTable = () => { }); const { data: expiredBootyData, isLoading: isExpiredBootyLoading } = - useGetUsersMePendingBootyQuery({ filterBy: { isExpired: 0 } }); + useGetUsersMePendingBootyQuery({ filterBy: { isExpired: 1 } }); // initial requests useEffect(() => { const cols = walletColumns(dispatch, t); @@ -240,20 +240,48 @@ export const WalletTable = () => { } }, [data]); - /* useEffect(() => { + useEffect(() => { if (typeof expiredBootyData?.results !== "undefined") { setExpiredRows( expiredBootyData.results.map((req) => { + const attributionDate = new Date(req.attributionDate); + const expiredDate = new Date(attributionDate); + expiredDate.setMonth(expiredDate.getMonth() + 12); return { - activity: req.activity, - amount: req.amount.gross.value, - attributionDate: req.attributionDate, - name: req.name, + key: req.id, + activityName: { + title: req.name, + content: {req.name}, + }, + activityType: { + title: req.activity, + content: {req.activity}, + }, + attributionDate: { + title: req.attributionDate, + content: {req.attributionDate}, + }, + gross: { + title: "€ " + req.amount?.gross?.value, + content: ( + + {req.amount?.gross?.currency && + req.amount?.gross?.currency in currencyTable + ? currencyTable[req.amount?.gross?.currency] + : req.amount?.gross?.currency}{" "} + {req.amount?.gross?.value?.toFixed(2)} + + ), + }, + expiredDate: { + title: expiredDate.toISOString().split("T")[0], + content: {expiredDate.toLocaleDateString()}, + }, }; }) ); } - }, [data]); */ + }, [expiredBootyData]); const changePagination = (newPage: number) => { const newStart = limit * (newPage - 1); dispatch(updatePagination(newStart)); diff --git a/src/services/tryberApi/index.ts b/src/services/tryberApi/index.ts index 1af30aa3..597aceca 100644 --- a/src/services/tryberApi/index.ts +++ b/src/services/tryberApi/index.ts @@ -1082,6 +1082,7 @@ const injectedRtkApi = api.injectEndpoints({ limit: queryArg.limit, orderBy: queryArg.orderBy, order: queryArg.order, + filterBy: queryArg.filterBy, }, }), }), @@ -2038,6 +2039,7 @@ export type PostDossiersApiArg = { } & { autoApply?: number; bugLanguage?: BugLang; + hasBugForm?: number; hasBugParade?: number; pageVersion?: "v1" | "v2"; skipPagesAndTasks?: number; @@ -3190,6 +3192,8 @@ export type GetUsersMePendingBootyApiArg = { | "activity"; /** How to order values (ASC, DESC) */ order?: "ASC" | "DESC"; + /** Key-value Array for item filtering */ + filterBy?: object; }; export type GetUsersMePermissionsApiResponse = /** status 200 OK */ { appq_bug?: Olp; diff --git a/src/utils/schema.ts b/src/utils/schema.ts index 507b30bc..6e52f5c7 100644 --- a/src/utils/schema.ts +++ b/src/utils/schema.ts @@ -33,12 +33,54 @@ export interface paths { /** A request to login with your username and password */ post: operations["post-authenticate"]; }; + "/browsers": { + get: operations["get-browsers"]; + }; + "/bugs/{bugId}/status": { + patch: operations["patch-bugs-bugId-status"]; + parameters: { + path: { + bugId: string; + }; + }; + }; + "/campaignTypes": { + get: operations["get-campaign-types"]; + parameters: {}; + }; "/campaigns": { /** Get all the Campaigns you have access to */ get: operations["get-campaigns"]; /** Create a new Campaign if you have access to the creation */ post: operations["post-campaigns"]; }; + "/campaigns/forms": { + get: operations["get-campaigns-forms"]; + post: operations["post-campaigns-forms"]; + parameters: {}; + }; + "/campaigns/forms/{formId}": { + get: operations["get-campaigns-forms-formId"]; + put: operations["put-campaigns-forms-formId"]; + parameters: { + path: { + formId: string; + }; + }; + }; + "/campaigns/owners": { + /** Get all the owners of campaigns you have access to */ + get: operations["get-campaigns-owners"]; + parameters: {}; + }; + "/campaigns/{campaignId}/visibility": { + patch: operations["patch-campaigns-campaignId-visibility"]; + parameters: { + path: { + campaignId: string; + }; + }; + }; "/campaigns/{campaign}": { /** Get the data of a Campaign if you have access to it */ get: operations["get-campaigns-campaign"]; @@ -61,6 +103,28 @@ export interface paths { }; }; }; + "/campaigns/{campaign}/bugs/{bugId}": { + /** Get single bug of a Campaign if you have access to it */ + get: operations["get-campaigns-single-bug"]; + parameters: { + path: { + /** A campaign id */ + campaign: string; + bugId: string; + }; + }; + }; + "/campaigns/{campaign}/bugs/{bugId}/aiReview": { + /** Get ai review for a single bug of a Campaign if you have access to it */ + get: operations["get-campaigns-single-bug-ai-review"]; + parameters: { + path: { + /** A campaign id */ + campaign: string; + bugId: string; + }; + }; + }; "/campaigns/{campaign}/candidates": { get: operations["get-campaigns-campaign-candidates"]; /** The Tryber will be inserted as a candidate Tryber on a specific Campaign */ @@ -112,6 +176,7 @@ export interface paths { }; "/campaigns/{campaign}/payouts": { get: operations["get-campaigns-campaign-payouts"]; + put: operations["put-campaigns-campaign-payouts"]; parameters: { path: { /** A campaign id */ @@ -119,6 +184,14 @@ export interface paths { }; }; }; + "/campaigns/{campaign}/preview": { + post: operations["post-campaigns-campaign-preview"]; + parameters: { + path: { + campaign: string; + }; + }; + }; "/campaigns/{campaign}/prospect": { get: operations["get-campaigns-campaign-prospect"]; /** Make campaign perspective status done, and change exp points and tester payouts. */ @@ -185,29 +258,6 @@ export interface paths { }; }; }; - "/campaigns/forms": { - get: operations["get-campaigns-forms"]; - post: operations["post-campaigns-forms"]; - parameters: {}; - }; - "/campaigns/forms/{formId}": { - get: operations["get-campaigns-forms-formId"]; - put: operations["put-campaigns-forms-formId"]; - parameters: { - path: { - formId: string; - }; - }; - }; - "/campaigns/owners": { - /** Get all the owners of campaigns you have access to */ - get: operations["get-campaigns-owners"]; - parameters: {}; - }; - "/campaignTypes": { - get: operations["get-campaign-types"]; - parameters: {}; - }; "/certifications": { /** Get all certificatio */ get: operations["get-certifications"]; @@ -221,15 +271,24 @@ export interface paths { }; }; }; + "/custom_user_fields": { + get: operations["get-customUserFields"]; + parameters: {}; + }; "/customers": { /** Get all the customers you have access to */ get: operations["get-customers"]; post: operations["post-customers"]; parameters: {}; }; - "/custom_user_fields": { - get: operations["get-customUserFields"]; - parameters: {}; + "/customers/{customer}/projects": { + get: operations["get-customers-customer-projects"]; + post: operations["post-customers-customer-projects"]; + parameters: { + path: { + customer: string; + }; + }; }; "/devices/{device_type}/models": { /** Get all model of devices with theirs manufacturers */ @@ -258,16 +317,58 @@ export interface paths { }; }; }; - "/education": { - /** Get all education levels */ - get: operations["get-education"]; + "/dossiers": { + post: operations["post-dossiers"]; + parameters: {}; }; - "/employments": { - /** Get all employments */ - get: operations["get-employments"]; + "/dossiers/{campaign}": { + get: operations["get-dossiers-campaign"]; + put: operations["put-dossiers-campaign"]; + parameters: { + path: { + /** A campaign id */ + campaign: string; + }; + }; }; - "/jotforms/{campaign}": { - post: operations["post-jotforms-campaignId"]; + "/dossiers/{campaign}/availableTesters": { + /** */ + get: operations["get-dossiers-campaign-availableTesters"]; + parameters: { + path: { + campaign: string; + }; + }; + }; + "/dossiers/{campaign}/manual": { + post: operations["post-dossiers-campaign-manual"]; + parameters: { + path: { + /** A campaign id */ + campaign: components["parameters"]["campaign"]; + }; + }; + }; + "/dossiers/{campaign}/phases": { + put: operations["put-dossiers-campaign-phases"]; + parameters: { + path: { + /** A campaign id */ + campaign: string; + }; + }; + }; + "/dossiers/{campaign}/preview": { + post: operations["post-dossiers-campaign-preview"]; + parameters: { + path: { + /** A campaign id */ + campaign: components["parameters"]["campaign"]; + }; + }; + }; + "/dossiers/{campaign}/quotations": { + post: operations["post-dossiers-campaign-quotations"]; parameters: { path: { /** A campaign id */ @@ -275,6 +376,33 @@ export interface paths { }; }; }; + "/dossiers/{campaign}/quotations/{quote}": { + patch: operations["patch-dossiers-campaign-quotations-quote"]; + parameters: { + path: { + /** A campaign id */ + campaign: string; + quote: string; + }; + }; + }; + "/dossiers/{campaign}/quotesHistory": { + get: operations["get-dossiers-campaign-quotes-history"]; + parameters: { + path: { + /** A campaign id */ + campaign: string; + }; + }; + }; + "/education": { + /** Get all education levels */ + get: operations["get-education"]; + }; + "/employments": { + /** Get all employments */ + get: operations["get-employments"]; + }; "/jotforms/forms": { get: operations["get-jotforms"]; parameters: {}; @@ -287,6 +415,15 @@ export interface paths { }; }; }; + "/jotforms/{campaign}": { + post: operations["post-jotforms-campaignId"]; + parameters: { + path: { + /** A campaign id */ + campaign: string; + }; + }; + }; "/languages": { /** Get all languages */ get: operations["get-languages"]; @@ -316,6 +453,9 @@ export interface paths { }; }; }; + "/phases": { + get: operations["get-phases"]; + }; "/popups": { /** Retrieve all available popups for admin operations */ get: operations["get-popups"]; @@ -334,6 +474,10 @@ export interface paths { }; }; }; + "/productTypes": { + get: operations["get-productTypes"]; + parameters: {}; + }; "/users": { /** Get all users you have access to */ get: operations["get-users"]; @@ -348,6 +492,14 @@ export interface paths { }; }; }; + "/users/by-role/{role}": { + get: operations["get-users-by-role-role"]; + parameters: { + path: { + role: "tester_lead" | "quality_leader" | "ux_researcher" | "assistants"; + }; + }; + }; "/users/me": { /** Get your user data */ get: operations["get-users-me"]; @@ -391,15 +543,6 @@ export interface paths { }; }; }; - "/users/me/campaigns/{campaign}/compatible_devices": { - get: operations["get-users-me-campaigns-campaignId-compatible-devices"]; - parameters: { - path: { - /** A campaign id */ - campaign: string; - }; - }; - }; "/users/me/campaigns/{campaignId}/bugs": { /** Send a user bug on a specific campaign */ post: operations["post-users-me-campaigns-campaign-bugs"]; @@ -435,6 +578,71 @@ export interface paths { }; }; }; + "/users/me/campaigns/{campaignId}/payout_data": { + get: operations["get-users-me-campaigns-cid-payout-data"]; + parameters: { + path: { + campaignId: string; + }; + }; + }; + "/users/me/campaigns/{campaignId}/preview": { + get: operations["get-users-me-campaigns-cid-preview"]; + parameters: { + path: { + campaignId: string; + }; + }; + }; + "/users/me/campaigns/{campaignId}/tasks": { + get: operations["get-users-me-campaign-campaignId-tasks"]; + parameters: { + path: { + campaignId: string; + }; + }; + }; + "/users/me/campaigns/{campaignId}/tasks/{taskId}": { + post: operations["post-users-me-campaigns-campaign-tasks-task"]; + parameters: { + path: { + /** the campaign id */ + campaignId: string; + taskId: string; + }; + }; + }; + "/users/me/campaigns/{campaignId}/tasks/{taskId}/media": { + /** Return a list of tester media uploaded on a specific Usecase of a specific Campaign */ + get: operations["get-users-me-campaigns-campaignId-tasks-taskId-media"]; + post: operations["post-users-me-campaigns-campaignId-tasks-taskId-media"]; + parameters: { + path: { + campaignId: string; + taskId: string; + }; + }; + }; + "/users/me/campaigns/{campaignId}/tasks/{taskId}/media/{mediaId}": { + /** Delete a specific media of a specific campaign task if authorized */ + delete: operations["delete-users-me-campaigns-campaignId-tasks-taskId-media-mediaId"]; + parameters: { + path: { + campaignId: string; + taskId: string; + mediaId: string; + }; + }; + }; + "/users/me/campaigns/{campaign}/compatible_devices": { + get: operations["get-users-me-campaigns-campaignId-compatible-devices"]; + parameters: { + path: { + /** A campaign id */ + campaign: string; + }; + }; + }; "/users/me/certifications": { /** Add one certification to your profile */ post: operations["post-users-me-certifications"]; @@ -541,86 +749,45 @@ export interface paths { "/users/me/rank/list": { get: operations["get-users-me-rank-list"]; }; - "/dossiers": { - post: operations["post-dossiers"]; - parameters: {}; - }; - "/dossiers/{campaign}": { - get: operations["get-dossiers-campaign"]; - put: operations["put-dossiers-campaign"]; - parameters: { - path: { - /** A campaign id */ - campaign: string; - }; - }; - }; - "/customers/{customer}/projects": { - get: operations["get-customers-customer-projects"]; - post: operations["post-customers-customer-projects"]; - parameters: { - path: { - customer: string; - }; - }; - }; - "/users/by-role/{role}": { - get: operations["get-users-by-role-role"]; - parameters: { - path: { - role: "tester_lead" | "quality_leader" | "ux_researcher" | "assistants"; - }; - }; - }; - "/browsers": { - get: operations["get-browsers"]; - }; - "/productTypes": { - get: operations["get-productTypes"]; - parameters: {}; - }; - "/phases": { - get: operations["get-phases"]; - }; - "/dossiers/{campaign}/phases": { - put: operations["put-dossiers-campaign-phases"]; - parameters: { - path: { - /** A campaign id */ - campaign: string; - }; - }; - }; } export interface components { schemas: { AdditionalField: { field_id: number; + is_candidate?: boolean; name: string; - value: string; text?: string; - is_candidate?: boolean; + value: string; }; Agreement: { - title: string; - tokens: number; - unitPrice: number; - startDate: string; expirationDate: string; - note?: string; /** @default false */ isTokenBased?: boolean; + note?: string; + startDate: string; + title: string; + tokens: number; + unitPrice: number; + }; + /** AvailableDevice */ + AvailableDevice: { + name: string; }; /** Bug */ Bug: { - severity?: components["schemas"]["BugSeverity"]; - status?: components["schemas"]["BugStatus"]; campaign?: components["schemas"]["CampaignOptional"] & { id?: number; }; + severity?: components["schemas"]["BugSeverity"]; + status?: components["schemas"]["BugStatus"]; title?: string; }; + /** + * BugLang + * @enum {string} + */ + BugLang: "IT" | "GB" | "ES" | "FR" | "DE"; /** BugSeverity */ BugSeverity: { id?: number; @@ -628,9 +795,9 @@ export interface components { }; /** BugStatus */ BugStatus: { + description?: string; id?: number; name?: string; - description?: string; }; /** BugTag */ BugTag: { @@ -645,19 +812,19 @@ export interface components { components["schemas"]["CampaignRequired"]; /** CampaignAdditionalField */ CampaignAdditionalField: { + error: string; name: string; slug: string; - error: string; } & ( | { + options: string[]; /** @enum {string} */ type: "select"; - options: string[]; } | { + regex: string; /** @enum {string} */ type: "text"; - regex: string; } ); /** CampaignField */ @@ -665,43 +832,43 @@ export interface components { id?: number; }; CampaignOptional: { - name?: string; + additionalFields?: components["schemas"]["CampaignField"][]; + allowed?: { + bug_types?: components["schemas"]["BugType"][]; + replicabilities?: components["schemas"]["Replicability"][]; + severities?: components["schemas"]["BugSeverity"][]; + }; + /** @description True if you applied on this Campaign */ + applied?: boolean; + /** @description If bugform is deactivated is a boolean else contains URLs to bugforms for each languages */ + bugform_link?: boolean | components["schemas"]["TranslatablePage"]; + /** @default 0 */ + csm_effort?: number; + customerCanViewReviewing?: boolean; customer_title?: string; - internal_id?: string; dates?: { - start?: string; - end?: string; close?: string; + end?: string; + start?: string; }; - status?: boolean; - language?: string; - public?: boolean; - hasBugParade?: boolean; devices?: { id?: string; }[]; + hasBugParade?: boolean; + internal_id?: string; + language?: string; + manual_link?: components["schemas"]["TranslatablePage"]; minNumberOfMedia?: number; - titleRule?: boolean; - allowed?: { - severities?: components["schemas"]["BugSeverity"][]; - bug_types?: components["schemas"]["BugType"][]; - replicabilities?: components["schemas"]["Replicability"][]; - }; + name?: string; + preview_link?: components["schemas"]["TranslatablePage"]; projectManager?: components["schemas"]["User"]; - customerCanViewReviewing?: boolean; - additionalFields?: components["schemas"]["CampaignField"][]; + public?: boolean; + status?: boolean; + titleRule?: boolean; /** @default 0 */ tokens?: number; /** @default 0 */ - csm_effort?: number; - /** @default 0 */ ux_effort?: number; - preview_link?: components["schemas"]["TranslatablePage"]; - manual_link?: components["schemas"]["TranslatablePage"]; - /** @description If bugform is deactivated is a boolean else contains URLs to bugforms for each languages */ - bugform_link?: boolean | components["schemas"]["TranslatablePage"]; - /** @description True if you applied on this Campaign */ - applied?: boolean; visibility?: { freeSpots?: number; totalSpots?: number; @@ -710,32 +877,39 @@ export interface components { }; }; CampaignRequired: { - name: string; + campaign_type: components["schemas"]["CampaignType"]; dates: { - start: string; - end: string; close: string; + end: string; + start: string; }; - campaign_type: components["schemas"]["CampaignType"]; + name: string; }; CampaignType: string | number; Certification: { - id?: number; - name: string; - area: string; - institute: string; /** Format: date */ achievement_date: string; + area: string; + id?: number; + institute: string; + name: string; + }; + /** CountryCode */ + CountryCode: string; + /** Currency */ + Currency: { + currency: string; + value: number; }; /** CustomUserFieldsData */ CustomUserFieldsData: { - id: number; - type: components["schemas"]["CustomUserFieldsType"]; - placeholder?: components["schemas"]["TranslatablePage"]; allow_other?: boolean; - name: components["schemas"]["TranslatablePage"]; format?: string; + id: number; + name: components["schemas"]["TranslatablePage"]; options?: components["schemas"]["CustomUserFieldsDataOption"][]; + placeholder?: components["schemas"]["TranslatablePage"]; + type: components["schemas"]["CustomUserFieldsType"]; }; /** CustomUserFieldsDataOption */ CustomUserFieldsDataOption: { @@ -747,10 +921,57 @@ export interface components { * @enum {string} */ CustomUserFieldsType: "text" | "select" | "multiselect"; - /** Currency */ - Currency: { - value: number; - currency: string; + DossierCreationData: { + additionals?: ({ + showInStats?: boolean; + } & components["schemas"]["CampaignAdditionalField"])[]; + browsers?: number[]; + bugTypes?: number[]; + /** Format: date-time */ + closeDate?: string; + countries?: components["schemas"]["CountryCode"][]; + csm?: number; + description?: string; + deviceList: number[]; + deviceRequirements?: string; + /** Format: date-time */ + endDate?: string; + goal?: string; + languages?: string[]; + notes?: string; + outOfScope?: string; + productLink?: string; + productType?: number; + project: number; + roles?: { + role: number; + user: number; + }[]; + /** Format: date-time */ + startDate: string; + target?: { + cap?: number; + genderQuote?: string; + notes?: string; + size?: number; + }; + testType: number; + title: { + customer: string; + tester?: string; + }; + visibilityCriteria?: { + ageRanges?: { + max: number; + min: number; + }[]; + cuf?: { + cufId: number; + cufValueIds: number[]; + }[]; + gender?: number[]; + provinces?: string[]; + }; }; /** FiscalBirthCity */ FiscalBirthCity: @@ -772,19 +993,34 @@ export interface components { | "non-italian" | "vat" | "company"; + /** + * Gender + * @enum {string} + */ + Gender: "male" | "female" | "not-specified" | "other"; /** LevelDefinition */ LevelDefinition: { + hold?: number; id: number; name: string; reach?: number; - hold?: number; }; /** MonthlyLevel */ MonthlyLevel: { id: number; name: string; }; + Olp: number[] | boolean; + /** PaginationData */ + PaginationData: { + limit?: number; + size: number; + start: number; + total?: number; + }; Popup: { + content?: string; + once?: boolean; profiles?: | number[] | ( @@ -794,11 +1030,8 @@ export interface components { | "logged-in-year" | "not-logged-in-year" ); - once?: boolean; - content?: string; title?: string; }; - Olp: number[] | boolean; /** PreselectionFormQuestion */ PreselectionFormQuestion: { question: string; @@ -808,30 +1041,47 @@ export interface components { type: components["schemas"]["PreselectionQuestionSimple"]; } | { - type: components["schemas"]["PreselectionQuestionMultiple"]; options?: { - value: string; isInvalid?: boolean; + value: string; }[]; + type: components["schemas"]["PreselectionQuestionMultiple"]; } | { - type: components["schemas"]["PreselectionQuestionCuf"]; options?: { - value: number; isInvalid?: boolean; + value: number; }[]; + type: components["schemas"]["PreselectionQuestionCuf"]; } ); + /** PreselectionQuestionCuf */ + PreselectionQuestionCuf: string; + /** + * PreselectionQuestionMultiple + * @enum {string} + */ + PreselectionQuestionMultiple: "multiselect" | "select" | "radio"; + /** + * PreselectionQuestionSimple + * @enum {string} + */ + PreselectionQuestionSimple: "gender" | "text" | "phone_number" | "address"; /** Project */ Project: { name?: string; }; + /** + * ProspectStatus + * @enum {string} + */ + ProspectStatus: "draft" | "confirmed" | "done"; RankingItem: { - position: number; - image: string; id: number; - name: string; + image: string; monthly_exp: number; + name: string; + position: number; }; /** Replicability */ Replicability: { @@ -841,153 +1091,86 @@ export interface components { Task: components["schemas"]["TaskOptional"] & components["schemas"]["TaskRequired"]; TaskOptional: { - name?: string; - content?: string; + allow_media?: boolean; campaign_id?: number; + content?: string; group?: number; - allow_media?: boolean; + name?: string; }; TaskRequired: { - name: string; - content: string; campaign_id: number; + content: string; + name: string; }; /** TranslatablePage */ TranslatablePage: { en?: string; - it?: string; es?: string; + it?: string; }; /** User */ User: { - username?: string; - name?: string; - surname?: string; /** Format: email */ email?: string; + id?: number; /** Format: uri */ image?: string; - id?: number; - wp_user_id?: number; - role?: string; is_verified?: boolean; + name?: string; + role?: string; + surname?: string; + username?: string; + wp_user_id?: number; }; /** UserDevice */ UserDevice: { - type: string; - id: number; device: | { + id?: number; manufacturer: string; model: string; - id?: number; } | { pc_type: string; }; + id: number; operating_system: { id: number; platform: string; version: string; }; + type: string; }; - /** - * Gender - * @enum {string} - */ - Gender: "male" | "female" | "not-specified" | "other"; - /** PaginationData */ - PaginationData: { - start: number; - limit?: number; - size: number; - total?: number; - }; - /** - * ProspectStatus - * @enum {string} - */ - ProspectStatus: "draft" | "confirmed" | "done"; - /** CountryCode */ - CountryCode: string; - DossierCreationData: { - project: number; - testType: number; - title: { - customer: string; - tester?: string; - }; - /** Format: date-time */ - startDate: string; - /** Format: date-time */ - endDate?: string; - /** Format: date-time */ - closeDate?: string; - deviceList: number[]; - csm?: number; - roles?: { - role: number; - user: number; - }[]; - description?: string; - productLink?: string; - goal?: string; - outOfScope?: string; - deviceRequirements?: string; - target?: { - notes?: string; - size?: number; - cap?: number; - }; - countries?: components["schemas"]["CountryCode"][]; - languages?: string[]; - browsers?: number[]; - productType?: number; - notes?: string; - }; - /** - * PreselectionQuestionSimple - * @enum {string} - */ - PreselectionQuestionSimple: "gender" | "text" | "phone_number" | "address"; - /** - * PreselectionQuestionMultiple - * @enum {string} - */ - PreselectionQuestionMultiple: "multiselect" | "select" | "radio"; - /** PreselectionQuestionCuf */ - PreselectionQuestionCuf: string; }; responses: { - /** A user */ - UserData: { - content: { - "application/json": components["schemas"]["User"]; - }; - }; /** Authentication data. The token can be used to authenticate the protected requests */ Authentication: { content: { "application/json": { - id?: number; + exp?: number; firstName?: string; + iat?: number; + id?: number; lastName?: string; token?: string; username?: string; - iat?: number; - exp?: number; }; }; }; - /** A single Campaigns with the Campaign id and Project data */ - SingleCampaign: { + /** An error due to missing required parameters */ + MissingParameters: { content: { - "application/json": components["schemas"]["Campaign"] & { - id: number; - } & { - project?: components["schemas"]["Project"] & { - id?: number; - }; + "application/json": { + message: string; + }; + }; + }; + /** An error due to insufficient authorization to access the resource */ + NotAuthorized: { + content: { + "application/json": { + code?: string; + message?: string; }; }; }; @@ -995,54 +1178,55 @@ export interface components { NotFound: { content: { "application/json": { + code?: string; element: string; id: number; message: string; - code?: string; }; }; }; - /** An error due to missing required parameters */ - MissingParameters: { + /** A single Campaigns with the Campaign id and Project data */ + SingleCampaign: { content: { - "application/json": { - message: string; + "application/json": components["schemas"]["Campaign"] & { + id: number; + } & { + project?: components["schemas"]["Project"] & { + id?: number; + }; }; }; }; - /** An error due to insufficient authorization to access the resource */ - NotAuthorized: { + /** A user */ + UserData: { content: { - "application/json": { - message?: string; - code?: string; - }; + "application/json": components["schemas"]["User"]; }; }; }; parameters: { /** @description A campaign id */ campaign: string; - /** @description A task id */ - task: string; /** @description A customer id */ customer: string; - /** @description A project id */ - project: string; - /** @description Max items to retrieve */ - limit: number; - /** @description Items to skip for pagination */ - start: number; /** @description Key-value Array for item filtering */ filterBy: { [key: string]: unknown }; - /** @description How to order values (ASC, DESC) */ - order: "ASC" | "DESC"; + /** @description Max items to retrieve */ + limit: number; /** @description How to localize values */ locale: "en" | "it"; - /** @description A comma separated list of fields which will be searched */ - searchBy: string; + /** @description How to order values (ASC, DESC) */ + order: "ASC" | "DESC"; + /** @description A project id */ + project: string; /** @description The value to search for */ search: string; + /** @description A comma separated list of fields which will be searched */ + searchBy: string; + /** @description Items to skip for pagination */ + start: number; + /** @description A task id */ + task: string; testerId: string; }; requestBodies: {}; @@ -1082,8 +1266,8 @@ export interface operations { id: number; } & components["schemas"]["Agreement"] & { customer: { - id: number; company: string; + id: number; }; })[]; } & components["schemas"]["PaginationData"]; @@ -1131,8 +1315,8 @@ export interface operations { id: number; } & components["schemas"]["Agreement"] & { customer: { - id: number; company: string; + id: number; }; }; }; @@ -1157,8 +1341,8 @@ export interface operations { id: number; } & components["schemas"]["Agreement"] & { customer: { - id: number; company: string; + id: number; }; }; }; @@ -1212,8 +1396,68 @@ export interface operations { requestBody: { content: { "application/json": { - username: string; password: string; + username: string; + }; + }; + }; + }; + "get-browsers": { + responses: { + /** OK */ + 200: { + content: { + "application/json": { + results: { + id: number; + name: string; + }[]; + }; + }; + }; + }; + }; + "patch-bugs-bugId-status": { + parameters: { + path: { + bugId: string; + }; + }; + responses: { + /** OK */ + 200: { + content: { + "application/json": { [key: string]: unknown }; + }; + }; + /** Forbidden */ + 403: { + content: { + "application/json": { [key: string]: unknown }; + }; + }; + }; + requestBody: { + content: { + "application/json": { + status_id: number; + }; + }; + }; + }; + "get-campaign-types": { + parameters: {}; + responses: { + 200: { + content: { + "application/json": { + customRoles: { + roleId: number; + userIds: number[]; + }[]; + id: number; + name: string; + }[]; }; }; }; @@ -1244,22 +1488,6 @@ export interface operations { content: { "application/json": { items?: { - id?: number; - name?: string; - customerTitle?: string; - startDate?: string; - endDate?: string; - /** @enum {string} */ - status?: "running" | "closed" | "incoming"; - /** @enum {string} */ - visibility?: - | "admin" - | "smallgroup" - | "logged" - | "public" - | "target"; - /** @enum {string} */ - resultType?: "bug" | "bugparade" | "no"; csm?: { id: number; name: string; @@ -1269,19 +1497,25 @@ export interface operations { id?: number; name: string; }; - type?: { + customerTitle?: string; + endDate?: string; + id?: number; + name?: string; + phase?: { + id: number; name: string; - /** @enum {string} */ - area: "quality" | "experience"; }; project?: { id?: number; name: string; }; - phase?: { + quote?: { id: number; - name: string; + price: string; + status: string; }; + /** @enum {string} */ + resultType?: "bug" | "bugparade" | "no"; roles?: { role: { id: number; @@ -1293,10 +1527,25 @@ export interface operations { surname: string; }; }[]; - }[]; - } & components["schemas"]["PaginationData"]; - }; - }; + startDate?: string; + /** @enum {string} */ + status?: "running" | "closed" | "incoming"; + type?: { + /** @enum {string} */ + area: "quality" | "experience"; + name: string; + }; + /** @enum {string} */ + visibility?: + | "admin" + | "smallgroup" + | "logged" + | "public" + | "target"; + }[]; + } & components["schemas"]["PaginationData"]; + }; + }; 403: components["responses"]["NotAuthorized"]; 404: components["responses"]["NotFound"]; }; @@ -1317,6 +1566,180 @@ export interface operations { }; }; }; + "get-campaigns-forms": { + parameters: { + query: { + /** A comma separated list of fields which will be searched */ + searchBy?: components["parameters"]["searchBy"]; + /** The value to search for */ + search?: components["parameters"]["search"]; + /** Max items to retrieve */ + limit?: components["parameters"]["limit"]; + /** Items to skip for pagination */ + start?: components["parameters"]["start"]; + }; + }; + responses: { + /** OK */ + 200: { + content: { + "application/json": { + limit?: number; + results: { + campaign?: number; + id: number; + name: string; + }[]; + size: number; + start: number; + total?: number; + }; + }; + }; + 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; + }; + }; + "post-campaigns-forms": { + parameters: {}; + responses: { + /** Created */ + 201: { + content: { + "application/json": { + campaign?: { + id: number; + name: string; + }; + fields?: ({ + id: number; + } & components["schemas"]["PreselectionFormQuestion"])[]; + id: number; + name: string; + }; + }; + }; + 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; + }; + requestBody: { + content: { + "application/json": { + campaign?: number; + creationDate?: string; + fields: components["schemas"]["PreselectionFormQuestion"][]; + name: string; + }; + }; + }; + }; + "get-campaigns-forms-formId": { + parameters: { + path: { + formId: string; + }; + }; + responses: { + /** OK */ + 200: { + content: { + "application/json": { + campaign?: { + id: number; + name: string; + }; + fields: ({ + id: number; + } & components["schemas"]["PreselectionFormQuestion"])[]; + id: number; + /** @example My form */ + name: string; + }; + }; + }; + 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; + }; + }; + "put-campaigns-forms-formId": { + parameters: { + path: { + formId: string; + }; + }; + responses: { + /** OK */ + 200: { + content: { + "application/json": { + campaign?: { + id: number; + name: string; + }; + fields: ({ + id: number; + } & components["schemas"]["PreselectionFormQuestion"])[]; + id: number; + name: string; + }; + }; + }; + 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; + }; + requestBody: { + content: { + "application/json": { + campaign?: number; + fields: ({ + id?: number; + } & components["schemas"]["PreselectionFormQuestion"])[]; + name: string; + }; + }; + }; + }; + /** Get all the owners of campaigns you have access to */ + "get-campaigns-owners": { + parameters: {}; + responses: { + /** OK */ + 200: { + content: { + "application/json": { + id: number; + name: string; + surname: string; + }[]; + }; + }; + 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; + }; + }; + "patch-campaigns-campaignId-visibility": { + parameters: { + path: { + campaignId: string; + }; + }; + responses: { + /** OK */ + 200: unknown; + 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; + /** Internal Server Error */ + 500: unknown; + }; + requestBody: { + content: { + "application/json": { + /** @enum {undefined} */ + type: "internal" | "target"; + }; + }; + }; + }; /** Get the data of a Campaign if you have access to it */ "get-campaigns-campaign": { parameters: { @@ -1331,10 +1754,14 @@ export interface operations { content: { "application/json": { id: number; + plan?: { + id: number; + name: string; + }; + preselectionFormId?: number; title: string; type: string; typeDescription: string; - preselectionFormId?: number; }; }; }; @@ -1391,29 +1818,29 @@ export interface operations { content: { "application/json": { items: { + created: string; + /** @enum {string} */ + duplication: "father" | "unique" | "duplicated"; id: number; - title: string; internalId: string; - status: { + isFavourite: boolean; + severity: { id: number; name: string; }; - type: { + status: { id: number; name: string; }; - severity: { + tags?: components["schemas"]["BugTag"][]; + tester: { id: number; - name: string; }; - tester: { + title: string; + type: { id: number; + name: string; }; - tags?: components["schemas"]["BugTag"][]; - /** @enum {string} */ - duplication: "father" | "unique" | "duplicated"; - isFavourite: boolean; - created: string; updated: string; }[]; } & components["schemas"]["PaginationData"]; @@ -1423,31 +1850,13 @@ export interface operations { 404: components["responses"]["NotFound"]; }; }; - "get-campaigns-campaign-candidates": { + /** Get single bug of a Campaign if you have access to it */ + "get-campaigns-single-bug": { parameters: { path: { /** A campaign id */ campaign: string; - }; - query: { - /** Max items to retrieve */ - limit?: components["parameters"]["limit"]; - /** Items to skip for pagination */ - start?: components["parameters"]["start"]; - /** The fields to add to the results */ - fields?: string; - /** Key-value Array for item filtering */ - filterByInclude?: unknown; - /** Key-value Array for item filtering */ - filterByExclude?: unknown; - /** Array with min and max */ - filterByAge?: unknown; - /** Show accepted/candidates or both */ - show?: - | "onlyAccepted" - | "onlyCandidates" - | "all" - | "candidatesAndExcluded"; + bugId: string; }; }; responses: { @@ -1455,26 +1864,121 @@ export interface operations { 200: { content: { "application/json": { - results?: { + actual_result: string; + description: string; + expected_result: string; + id: number; + media: { + id: number; + type: string; + url: string; + }[]; + note: string; + reason: string; + replicability: { id: number; name: string; - surname: string; - gender: components["schemas"]["Gender"]; - age: number; - experience: number; - businessCps: number; - businessCpsLastMonth: number; - levels: { - bugHunting: string; - metal: string; - }; - devices: { + }; + severity: components["schemas"]["BugSeverity"]; + status: components["schemas"]["BugStatus"]; + status_history: { + date: string; + reason: string; + status: string; + }[]; + title: string; + type: { + id: number; + name: string; + }; + usecase: { + description: string; + id: number; + title: string; + }; + }; + }; + }; + 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; + }; + }; + /** Get ai review for a single bug of a Campaign if you have access to it */ + "get-campaigns-single-bug-ai-review": { + parameters: { + path: { + /** A campaign id */ + campaign: string; + bugId: string; + }; + }; + responses: { + /** OK */ + 200: { + content: { + "application/json": { + ai_notes?: string; + ai_reason: string; + ai_status: string; + score_percentage: number; + }; + }; + }; + 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; + }; + }; + "get-campaigns-campaign-candidates": { + parameters: { + path: { + /** A campaign id */ + campaign: string; + }; + query: { + /** Max items to retrieve */ + limit?: components["parameters"]["limit"]; + /** Items to skip for pagination */ + start?: components["parameters"]["start"]; + /** The fields to add to the results */ + fields?: string; + /** Key-value Array for item filtering */ + filterByInclude?: unknown; + /** Key-value Array for item filtering */ + filterByExclude?: unknown; + /** Array with min and max */ + filterByAge?: unknown; + /** Show accepted/candidates or both */ + show?: + | "onlyAccepted" + | "onlyCandidates" + | "all" + | "candidatesAndExcluded"; + }; + }; + responses: { + /** OK */ + 200: { + content: { + "application/json": { + results?: { + age: number; + businessCps: number; + businessCpsLastMonth: number; + devices: { + id: number; manufacturer?: string; model?: string; os: string; osVersion: string; - id: number; }[]; + experience: number; + gender: components["schemas"]["Gender"]; + id: number; + levels: { + bugHunting: string; + metal: string; + }; + name: string; questions?: { id?: number; title?: string; @@ -1482,6 +1986,7 @@ export interface operations { }[]; /** @enum {string} */ status?: "candidate" | "excluded" | "selected"; + surname: string; }[]; } & components["schemas"]["PaginationData"]; }; @@ -1504,9 +2009,9 @@ export interface operations { content: { "application/json": { results: { - tester_id: number; - device?: "any" | number; campaignId?: number; + device?: "any" | number; + tester_id: number; }[]; }; }; @@ -1515,12 +2020,12 @@ export interface operations { 207: { content: { "application/json": { + invalidTesters?: number[]; results: { - tester_id: number; - device?: "any" | number; campaignId?: number; + device?: "any" | number; + tester_id: number; }[]; - invalidTesters?: number[]; }; }; }; @@ -1531,12 +2036,12 @@ export interface operations { content: { "application/json": | { - tester_id: number; device?: number | "random"; + tester_id: number; }[] | { - tester_id: number; device?: number | "random"; + tester_id: number; }; }; }; @@ -1625,22 +2130,22 @@ export interface operations { content: { "application/json": { items: { - id: number; - name: string; - time: number; - tester: { - id: number; - name: string; - }; cluster: { id: number; name: string; }; + id: number; media: { id: number; - url: string; streamUrl: string; + url: string; + }; + name: string; + tester: { + id: number; + name: string; }; + time: number; }[]; }; }; @@ -1661,20 +2166,20 @@ export interface operations { 200: { content: { "application/json": { - maxBonusBug: number; completionRule: { bugs?: number; usecases?: number; }; - testSuccess: { + maxBonusBug: number; + testFailure: { + message: string; payout: number; points: number; - message: string; }; - testFailure: { + testSuccess: { + message: string; payout: number; points: number; - message: string; }; }; }; @@ -1683,6 +2188,89 @@ export interface operations { 404: components["responses"]["NotFound"]; }; }; + "put-campaigns-campaign-payouts": { + parameters: { + path: { + /** A campaign id */ + campaign: components["parameters"]["campaign"]; + }; + }; + responses: { + /** OK */ + 200: { + content: { + "application/json": { + campaign_complete_bonus_eur?: number; + campaign_pts?: number; + critical_bug_payout?: number; + high_bug_payout?: number; + low_bug_payout?: number; + medium_bug_payout?: number; + minimum_bugs?: number; + payout_limit?: number; + percent_usecases?: number; + point_multiplier_critical?: number; + point_multiplier_high?: number; + point_multiplier_low?: number; + point_multiplier_medium?: number; + point_multiplier_perfect?: number; + point_multiplier_refused?: number; + top_tester_bonus?: number; + }; + }; + }; + 400: components["responses"]["MissingParameters"]; + 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; + }; + requestBody: { + content: { + "application/json": { + campaign_complete_bonus_eur?: number; + campaign_pts?: number; + critical_bug_payout?: number; + high_bug_payout?: number; + low_bug_payout?: number; + medium_bug_payout?: number; + minimum_bugs?: number; + payout_limit?: number; + percent_usecases?: number; + point_multiplier_critical?: number; + point_multiplier_high?: number; + point_multiplier_low?: number; + point_multiplier_medium?: number; + /** Format: float */ + point_multiplier_perfect?: number; + point_multiplier_refused?: number; + top_tester_bonus?: number; + }; + }; + }; + }; + "post-campaigns-campaign-preview": { + parameters: { + path: { + campaign: string; + }; + }; + responses: { + /** OK */ + 200: { + content: { + "application/json": { [key: string]: unknown }; + }; + }; + 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; + }; + requestBody: { + content: { + "application/json": { + content: string; + }; + }; + }; + }; "get-campaigns-campaign-prospect": { parameters: { path: { @@ -1701,38 +2289,38 @@ export interface operations { content: { "application/json": { items: { - tester: { - id: number; - name: string; - surname: string; - group: number; - }; - usecases: { - completed: number; - required: number; - }; bugs: { critical: number; high: number; - medium: number; low: number; + medium: number; }; - payout: { + experience: { completion: number; - bug: number; - refund: number; extra: number; }; - experience: { + isCompleted: boolean; + isTopTester: boolean; + note: string; + payout: { + bug: number; completion: number; extra: number; + refund: number; }; - note: string; /** @enum {string} */ status: "pending" | "done"; + tester: { + group: number; + id: number; + name: string; + surname: string; + }; + usecases: { + completed: number; + required: number; + }; weightedBugs: number; - isCompleted: boolean; - isTopTester: boolean; }[]; status: components["schemas"]["ProspectStatus"]; }; @@ -1762,24 +2350,24 @@ export interface operations { requestBody: { content: { "application/json": { - status: components["schemas"]["ProspectStatus"]; items: { - tester: { - id: number; - }; + completed: boolean; experience: { completion: number; extra: number; }; + note?: string; payout: { - completion: number; bug: number; + completion: number; extra: number; refund: number; }; - note?: string; - completed: boolean; + tester: { + id: number; + }; }[]; + status: components["schemas"]["ProspectStatus"]; }; }; }; @@ -1821,18 +2409,18 @@ export interface operations { 200: { content: { "application/json": { - payout: { + completed: boolean; + experience: { completion: number; - bugs: number; - refund: number; extra: number; }; - experience: { + note: string; + payout: { + bugs: number; completion: number; extra: number; + refund: number; }; - note: string; - completed: boolean; }; }; }; @@ -1840,18 +2428,18 @@ export interface operations { requestBody: { content: { "application/json": { - payout: { + completed: boolean; + experience: { completion: number; - bugs: number; - refund: number; extra: number; }; - experience: { + note: string; + payout: { + bugs: number; completion: number; extra: number; + refund: number; }; - note: string; - completed: boolean; }; }; }; @@ -1904,14 +2492,33 @@ export interface operations { }; responses: { /** Created */ - 201: unknown; + 201: { + content: { + "application/json": { + content: string; + id: number; + title: string; + }; + }; + }; 403: components["responses"]["NotAuthorized"]; 404: components["responses"]["NotFound"]; }; /** The data of the new UseCase to link to the Campaign */ requestBody: { content: { - "application/json": components["schemas"]["TaskOptional"]; + "application/json": { + content: string; + is_required: number; + position?: number; + prefix?: string; + title: string; + upload?: { + language: string; + /** @enum {string} */ + policy: "optimize" | "allow"; + }; + }; }; }; }; @@ -1977,26 +2584,26 @@ export interface operations { content: { "application/json": { goal: string; - usersNumber: number; - sentiments: { - id: number; - value: number; - comment: string; - cluster: { - id: number; - name: string; - }; - }[]; methodology: { + description: string; name: string; /** @enum {string} */ type: "qualitative" | "quantitative" | "quali-quantitative"; - description: string; }; questions: { id: number; name: string; }[]; + sentiments: { + cluster: { + id: number; + name: string; + }; + comment: string; + id: number; + value: number; + }[]; + usersNumber: number; visible: number; }; }; @@ -2026,37 +2633,32 @@ export interface operations { content: { "application/json": { goal?: string; - usersNumber?: number; - visible?: number; methodology?: { description: string; type: string; }; + questions?: { + id?: number; + name: string; + }[]; sentiments?: { clusterId: number; - value: number; comment: string; id?: number; + value: number; }[]; - questions?: { - name: string; - id?: number; - }[]; + usersNumber?: number; + visible?: number; }; }; }; }; - "get-campaigns-forms": { + /** Get all certificatio */ + "get-certifications": { parameters: { query: { - /** A comma separated list of fields which will be searched */ - searchBy?: components["parameters"]["searchBy"]; - /** The value to search for */ - search?: components["parameters"]["search"]; - /** Max items to retrieve */ - limit?: components["parameters"]["limit"]; - /** Items to skip for pagination */ - start?: components["parameters"]["start"]; + /** Key-value Array for item filtering */ + filterBy?: components["parameters"]["filterBy"]; }; }; responses: { @@ -2064,59 +2666,24 @@ export interface operations { 200: { content: { "application/json": { - results: { - id: number; - name: string; - campaign?: number; - }[]; - limit?: number; - start: number; - size: number; - total?: number; - }; - }; - }; - 403: components["responses"]["NotAuthorized"]; - 404: components["responses"]["NotFound"]; - }; - }; - "post-campaigns-forms": { - parameters: {}; - responses: { - /** Created */ - 201: { - content: { - "application/json": { + area: string; id: number; + institute: string; name: string; - campaign?: { - id: number; - name: string; - }; - fields?: ({ - id: number; - } & components["schemas"]["PreselectionFormQuestion"])[]; - }; + }[]; }; }; 403: components["responses"]["NotAuthorized"]; 404: components["responses"]["NotFound"]; }; - requestBody: { - content: { - "application/json": { - name: string; - fields: components["schemas"]["PreselectionFormQuestion"][]; - campaign?: number; - creationDate?: string; - }; - }; - }; }; - "get-campaigns-forms-formId": { + "get-regions": { parameters: { path: { - formId: string; + code: string; + }; + query: { + languageCode?: string; }; }; responses: { @@ -2124,127 +2691,72 @@ export interface operations { 200: { content: { "application/json": { - id: number; - /** @example My form */ name: string; - campaign?: { - id: number; - name: string; - }; - fields: ({ - id: number; - } & components["schemas"]["PreselectionFormQuestion"])[]; - }; + value: string; + }[]; }; }; - 403: components["responses"]["NotAuthorized"]; - 404: components["responses"]["NotFound"]; }; }; - "put-campaigns-forms-formId": { - parameters: { - path: { - formId: string; - }; - }; + "get-customUserFields": { + parameters: {}; responses: { /** OK */ 200: { content: { "application/json": { - id: number; - name: string; - fields: ({ - id: number; - } & components["schemas"]["PreselectionFormQuestion"])[]; - campaign?: { + fields?: components["schemas"]["CustomUserFieldsData"][]; + group: { + description?: components["schemas"]["TranslatablePage"]; id: number; - name: string; + name: components["schemas"]["TranslatablePage"]; }; - }; - }; - }; - 403: components["responses"]["NotAuthorized"]; - 404: components["responses"]["NotFound"]; - }; - requestBody: { - content: { - "application/json": { - name: string; - campaign?: number; - fields: ({ - id?: number; - } & components["schemas"]["PreselectionFormQuestion"])[]; + }[]; }; }; }; }; - /** Get all the owners of campaigns you have access to */ - "get-campaigns-owners": { + /** Get all the customers you have access to */ + "get-customers": { parameters: {}; responses: { - /** OK */ + /** An array of Customer objects */ 200: { content: { "application/json": { - id: number; - name: string; - surname: string; + id?: number; + name?: string; }[]; }; }; - 403: components["responses"]["NotAuthorized"]; - 404: components["responses"]["NotFound"]; + 403: components["responses"]["NotFound"]; }; }; - "get-campaign-types": { + "post-customers": { parameters: {}; responses: { + /** OK */ 200: { content: { "application/json": { id: number; name: string; - customRoles: { - roleId: number; - userIds: number[]; - }[]; - }[]; + }; }; }; }; - }; - /** Get all certificatio */ - "get-certifications": { - parameters: { - query: { - /** Key-value Array for item filtering */ - filterBy?: components["parameters"]["filterBy"]; - }; - }; - responses: { - /** OK */ - 200: { - content: { - "application/json": { - id: number; - name: string; - area: string; - institute: string; - }[]; + requestBody: { + content: { + "application/json": { + name: string; }; }; - 403: components["responses"]["NotAuthorized"]; - 404: components["responses"]["NotFound"]; }; }; - "get-regions": { + "get-customers-customer-projects": { parameters: { path: { - code: string; - }; - query: { - languageCode?: string; + customer: string; }; }; responses: { @@ -2252,31 +2764,21 @@ export interface operations { 200: { content: { "application/json": { - name: string; - value: string; - }[]; + results: { + id: number; + name: string; + }[]; + }; }; }; }; }; - /** Get all the customers you have access to */ - "get-customers": { - parameters: {}; - responses: { - /** An array of Customer objects */ - 200: { - content: { - "application/json": { - id?: number; - name?: string; - }[]; - }; + "post-customers-customer-projects": { + parameters: { + path: { + customer: string; }; - 403: components["responses"]["NotFound"]; }; - }; - "post-customers": { - parameters: {}; responses: { /** OK */ 200: { @@ -2296,24 +2798,6 @@ export interface operations { }; }; }; - "get-customUserFields": { - parameters: {}; - responses: { - /** OK */ - 200: { - content: { - "application/json": { - group: { - id: number; - name: components["schemas"]["TranslatablePage"]; - description?: components["schemas"]["TranslatablePage"]; - }; - fields?: components["schemas"]["CustomUserFieldsData"][]; - }[]; - }; - }; - }; - }; /** Get all model of devices with theirs manufacturers */ "get-devices-devices-type-model": { parameters: { @@ -2393,39 +2877,153 @@ export interface operations { 404: components["responses"]["NotFound"]; }; }; - /** Get all education levels */ - "get-education": { + "post-dossiers": { + parameters: {}; responses: { - /** OK */ - 200: { + /** Created */ + 201: { content: { "application/json": { id: number; - name: string; - }[]; + /** @enum {string} */ + message?: "HOOK_FAILED"; + }; + }; + }; + /** Partial Content */ + 206: { + content: { + "application/json": { + id?: number; + }; + }; + }; + }; + requestBody: { + content: { + "application/json": components["schemas"]["DossierCreationData"] & { + duplicate?: { + campaign?: number; + fields?: number; + mailMerges?: number; + pages?: number; + testers?: number; + useCases?: number; + }; + } & { + autoApply?: number; + bugLanguage?: components["schemas"]["BugLang"]; + hasBugForm?: number; + hasBugParade?: number; + /** @enum {string} */ + pageVersion?: "v1" | "v2"; + /** @default 0 */ + skipPagesAndTasks?: number; }; }; - 403: components["responses"]["NotAuthorized"]; - 404: components["responses"]["NotFound"]; }; }; - /** Get all employments */ - "get-employments": { + "get-dossiers-campaign": { + parameters: { + path: { + /** A campaign id */ + campaign: string; + }; + }; responses: { /** OK */ 200: { content: { "application/json": { + autoApply: number; + browsers?: { + id: number; + name: string; + }[]; + /** Format: date-time */ + closeDate: string; + countries?: components["schemas"]["CountryCode"][]; + csm: { + id: number; + name: string; + }; + customer: { + id: number; + name: string; + }; + description?: string; + deviceList: { + id: number; + name: string; + }[]; + deviceRequirements?: string; + /** Format: date-time */ + endDate: string; + goal?: string; id: number; - name: string; - }[]; + languages?: { + name: string; + }[]; + notes?: string; + outOfScope?: string; + phase: { + id: number; + name: string; + }; + productLink?: string; + productType?: { + id: number; + name: string; + }; + project: { + id: number; + name: string; + }; + roles?: { + role?: { + id: number; + name: string; + }; + user?: { + id: number; + name: string; + surname: string; + }; + }[]; + /** Format: date-time */ + startDate: string; + target?: { + cap?: number; + genderQuote?: string; + notes?: string; + size?: number; + }; + testType: { + id: number; + name: string; + }; + title: { + customer: string; + tester: string; + }; + visibilityCriteria?: { + ageRanges?: { + max: number; + min: number; + }[]; + cuf?: { + cufId: number; + cufValueIds: number[]; + }[]; + gender?: number[]; + province?: string[]; + }; + }; }; }; - 403: components["responses"]["NotAuthorized"]; - 404: components["responses"]["NotFound"]; }; }; - "post-jotforms-campaignId": { + "put-dossiers-campaign": { parameters: { path: { /** A campaign id */ @@ -2439,61 +3037,70 @@ export interface operations { "application/json": { [key: string]: unknown }; }; }; - /** Forbidden */ - 403: unknown; }; requestBody: { content: { - "application/json": { - formId: string; - testerIdColumn: string; + "application/json": components["schemas"]["DossierCreationData"] & { + autoApply?: number; + bugLanguage?: components["schemas"]["BugLang"] | boolean; + hasBugParade?: number; }; }; }; }; - "get-jotforms": { - parameters: {}; + /** */ + "get-dossiers-campaign-availableTesters": { + parameters: { + path: { + campaign: string; + }; + query: { + refresh?: "1" | "0"; + }; + }; responses: { /** OK */ 200: { content: { "application/json": { - id: string; - name: string; - createdAt: string; - }[]; + count: number; + /** Format: date-time */ + lastUpdate: string; + }; }; }; - /** Forbidden */ - 403: unknown; }; }; - "get-jotforms-forms-formId-questions": { + "post-dossiers-campaign-manual": { parameters: { path: { - formId: string; + /** A campaign id */ + campaign: components["parameters"]["campaign"]; }; }; responses: { /** OK */ 200: { content: { - "application/json": { - id: string; - name: string; - title: string; - description?: string; - type: string; - }[]; + "application/json": { [key: string]: unknown }; + }; + }; + }; + requestBody: { + content: { + "application/json": { + importFrom: number; }; }; - /** Forbidden */ - 403: unknown; }; }; - /** Get all languages */ - "get-languages": { - parameters: {}; + "put-dossiers-campaign-phases": { + parameters: { + path: { + /** A campaign id */ + campaign: string; + }; + }; responses: { /** OK */ 200: { @@ -2501,83 +3108,311 @@ export interface operations { "application/json": { id: number; name: string; - }[]; + }; + }; + }; + }; + requestBody: { + content: { + "application/json": { + phase: number; }; }; - 403: components["responses"]["NotAuthorized"]; - 404: components["responses"]["NotFound"]; }; }; - /** Get all levels */ - "get-levels": { - parameters: {}; + "post-dossiers-campaign-preview": { + parameters: { + path: { + /** A campaign id */ + campaign: components["parameters"]["campaign"]; + }; + }; responses: { /** OK */ 200: { content: { - "application/json": components["schemas"]["LevelDefinition"][]; + "application/json": { [key: string]: unknown }; + }; + }; + }; + requestBody: { + content: { + "application/json": { + importFrom: number; }; }; - 403: components["responses"]["NotAuthorized"]; - 404: components["responses"]["NotFound"]; }; }; - /** Send a media for my bug to AppQuality Bucket. */ - "post-media": { - parameters: {}; + "post-dossiers-campaign-quotations": { + parameters: { + path: { + /** A campaign id */ + campaign: string; + }; + }; responses: { - /** OK */ - 200: { + /** Created */ + 201: { content: { "application/json": { - files: { - name: string; - path: string; - }[]; - failed?: { - name: string; - errorCode: string; - }[]; + id?: number; }; }; }; + /** Not Found */ + 404: unknown; }; requestBody: { content: { - "multipart/form-data": { - media?: string | string[]; + "application/json": { + notes?: string; + quote?: string; }; }; }; }; - "delete-media": { - parameters: {}; + "patch-dossiers-campaign-quotations-quote": { + parameters: { + path: { + /** A campaign id */ + campaign: string; + quote: string; + }; + }; responses: { /** OK */ - 200: unknown; + 200: { + content: { + "application/json": { [key: string]: unknown }; + }; + }; + 403: components["responses"]["NotAuthorized"]; 404: components["responses"]["NotFound"]; }; requestBody: { content: { "application/json": { - /** Format: uri */ - url: string; + amount?: string; }; }; }; }; - "get-payments": { + "get-dossiers-campaign-quotes-history": { parameters: { - query: { - /** The status of the payment */ - status?: "pending" | "failed"; - /** How to order values (ASC, DESC) */ - order?: components["parameters"]["order"]; - /** The value to order by */ - orderBy?: "created" | "updated" | "id"; - /** Items to skip for pagination */ - start?: components["parameters"]["start"]; - /** Max items to retrieve */ + path: { + /** A campaign id */ + campaign: string; + }; + }; + responses: { + /** OK */ + 200: { + content: { + "application/json": { + items: { + campaign: { + id: number; + phase_id: number; + phase_name: string; + title: string; + }; + quote: { + amount: string; + id: number; + /** @enum {string} */ + status: "pending" | "proposed" | "approved" | "rejected"; + }; + }[]; + }; + }; + }; + }; + }; + /** Get all education levels */ + "get-education": { + responses: { + /** OK */ + 200: { + content: { + "application/json": { + id: number; + name: string; + }[]; + }; + }; + 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; + }; + }; + /** Get all employments */ + "get-employments": { + responses: { + /** OK */ + 200: { + content: { + "application/json": { + id: number; + name: string; + }[]; + }; + }; + 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; + }; + }; + "get-jotforms": { + parameters: {}; + responses: { + /** OK */ + 200: { + content: { + "application/json": { + createdAt: string; + id: string; + name: string; + }[]; + }; + }; + /** Forbidden */ + 403: unknown; + }; + }; + "get-jotforms-forms-formId-questions": { + parameters: { + path: { + formId: string; + }; + }; + responses: { + /** OK */ + 200: { + content: { + "application/json": { + description?: string; + id: string; + name: string; + title: string; + type: string; + }[]; + }; + }; + /** Forbidden */ + 403: unknown; + }; + }; + "post-jotforms-campaignId": { + parameters: { + path: { + /** A campaign id */ + campaign: string; + }; + }; + responses: { + /** OK */ + 200: { + content: { + "application/json": { [key: string]: unknown }; + }; + }; + /** Forbidden */ + 403: unknown; + }; + requestBody: { + content: { + "application/json": { + formId: string; + testerIdColumn: string; + }; + }; + }; + }; + /** Get all languages */ + "get-languages": { + parameters: {}; + responses: { + /** OK */ + 200: { + content: { + "application/json": { + id: number; + name: string; + }[]; + }; + }; + 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; + }; + }; + /** Get all levels */ + "get-levels": { + parameters: {}; + responses: { + /** OK */ + 200: { + content: { + "application/json": components["schemas"]["LevelDefinition"][]; + }; + }; + 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; + }; + }; + /** Send a media for my bug to AppQuality Bucket. */ + "post-media": { + parameters: {}; + responses: { + /** OK */ + 200: { + content: { + "application/json": { + failed?: { + errorCode: string; + name: string; + }[]; + files: { + name: string; + path: string; + }[]; + }; + }; + }; + }; + requestBody: { + content: { + "multipart/form-data": { + media?: string | string[]; + }; + }; + }; + }; + "delete-media": { + parameters: {}; + responses: { + /** OK */ + 200: unknown; + 404: components["responses"]["NotFound"]; + }; + requestBody: { + content: { + "application/json": { + /** Format: uri */ + url: string; + }; + }; + }; + }; + "get-payments": { + parameters: { + query: { + /** The status of the payment */ + status?: "pending" | "failed"; + /** How to order values (ASC, DESC) */ + order?: components["parameters"]["order"]; + /** The value to order by */ + orderBy?: "created" | "updated" | "id"; + /** Items to skip for pagination */ + start?: components["parameters"]["start"]; + /** Max items to retrieve */ limit?: components["parameters"]["limit"]; /** Key-value Array for item filtering */ filterBy?: components["parameters"]["filterBy"]; @@ -2588,29 +3423,29 @@ export interface operations { 200: { content: { "application/json": { - limit?: number; - size: number; - start: number; - total?: number; items: { - /** @description The timestamp (GMT) of the request creation */ - created: string; - /** @description The timestamp (GMT) of the request last update */ - updated: string; - id: number; amount: { - value: number; currency: string; + value: number; }; - /** @enum {string} */ - type: "paypal" | "transferwise"; + /** @description The timestamp (GMT) of the request creation */ + created: string; + error?: string; + id: number; tryber: { id: number; name: string; surname: string; }; - error?: string; + /** @enum {string} */ + type: "paypal" | "transferwise"; + /** @description The timestamp (GMT) of the request last update */ + updated: string; }[]; + limit?: number; + size: number; + start: number; + total?: number; }; }; }; @@ -2681,6 +3516,25 @@ export interface operations { 404: components["responses"]["NotFound"]; }; }; + "get-phases": { + responses: { + /** OK */ + 200: { + content: { + "application/json": { + results: { + id: number; + name: string; + type: { + id: number; + name: string; + }; + }[]; + }; + }; + }; + }; + }; /** Retrieve all available popups for admin operations */ "get-popups": { parameters: { @@ -2767,9 +3621,25 @@ export interface operations { }; }; }; - /** Get all users you have access to */ - "get-users": { - responses: { + "get-productTypes": { + parameters: {}; + responses: { + /** OK */ + 200: { + content: { + "application/json": { + results: { + id: number; + name: string; + }[]; + }; + }; + }; + }; + }; + /** Get all users you have access to */ + "get-users": { + responses: { /** OK */ 200: { content: { @@ -2801,19 +3671,19 @@ export interface operations { requestBody: { content: { "application/json": { - name: string; - surname: string; + /** Format: date */ + birthDate: string; + country: string; /** Format: email */ email: string; + name: string; password: string; - country: string; - /** Format: date */ - birthDate: string; /** * @description A referral code (formatted as TESTER_ID-CAMPAIGN_ID) * @example 555-1234 */ referral?: string; + surname: string; }; }; }; @@ -2833,6 +3703,27 @@ export interface operations { 404: unknown; }; }; + "get-users-by-role-role": { + parameters: { + path: { + role: "tester_lead" | "quality_leader" | "ux_researcher" | "assistants"; + }; + }; + responses: { + /** OK */ + 200: { + content: { + "application/json": { + results: { + id: number; + name: string; + surname: string; + }[]; + }; + }; + }; + }; + }; /** Get your user data */ "get-users-me": { parameters: { @@ -2846,53 +3737,53 @@ export interface operations { 200: { content: { "application/json": { - username?: string; - name?: string; - surname?: string; - /** Format: email */ - email?: string; - image?: string; - id: number; - wp_user_id?: number; - role?: string; - is_verified?: boolean; - rank?: string; - total_exp_pts?: number; + additional?: components["schemas"]["AdditionalField"][]; + approved_bugs?: number; + attended_cp?: number; + /** Format: date */ + birthDate?: string; booty?: { - net?: components["schemas"]["Currency"]; gross: components["schemas"]["Currency"]; - }; - pending_booty?: { net?: components["schemas"]["Currency"]; - gross: components["schemas"]["Currency"]; }; + booty_threshold?: { + isOver: boolean; + value: number; + }; + certifications?: components["schemas"]["Certification"][] | boolean; + city?: string; + completionPercent?: number; + country?: string; + education?: { + id: number; + name: string; + }; + /** Format: email */ + email?: string; + gender?: components["schemas"]["Gender"]; + id: number; + image?: string; + is_verified?: boolean; languages?: { name?: string; }[]; + name?: string; onboarding_completed?: boolean; - additional?: components["schemas"]["AdditionalField"][]; - gender?: components["schemas"]["Gender"]; - /** Format: date */ - birthDate?: string; - phone?: string; - education?: { - id: number; - name: string; + pending_booty?: { + gross: components["schemas"]["Currency"]; + net?: components["schemas"]["Currency"]; }; + phone?: string; profession?: { id: number; name: string; }; - certifications?: components["schemas"]["Certification"][] | boolean; - completionPercent?: number; - country?: string; - city?: string; - attended_cp?: number; - approved_bugs?: number; - booty_threshold?: { - value: number; - isOver: boolean; - }; + rank?: string; + role?: string; + surname?: string; + total_exp_pts?: number; + username?: string; + wp_user_id?: number; }; }; }; @@ -2911,10 +3802,10 @@ export interface operations { requestBody: { content: { "application/json": { + email?: string; name?: string; - surname?: string; password?: string; - email?: string; + surname?: string; }; }; }; @@ -2940,50 +3831,50 @@ export interface operations { 200: { content: { "application/json": { - username?: string; - name?: string; - surname?: string; - email?: string; - image?: string; - id: number; - wp_user_id?: number; - role?: string; - is_verified?: boolean; - rank?: string; - total_exp_pts?: number; + additional?: components["schemas"]["AdditionalField"][]; + approved_bugs?: number; + attended_cp?: number; + /** Format: date */ + birthDate?: string; booty?: { gross: components["schemas"]["Currency"]; net?: components["schemas"]["Currency"]; }; - pending_booty?: { - gross: components["schemas"]["Currency"]; - net?: components["schemas"]["Currency"]; + certifications?: components["schemas"]["Certification"][] | boolean; + city?: string; + completionPercent?: number; + country?: string; + education?: { + id: number; + name: string; }; + email?: string; + /** @enum {string} */ + gender?: "male" | "female" | "not-specified" | "other"; + id: number; + image?: string; + is_verified?: boolean; languages?: { id?: number; name?: string; }[]; + name?: string; onboarding_completed?: boolean; - additional?: components["schemas"]["AdditionalField"][]; - /** @enum {string} */ - gender?: "male" | "female" | "not-specified" | "other"; - /** Format: date */ - birthDate?: string; - phone?: string; - education?: { - id: number; - name: string; + pending_booty?: { + gross: components["schemas"]["Currency"]; + net?: components["schemas"]["Currency"]; }; + phone?: string; profession?: { id: number; name: string; }; - certifications?: components["schemas"]["Certification"][] | boolean; - completionPercent?: number; - country?: string; - city?: string; - attended_cp?: number; - approved_bugs?: number; + rank?: string; + role?: string; + surname?: string; + total_exp_pts?: number; + username?: string; + wp_user_id?: number; }; }; }; @@ -2994,21 +3885,21 @@ export interface operations { requestBody: { content: { "application/json": { - name?: string; + birthDate?: string; + city?: string; + country?: string; + education?: number; /** Format: email */ email?: string; - onboarding_completed?: boolean; - surname?: string; /** @enum {string} */ gender?: "male" | "female" | "not-specified" | "other"; - birthDate?: string; + name?: string; + oldPassword?: string; + onboarding_completed?: boolean; + password?: string; phone?: string; - education?: number; profession?: number; - country?: string; - city?: string; - password?: string; - oldPassword?: string; + surname?: string; }; }; }; @@ -3037,12 +3928,12 @@ export interface operations { content: { "application/json": | { - value: string; is_candidate?: boolean; + value: string; }[] | { - value: string; is_candidate?: boolean; + value: string; }; }; }; @@ -3068,10 +3959,10 @@ export interface operations { 200: { content: { "application/json": { + limit?: number; results: ({ id: number; } & components["schemas"]["Bug"])[]; - limit?: number; size?: number; start?: number; total?: number; @@ -3117,10 +4008,10 @@ export interface operations { 200: { content: { "application/json": { + limit?: number; results?: ({ id: number; } & components["schemas"]["Campaign"])[]; - limit?: number; size?: number; start?: number; total?: number; @@ -3144,65 +4035,55 @@ export interface operations { 200: { content: { "application/json": { - id: number; - title: string; - language?: { - code: string; - message: string; - }; - titleRule?: boolean; - minimumMedia: number; - useCases: { - id: number; - name: string; - }[]; additionalFields?: components["schemas"]["CampaignAdditionalField"][]; - bugTypes: { - valid: string[]; + bugReplicability: { invalid: string[]; + valid: string[]; }; bugSeverity: { - valid: string[]; invalid: string[]; - }; - bugReplicability: { valid: string[]; + }; + bugTypes: { invalid: string[]; + valid: string[]; + }; + campaign_type: { + icon: string; + id: number; + name: string; }; - hasBugForm: boolean; devices?: ({ id: number; } & components["schemas"]["UserDevice"])[]; + end_date: string; + goal: string; + hasBugForm: boolean; + hasBugParade: number; + id: number; + language?: { + code: string; + message: string; + }; + minimumMedia: number; + title: string; + titleRule?: boolean; + useCases: { + id: number; + name: string; + }[]; validFileExtensions: string[]; }; }; }; }; }; - "get-users-me-campaigns-campaignId-compatible-devices": { + /** Send a user bug on a specific campaign */ + "post-users-me-campaigns-campaign-bugs": { parameters: { path: { - /** A campaign id */ - campaign: string; - }; - }; - responses: { - /** OK */ - 200: { - content: { - "application/json": components["schemas"]["UserDevice"][]; - }; - }; - 403: components["responses"]["NotAuthorized"]; - 404: components["responses"]["NotFound"]; - }; - }; - /** Send a user bug on a specific campaign */ - "post-users-me-campaigns-campaign-bugs": { - parameters: { - path: { - /** the campaign id */ - campaignId: string; + /** the campaign id */ + campaignId: string; }; }; responses: { @@ -3210,37 +4091,28 @@ export interface operations { 200: { content: { "application/json": { + additional?: { + slug: string; + value: string; + }[]; + current: string; + description: string; + device: components["schemas"]["UserDevice"]; + expected: string; id: number; internalId?: string; - testerId: number; - title: string; - description: string; + media: string[]; + notes: string; /** @enum {string} */ - status: "PENDING" | "APPROVED" | "REFUSED" | "NEED-REVIEW"; - expected: string; - current: string; + replicability: "ONCE" | "SOMETIMES" | "ALWAYS"; /** @enum {string} */ severity: "LOW" | "MEDIUM" | "HIGH" | "CRITICAL"; /** @enum {string} */ - replicability: "ONCE" | "SOMETIMES" | "ALWAYS"; - /** @enum {string} */ - type: - | "CRASH" - | "GRAPHIC" - | "MALFUNCTION" - | "OTHER" - | "PERFORMANCE" - | "SECURITY" - | "TYPO" - | "USABILITY"; - notes: string; + status: "PENDING" | "APPROVED" | "REFUSED" | "NEED-REVIEW"; + testerId: number; + title: string; + type: string; usecase: string; - device: components["schemas"]["UserDevice"]; - media: string[]; - additional?: { - slug: string; - value: string; - }[]; }; }; }; @@ -3250,33 +4122,24 @@ export interface operations { requestBody: { content: { "application/json": { - title: string; + additional?: { + slug: string; + value: string; + }[]; + current: string; description: string; + device: number; expected: string; - current: string; - /** @enum {string} */ - severity: "LOW" | "MEDIUM" | "HIGH" | "CRITICAL"; + lastSeen: string; + media: string[]; + notes: string; /** @enum {string} */ replicability: "ONCE" | "SOMETIMES" | "ALWAYS"; /** @enum {string} */ - type: - | "CRASH" - | "GRAPHIC" - | "MALFUNCTION" - | "OTHER" - | "PERFORMANCE" - | "SECURITY" - | "TYPO" - | "USABILITY"; - notes: string; - lastSeen: string; + severity: "LOW" | "MEDIUM" | "HIGH" | "CRITICAL"; + title: string; + type: string; usecase: number; - device: number; - media: string[]; - additional?: { - slug: string; - value: string; - }[]; }; }; }; @@ -3309,8 +4172,13 @@ export interface operations { 200: { content: { "application/json": ({ + id: number; question: string; short_name?: string; + validation?: { + error?: string; + regex: string; + }; value?: | number | { @@ -3319,22 +4187,17 @@ export interface operations { } | number[] | string; - validation?: { - regex: string; - error?: string; - }; - id: number; } & ( | { type: components["schemas"]["PreselectionQuestionSimple"]; } | { - type: components["schemas"]["PreselectionQuestionMultiple"]; options: string[]; + type: components["schemas"]["PreselectionQuestionMultiple"]; } | { - type: components["schemas"]["PreselectionQuestionCuf"]; options?: number[]; + type: components["schemas"]["PreselectionQuestionCuf"]; } ))[]; }; @@ -3358,7 +4221,9 @@ export interface operations { requestBody: { content: { "application/json": { + device?: number[]; form?: { + question: number; value: { id?: number | number[]; serialized?: @@ -3369,9 +4234,7 @@ export interface operations { country: string; }; }; - question: number; }[]; - device?: number[]; }; }; }; @@ -3387,17 +4250,17 @@ export interface operations { 200: { content: { "application/json": { - files?: { - name: string; - path: string; - }[]; failed?: { - name: string; /** @enum {string} */ errorCode: | "FILE_TOO_BIG" | "INVALID_FILE_EXTENSION" | "GENERIC_ERROR"; + name: string; + }[]; + files?: { + name: string; + path: string; }[]; }; }; @@ -3411,41 +4274,44 @@ export interface operations { }; }; }; - /** Add one certification to your profile */ - "post-users-me-certifications": { + "get-users-me-campaigns-cid-payout-data": { + parameters: { + path: { + campaignId: string; + }; + }; responses: { - /** Created */ - 201: { + /** OK */ + 200: { content: { - "application/json": - | components["schemas"]["Certification"] - | { - message: string; - }; + "application/json": { + campaign_complete_bonus_eur: number; + campaign_pts: number; + critical_bug_payout: number; + high_bug_payout: number; + low_bug_payout: number; + medium_bug_payout: number; + minimum_bugs: number; + payout_limit: number; + percent_usecases: number; + point_multiplier_critical: number; + point_multiplier_high: number; + point_multiplier_low: number; + point_multiplier_medium: number; + point_multiplier_perfect: number; + point_multiplier_refused: number; + top_tester_bonus: number; + }; }; }; 403: components["responses"]["NotAuthorized"]; - }; - requestBody: { - content: { - "application/json": - | { - certifications: boolean; - } - | { - certification_id: number; - /** Format: date */ - achievement_date: string; - }; - }; + 404: components["responses"]["NotFound"]; }; }; - /** The certification will be removed */ - "delete-users-me-certifications-certificationId": { + "get-users-me-campaigns-cid-preview": { parameters: { path: { - /** The id of the certification */ - certificationId: number; + campaignId: string; }; }; responses: { @@ -3453,7 +4319,39 @@ export interface operations { 200: { content: { "application/json": { - message?: string; + acceptedDevices: { + console?: components["schemas"]["AvailableDevice"][] | "all"; + pc?: components["schemas"]["AvailableDevice"][] | "all"; + smartTv?: components["schemas"]["AvailableDevice"][] | "all"; + smartphone?: components["schemas"]["AvailableDevice"][] | "all"; + smartwatch?: components["schemas"]["AvailableDevice"][] | "all"; + tablet?: components["schemas"]["AvailableDevice"][] | "all"; + }; + cap?: { + free: number; + value: number; + }; + content: string; + endDate: string; + /** @enum {string} */ + selectionStatus?: + | "starting" + | "excluded" + | "ready" + | "complete" + | "not-started"; + startDate: string; + /** @enum {string} */ + status: "available" | "applied" | "excluded" | "selected"; + title: string; + tl?: { + email: string; + name: string; + }; + type: { + icon: string; + name: string; + }; }; }; }; @@ -3461,58 +4359,60 @@ export interface operations { 404: components["responses"]["NotFound"]; }; }; - /** Get all your device data */ - "get-users-me-devices": { + "get-users-me-campaign-campaignId-tasks": { + parameters: { + path: { + campaignId: string; + }; + }; responses: { /** OK */ 200: { content: { - "application/json": ({ - id?: number; - } & components["schemas"]["UserDevice"] & { - [key: string]: unknown; - })[]; + "application/json": { + can_upload_media: boolean; + content: string; + id: number; + is_required: number; + name: string; + /** @enum {string} */ + status: "completed" | "pending"; + }[]; }; }; 403: components["responses"]["NotAuthorized"]; 404: components["responses"]["NotFound"]; }; }; - /** Add a new device to your user */ - "post-users-me-devices": { - responses: { - /** Created */ - 201: { - content: { - "application/json": { - id?: number; - } & components["schemas"]["UserDevice"]; - }; + "post-users-me-campaigns-campaign-tasks-task": { + parameters: { + path: { + /** the campaign id */ + campaignId: string; + taskId: string; }; + }; + responses: { + /** OK */ + 200: unknown; 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; }; requestBody: { content: { "application/json": { - device: - | number - | ( - | "Notebook" - | "Desktop" - | "Ultrabook" - | "Gaming PC" - | "Tablet PC / Hybrid" - ); - operating_system: number; + /** @enum {undefined} */ + status: "completed"; }; }; }; }; - /** Retrieve a single device */ - "get-users-me-devices-deviceId": { + /** Return a list of tester media uploaded on a specific Usecase of a specific Campaign */ + "get-users-me-campaigns-campaignId-tasks-taskId-media": { parameters: { path: { - deviceId: number; + campaignId: string; + taskId: string; }; }; responses: { @@ -3520,19 +4420,22 @@ export interface operations { 200: { content: { "application/json": { - id?: number; - } & components["schemas"]["UserDevice"]; + items: { + id: number; + location: string; + name: string; + }[]; + }; }; }; 403: components["responses"]["NotAuthorized"]; - 404: components["responses"]["NotFound"]; }; }; - /** The device will be disabled and won't be available for selections and bugs submission. You can't remove a device currently involved in a campaign */ - "delete-users-me-devices-deviceId": { + "post-users-me-campaigns-campaignId-tasks-taskId-media": { parameters: { path: { - deviceId: number; + campaignId: string; + taskId: string; }; }; responses: { @@ -3540,47 +4443,239 @@ export interface operations { 200: { content: { "application/json": { - message?: string; + failed?: { + /** @enum {string} */ + errorCode: + | "FILE_TOO_BIG" + | "INVALID_FILE_EXTENSION" + | "GENERIC_ERROR"; + name: string; + }[]; + files?: { + name: string; + path: string; + }[]; }; }; }; - 403: components["responses"]["NotAuthorized"]; - 404: components["responses"]["NotFound"]; + }; + requestBody: { + content: { + "multipart/form-data": { + media?: string | string[]; + }; + }; }; }; - /** You can change only operating system version */ - "patch-users-me-devices-deviceId": { + /** Delete a specific media of a specific campaign task if authorized */ + "delete-users-me-campaigns-campaignId-tasks-taskId-media-mediaId": { parameters: { path: { - deviceId: number; + campaignId: string; + taskId: string; + mediaId: string; }; }; responses: { /** OK */ 200: { content: { - "application/json": { - id?: number; - } & components["schemas"]["UserDevice"]; - }; - }; - /** Not Modified */ - 304: { - content: { - "application/json": { - id?: number; - } & components["schemas"]["UserDevice"]; + "application/json": { [key: string]: unknown }; }; }; - 403: components["responses"]["NotAuthorized"]; + /** Forbidden */ + 403: unknown; 404: components["responses"]["NotFound"]; }; - requestBody: { - content: { - "application/json": { - operating_system: number; - }; - }; + }; + "get-users-me-campaigns-campaignId-compatible-devices": { + parameters: { + path: { + /** A campaign id */ + campaign: string; + }; + }; + responses: { + /** OK */ + 200: { + content: { + "application/json": components["schemas"]["UserDevice"][]; + }; + }; + 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; + }; + }; + /** Add one certification to your profile */ + "post-users-me-certifications": { + responses: { + /** Created */ + 201: { + content: { + "application/json": + | components["schemas"]["Certification"] + | { + message: string; + }; + }; + }; + 403: components["responses"]["NotAuthorized"]; + }; + requestBody: { + content: { + "application/json": + | { + certifications: boolean; + } + | { + /** Format: date */ + achievement_date: string; + certification_id: number; + }; + }; + }; + }; + /** The certification will be removed */ + "delete-users-me-certifications-certificationId": { + parameters: { + path: { + /** The id of the certification */ + certificationId: number; + }; + }; + responses: { + /** OK */ + 200: { + content: { + "application/json": { + message?: string; + }; + }; + }; + 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; + }; + }; + /** Get all your device data */ + "get-users-me-devices": { + responses: { + /** OK */ + 200: { + content: { + "application/json": ({ + id?: number; + } & components["schemas"]["UserDevice"] & { + [key: string]: unknown; + })[]; + }; + }; + 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; + }; + }; + /** Add a new device to your user */ + "post-users-me-devices": { + responses: { + /** Created */ + 201: { + content: { + "application/json": { + id?: number; + } & components["schemas"]["UserDevice"]; + }; + }; + 403: components["responses"]["NotAuthorized"]; + }; + requestBody: { + content: { + "application/json": { + device: + | number + | ( + | "Notebook" + | "Desktop" + | "Ultrabook" + | "Gaming PC" + | "Tablet PC / Hybrid" + ); + operating_system: number; + }; + }; + }; + }; + /** Retrieve a single device */ + "get-users-me-devices-deviceId": { + parameters: { + path: { + deviceId: number; + }; + }; + responses: { + /** OK */ + 200: { + content: { + "application/json": { + id?: number; + } & components["schemas"]["UserDevice"]; + }; + }; + 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; + }; + }; + /** The device will be disabled and won't be available for selections and bugs submission. You can't remove a device currently involved in a campaign */ + "delete-users-me-devices-deviceId": { + parameters: { + path: { + deviceId: number; + }; + }; + responses: { + /** OK */ + 200: { + content: { + "application/json": { + message?: string; + }; + }; + }; + 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; + }; + }; + /** You can change only operating system version */ + "patch-users-me-devices-deviceId": { + parameters: { + path: { + deviceId: number; + }; + }; + responses: { + /** OK */ + 200: { + content: { + "application/json": { + id?: number; + } & components["schemas"]["UserDevice"]; + }; + }; + /** Not Modified */ + 304: { + content: { + "application/json": { + id?: number; + } & components["schemas"]["UserDevice"]; + }; + }; + 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; + }; + requestBody: { + content: { + "application/json": { + operating_system: number; + }; + }; }; }; /** Get all the experience points earned in AppQuality. */ @@ -3608,27 +4703,27 @@ export interface operations { 200: { content: { "application/json": { + limit?: number; results: { - id: number; activity: { id: number; }; + amount: number; campaign: { id: number; title?: string; }; /** Format: date */ date: string; - amount: number; + id: number; note?: string; }[]; - limit?: number; size?: number; start?: number; - /** @description The total number of experience entries */ - total?: number; /** @description The total sum of experience */ sum: number; + /** @description The total number of experience entries */ + total?: number; }; }; }; @@ -3644,14 +4739,13 @@ export interface operations { content: { "application/json": { address: { + city: string; + cityCode: string; country: string; province: string; - city: string; street: string; streetNumber?: string; - cityCode: string; }; - type: components["schemas"]["FiscalType"] | "internal"; birthPlace: { city?: string; province?: string; @@ -3661,6 +4755,7 @@ export interface operations { fiscalStatus: "Verified" | "Unverified"; /** @enum {string} */ gender: "male" | "female"; + type: components["schemas"]["FiscalType"] | "internal"; }; }; }; @@ -3676,14 +4771,13 @@ export interface operations { content: { "application/json": { address: { + city: string; + cityCode: string; country: string; province: string; - city: string; street: string; streetNumber?: string; - cityCode: string; }; - type: components["schemas"]["FiscalType"]; birthPlace?: { city?: string; province?: string; @@ -3693,6 +4787,7 @@ export interface operations { fiscalStatus: "Verified" | "Unverified"; /** @enum {string} */ gender: "male" | "female"; + type: components["schemas"]["FiscalType"]; }; }; }; @@ -3702,18 +4797,18 @@ export interface operations { content: { "application/json": { address: { + city: string; + cityCode: string; country: string; province: string; - city: string; street: string; streetNumber: string; - cityCode: string; }; - type: components["schemas"]["FiscalType"]; birthPlace?: components["schemas"]["FiscalBirthCity"]; fiscalId: string; /** @enum {string} */ gender: "male" | "female"; + type: components["schemas"]["FiscalType"]; }; }; }; @@ -3726,14 +4821,13 @@ export interface operations { content: { "application/json": { address: { + city: string; + cityCode: string; country: string; province: string; - city: string; street: string; streetNumber?: string; - cityCode: string; }; - type: components["schemas"]["FiscalType"]; birthPlace?: { city?: string; province?: string; @@ -3743,6 +4837,7 @@ export interface operations { fiscalStatus: "Verified" | "Unverified"; /** @enum {string} */ gender: "male" | "female"; + type: components["schemas"]["FiscalType"]; }; }; }; @@ -3752,18 +4847,18 @@ export interface operations { content: { "application/json": { address: { + city: string; + cityCode: string; country: string; province: string; - city: string; street: string; streetNumber: string; - cityCode: string; }; - type: components["schemas"]["FiscalType"]; birthPlace?: components["schemas"]["FiscalBirthCity"]; fiscalId: string; /** @enum {string} */ gender: "male" | "female"; + type: components["schemas"]["FiscalType"]; }; }; }; @@ -3799,462 +4894,48 @@ export interface operations { }; }; 403: components["responses"]["NotAuthorized"]; - }; - requestBody: { - content: { - "application/json": { - language_name?: string; - }; - }; - }; - }; - /** The language will be removed from your profile */ - "delete-users-me-languages-languageId": { - parameters: { - path: { - /** The id of the language */ - languageId: number; - }; - }; - responses: { - /** OK */ - 200: { - content: { - "application/json": { - message?: string; - }; - }; - }; - 403: components["responses"]["NotAuthorized"]; - 404: components["responses"]["NotFound"]; - }; - }; - /** Return all payment requests */ - "get-users-me-payments": { - parameters: { - query: { - /** Items to skip for pagination */ - start?: components["parameters"]["start"]; - /** Max items to retrieve */ - limit?: components["parameters"]["limit"]; - /** The field for item order */ - orderBy?: string; - /** How to order values (ASC, DESC) */ - order?: components["parameters"]["order"]; - }; - }; - responses: { - /** OK */ - 200: { - content: { - "application/json": { - results?: ({ - id: number; - } & { - /** @enum {string} */ - status: "paid" | "processing"; - amount: { - net: components["schemas"]["Currency"]; - gross: components["schemas"]["Currency"]; - }; - paidDate: string; - method: { - /** @enum {string} */ - type: "paypal" | "iban"; - note: string; - }; - /** Format: uri-reference */ - receipt?: string; - })[]; - limit?: number; - size: number; - start: number; - total?: number; - }; - }; - }; - 403: components["responses"]["NotAuthorized"]; - 404: components["responses"]["NotFound"]; - }; - }; - "post-users-me-payments": { - parameters: {}; - responses: { - /** OK */ - 200: { - content: { - "application/json": { - id?: number; - amount?: number; - }; - }; - }; - 403: components["responses"]["NotAuthorized"]; - }; - requestBody: { - content: { - "application/json": { - method: - | { - /** @enum {string} */ - type: "paypal"; - email: string; - } - | { - /** @enum {string} */ - type: "iban"; - accountHolderName: string; - iban: string; - }; - }; - }; - }; - }; - /** Return all attributions of a specific request */ - "get-users-me-payments-payment": { - parameters: { - path: { - payment: string; - }; - query: { - /** Max items to retrieve */ - limit?: components["parameters"]["limit"]; - /** Items to skip for pagination */ - start?: components["parameters"]["start"]; - /** How to order values (ASC, DESC) */ - order?: components["parameters"]["order"]; - /** The value to order by */ - orderBy?: "type" | "date" | "activity" | "net" | "gross"; - }; - }; - responses: { - /** OK */ - 200: { - content: { - "application/json": { - results: ({ - id: number; - } & { - type: string; - amount: { - net?: components["schemas"]["Currency"]; - gross: components["schemas"]["Currency"]; - }; - /** Format: date */ - date: string; - activity: string; - })[]; - limit?: number; - size: number; - total?: number; - start: number; - }; - }; - }; - 403: components["responses"]["NotAuthorized"]; - 404: components["responses"]["NotFound"]; - }; - }; - /** Return all single attributions that dials the pending booty */ - "get-users-me-pending-booty": { - parameters: { - query: { - /** Items to skip for pagination */ - start?: components["parameters"]["start"]; - /** Max items to retrieve */ - limit?: components["parameters"]["limit"]; - /** The field for item order */ - orderBy?: - | "id" - | "attributionDate" - | "activityName" - | "net" - | "gross" - | "activity"; - /** How to order values (ASC, DESC) */ - order?: components["parameters"]["order"]; - }; - }; - responses: { - /** OK */ - 200: { - content: { - "application/json": { - results?: ({ - id: number; - } & { - name: string; - amount: { - net?: components["schemas"]["Currency"]; - gross: components["schemas"]["Currency"]; - }; - /** Format: date */ - attributionDate: string; - activity: string; - })[]; - limit?: number; - size: number; - start: number; - total?: number; - }; - }; - }; - 403: components["responses"]["NotAuthorized"]; - 404: components["responses"]["NotFound"]; - }; - }; - /** Return all user permissions */ - "get-users-me-permissions": { - parameters: {}; - responses: { - /** OK */ - 200: { - content: { - "application/json": { - appq_bug?: components["schemas"]["Olp"]; - appq_campaign?: components["schemas"]["Olp"]; - appq_message_center?: components["schemas"]["Olp"]; - appq_prospect?: components["schemas"]["Olp"]; - appq_tester_selection?: components["schemas"]["Olp"]; - }; - }; - }; - 403: components["responses"]["NotAuthorized"]; - /** Internal Server Error */ - 500: unknown; - }; - }; - /** Get all popup defined for your user */ - "get-users-me-popups": { - parameters: { - query: { - /** Show all popup history, expired popups included */ - showExpired?: boolean; - /** How to order values (ASC, DESC) */ - order?: components["parameters"]["order"]; - }; - }; - responses: { - /** OK */ - 200: { - content: { - "application/json": { - id?: number; - title?: string; - content?: string; - once?: boolean; - }[]; - }; - }; - 404: components["responses"]["NotFound"]; - }; - }; - /** Get a single popup. Will set the retrieved popup as expired */ - "get-users-me-popups-popup": { - parameters: { - path: { - popup: number; - }; - }; - responses: { - /** OK */ - 200: { - content: { - "application/json": { - id?: number; - } & components["schemas"]["Popup"]; - }; - }; - }; - }; - "get-users-me-rank": { - parameters: {}; - responses: { - /** OK */ - 200: { - content: { - "application/json": { - level: components["schemas"]["MonthlyLevel"]; - previousLevel: components["schemas"]["MonthlyLevel"]; - rank: number; - points: number; - prospect: { - level: components["schemas"]["MonthlyLevel"]; - maintenance?: number; - next?: { - points: number; - level: components["schemas"]["MonthlyLevel"]; - }; - }; - }; - }; - }; - 403: components["responses"]["NotAuthorized"]; - }; - }; - "get-users-me-rank-list": { - responses: { - /** OK */ - 200: { - content: { - "application/json": { - tops: components["schemas"]["RankingItem"][]; - peers: components["schemas"]["RankingItem"][]; - }; - }; - }; - 403: components["responses"]["NotAuthorized"]; - 404: components["responses"]["NotFound"]; - }; - }; - "post-dossiers": { - parameters: {}; - responses: { - /** Created */ - 201: { - content: { - "application/json": { - id: number; - /** @enum {string} */ - message?: "HOOK_FAILED"; - }; - }; - }; - /** Partial Content */ - 206: { - content: { - "application/json": { - id?: number; - }; - }; - }; - }; - requestBody: { - content: { - "application/json": components["schemas"]["DossierCreationData"] & { - duplicate?: { - fields?: number; - useCases?: number; - mailMerges?: number; - pages?: number; - testers?: number; - campaign?: number; - }; - }; - }; - }; - }; - "get-dossiers-campaign": { - parameters: { - path: { - /** A campaign id */ - campaign: string; - }; - }; - responses: { - /** OK */ - 200: { - content: { - "application/json": { - id: number; - title: { - customer: string; - tester: string; - }; - /** Format: date-time */ - startDate: string; - /** Format: date-time */ - endDate: string; - /** Format: date-time */ - closeDate: string; - customer: { - id: number; - name: string; - }; - project: { - id: number; - name: string; - }; - testType: { - id: number; - name: string; - }; - deviceList: { - id: number; - name: string; - }[]; - csm: { - id: number; - name: string; - }; - roles?: { - role?: { - id: number; - name: string; - }; - user?: { - id: number; - name: string; - surname: string; - }; - }[]; - description?: string; - productLink?: string; - goal?: string; - outOfScope?: string; - deviceRequirements?: string; - target?: { - notes?: string; - size?: number; - cap?: number; - }; - countries?: components["schemas"]["CountryCode"][]; - languages?: { - name: string; - }[]; - browsers?: { - id: number; - name: string; - }[]; - productType?: { - id: number; - name: string; - }; - phase: { - id: number; - name: string; - }; - notes?: string; - }; + }; + requestBody: { + content: { + "application/json": { + language_name?: string; }; }; }; }; - "put-dossiers-campaign": { + /** The language will be removed from your profile */ + "delete-users-me-languages-languageId": { parameters: { path: { - /** A campaign id */ - campaign: string; + /** The id of the language */ + languageId: number; }; }; responses: { /** OK */ 200: { content: { - "application/json": { [key: string]: unknown }; + "application/json": { + message?: string; + }; }; }; - }; - requestBody: { - content: { - "application/json": components["schemas"]["DossierCreationData"]; - }; + 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; }; }; - "get-customers-customer-projects": { + /** Return all payment requests */ + "get-users-me-payments": { parameters: { - path: { - customer: string; + query: { + /** Items to skip for pagination */ + start?: components["parameters"]["start"]; + /** Max items to retrieve */ + limit?: components["parameters"]["limit"]; + /** The field for item order */ + orderBy?: string; + /** How to order values (ASC, DESC) */ + order?: components["parameters"]["order"]; }; }; responses: { @@ -4262,44 +4943,83 @@ export interface operations { 200: { content: { "application/json": { - results: { + limit?: number; + results?: ({ id: number; - name: string; - }[]; + } & { + amount: { + gross: components["schemas"]["Currency"]; + net: components["schemas"]["Currency"]; + }; + method: { + note: string; + /** @enum {string} */ + type: "paypal" | "iban"; + }; + paidDate: string; + /** Format: uri-reference */ + receipt?: string; + /** @enum {string} */ + status: "paid" | "processing"; + })[]; + size: number; + start: number; + total?: number; }; }; }; + 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; }; }; - "post-customers-customer-projects": { - parameters: { - path: { - customer: string; - }; - }; + "post-users-me-payments": { + parameters: {}; responses: { /** OK */ 200: { content: { "application/json": { - id: number; - name: string; + amount?: number; + id?: number; }; }; }; + 403: components["responses"]["NotAuthorized"]; }; requestBody: { content: { "application/json": { - name: string; + method: + | { + email: string; + /** @enum {string} */ + type: "paypal"; + } + | { + accountHolderName: string; + iban: string; + /** @enum {string} */ + type: "iban"; + }; }; }; }; }; - "get-users-by-role-role": { + /** Return all attributions of a specific request */ + "get-users-me-payments-payment": { parameters: { path: { - role: "tester_lead" | "quality_leader" | "ux_researcher" | "assistants"; + payment: string; + }; + query: { + /** Max items to retrieve */ + limit?: components["parameters"]["limit"]; + /** Items to skip for pagination */ + start?: components["parameters"]["start"]; + /** How to order values (ASC, DESC) */ + order?: components["parameters"]["order"]; + /** The value to order by */ + orderBy?: "type" | "date" | "activity" | "net" | "gross"; }; }; responses: { @@ -4307,71 +5027,130 @@ export interface operations { 200: { content: { "application/json": { - results: { + limit?: number; + results: ({ id: number; - name: string; - surname: string; - }[]; + } & { + activity: string; + amount: { + gross: components["schemas"]["Currency"]; + net?: components["schemas"]["Currency"]; + }; + /** Format: date */ + date: string; + type: string; + })[]; + size: number; + start: number; + total?: number; }; }; }; + 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; }; }; - "get-browsers": { + /** Return all single attributions that dials the pending booty */ + "get-users-me-pending-booty": { + parameters: { + query: { + /** Items to skip for pagination */ + start?: components["parameters"]["start"]; + /** Max items to retrieve */ + limit?: components["parameters"]["limit"]; + /** The field for item order */ + orderBy?: + | "id" + | "attributionDate" + | "activityName" + | "net" + | "gross" + | "activity"; + /** How to order values (ASC, DESC) */ + order?: components["parameters"]["order"]; + /** Key-value Array for item filtering */ + filterBy?: components["parameters"]["filterBy"]; + }; + }; responses: { /** OK */ 200: { content: { "application/json": { - results: { + limit?: number; + results?: ({ id: number; + } & { + activity: string; + amount: { + gross: components["schemas"]["Currency"]; + net?: components["schemas"]["Currency"]; + }; + /** Format: date */ + attributionDate: string; name: string; - }[]; + })[]; + size: number; + start: number; + total?: number; }; }; }; + 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; }; }; - "get-productTypes": { + /** Return all user permissions */ + "get-users-me-permissions": { parameters: {}; responses: { /** OK */ 200: { content: { "application/json": { - results: { - id: number; - name: string; - }[]; + appq_bug?: components["schemas"]["Olp"]; + appq_campaign?: components["schemas"]["Olp"]; + appq_message_center?: components["schemas"]["Olp"]; + appq_prospect?: components["schemas"]["Olp"]; + appq_tester_selection?: components["schemas"]["Olp"]; }; }; }; + 403: components["responses"]["NotAuthorized"]; + /** Internal Server Error */ + 500: unknown; }; }; - "get-phases": { + /** Get all popup defined for your user */ + "get-users-me-popups": { + parameters: { + query: { + /** Show all popup history, expired popups included */ + showExpired?: boolean; + /** How to order values (ASC, DESC) */ + order?: components["parameters"]["order"]; + }; + }; responses: { /** OK */ 200: { content: { "application/json": { - results: { - id: number; - name: string; - type: { - id: number; - name: string; - }; - }[]; - }; + content?: string; + id?: number; + once?: boolean; + title?: string; + }[]; }; }; + 404: components["responses"]["NotFound"]; }; }; - "put-dossiers-campaign-phases": { + /** Get a single popup. Will set the retrieved popup as expired */ + "get-users-me-popups-popup": { parameters: { path: { - /** A campaign id */ - campaign: string; + popup: number; }; }; responses: { @@ -4379,18 +5158,50 @@ export interface operations { 200: { content: { "application/json": { - id: number; - name: string; + id?: number; + } & components["schemas"]["Popup"]; + }; + }; + }; + }; + "get-users-me-rank": { + parameters: {}; + responses: { + /** OK */ + 200: { + content: { + "application/json": { + level: components["schemas"]["MonthlyLevel"]; + points: number; + previousLevel: components["schemas"]["MonthlyLevel"]; + prospect: { + level: components["schemas"]["MonthlyLevel"]; + maintenance?: number; + next?: { + level: components["schemas"]["MonthlyLevel"]; + points: number; + }; + }; + rank: number; }; }; }; + 403: components["responses"]["NotAuthorized"]; }; - requestBody: { - content: { - "application/json": { - phase: number; + }; + "get-users-me-rank-list": { + responses: { + /** OK */ + 200: { + content: { + "application/json": { + peers: components["schemas"]["RankingItem"][]; + tops: components["schemas"]["RankingItem"][]; + }; }; }; + 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; }; }; } From a06914c5fe03a36848650acf16fc824fcc7e4c2e Mon Sep 17 00:00:00 2001 From: Kariamos Date: Thu, 23 Oct 2025 12:54:33 +0200 Subject: [PATCH 18/37] fix: correct styled component syntax in StyledPageTemplate --- src/pages/UsecaseMediaDropzone/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/UsecaseMediaDropzone/index.tsx b/src/pages/UsecaseMediaDropzone/index.tsx index 96774ad1..ccab52d4 100644 --- a/src/pages/UsecaseMediaDropzone/index.tsx +++ b/src/pages/UsecaseMediaDropzone/index.tsx @@ -14,7 +14,7 @@ import styled from "styled-components"; const StyledPageTemplate = styled.div` background-color: ${aqBootstrapTheme.colors.white}; - } + min-height: 100vh; `; const FileDropzonePage = () => { From dcf6fa91b4e13d96b5f4555924ecb6a855fbc6de Mon Sep 17 00:00:00 2001 From: Kariamos Date: Thu, 23 Oct 2025 13:10:25 +0200 Subject: [PATCH 19/37] refactor: replace inline styles with styled component for StyledFileGrid in MediaDropzone --- src/pages/Manual/UseCases/MediaDropzone.tsx | 23 +++++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/pages/Manual/UseCases/MediaDropzone.tsx b/src/pages/Manual/UseCases/MediaDropzone.tsx index c4dead1b..061e2307 100644 --- a/src/pages/Manual/UseCases/MediaDropzone.tsx +++ b/src/pages/Manual/UseCases/MediaDropzone.tsx @@ -9,10 +9,22 @@ import { usePostUsersMeCampaignsByCampaignIdTasksAndTaskIdMediaMutation, } from "src/services/tryberApi"; import { useAppDispatch, useAppSelector } from "src/store"; +import styled from "styled-components"; import { createFilesElementList } from "./createFilesElementList"; import { appendMediaList, removeElementFromMedialist } from "./mediaSlice"; import { normalizeFileName } from "./normalizeFileName"; +const StyledFileGrid = styled.div` + display: grid; + grid-template-columns: repeat(auto-fill, 32%); + gap: 10px; + margin-bottom: 10px; + + @media (max-width: ${(p) => p.theme.grid.breakpoints.md}) { + grid-template-columns: 1fr; + } +`; + export const MediaDropzone = ({ taskId, campaignId, @@ -88,14 +100,7 @@ export const MediaDropzone = ({ return ( <> -
+ {media?.items.map((m) => ( ))} -
+ Date: Thu, 23 Oct 2025 14:33:53 +0200 Subject: [PATCH 20/37] refactor: moved dropzone over the uploaded files grid and modified some style --- src/pages/Manual/UseCases/MediaDropzone.tsx | 41 +++++++++++---------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/src/pages/Manual/UseCases/MediaDropzone.tsx b/src/pages/Manual/UseCases/MediaDropzone.tsx index 061e2307..98f0e967 100644 --- a/src/pages/Manual/UseCases/MediaDropzone.tsx +++ b/src/pages/Manual/UseCases/MediaDropzone.tsx @@ -18,10 +18,11 @@ const StyledFileGrid = styled.div` display: grid; grid-template-columns: repeat(auto-fill, 32%); gap: 10px; + margin-top: 10px; margin-bottom: 10px; @media (max-width: ${(p) => p.theme.grid.breakpoints.md}) { - grid-template-columns: 1fr; + display: block; } `; @@ -100,6 +101,25 @@ export const MediaDropzone = ({ return ( <> + uploadMedia(acceptedFiles)} + onRejected={(fileRejections) => { + const newFileList: File[] = []; + fileRejections.forEach((f) => newFileList.push(f.file)); + const elements = createFilesElementList({ + files: newFileList, + status: "failed", + taskId, + }); + dispatch(appendMediaList(elements)); + }} + danger={false} + /> {media?.items.map((m) => ( ))} - uploadMedia(acceptedFiles)} - onRejected={(fileRejections) => { - const newFileList: File[] = []; - fileRejections.forEach((f) => newFileList.push(f.file)); - const elements = createFilesElementList({ - files: newFileList, - status: "failed", - taskId, - }); - dispatch(appendMediaList(elements)); - }} - danger={false} - /> ); }; From f8bd372677e1aa23613a44575033567e69c05134 Mon Sep 17 00:00:00 2001 From: Kariamos Date: Thu, 23 Oct 2025 16:59:07 +0200 Subject: [PATCH 21/37] fix: add errorCode to media item in MediaDropzone component to show error message --- src/pages/Manual/UseCases/MediaDropzone.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pages/Manual/UseCases/MediaDropzone.tsx b/src/pages/Manual/UseCases/MediaDropzone.tsx index 98f0e967..37f59cb6 100644 --- a/src/pages/Manual/UseCases/MediaDropzone.tsx +++ b/src/pages/Manual/UseCases/MediaDropzone.tsx @@ -152,6 +152,7 @@ export const MediaDropzone = ({ fileType: "", mimeType: "", status: m.status, + errorCode: m.errorCode, }} onDelete={() => m.status !== "uploading" From b6a3a55a725d90a08114dba51ea76680108ad0be Mon Sep 17 00:00:00 2001 From: Kariamos Date: Thu, 23 Oct 2025 17:38:39 +0200 Subject: [PATCH 22/37] feat: update translation keys for wallet expired tab and improve localization --- src/locales/en/translation.json | 10 +++++----- src/locales/es/translation.json | 10 +++++----- src/locales/fr/translation.json | 10 +++++----- src/locales/it/translation.json | 6 +++--- src/pages/Wallet/expiredTabColumns.ts | 8 ++++---- 5 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index 08a1e450..bf232a60 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -76,6 +76,7 @@ "Approved bugs": "Approved bugs", "Area is a required field.": "Area is a required field.", "As first step to be done, complete your profile with authentic and real data. This is the only way to be selected for the Campaigns and get your reward.": "Enter your details in the Profile section: they are important to be selected for suitable campaign and to request the payments.", + "Attribution date": "Attribution date", "Available booty": "Available booty", "Available tags \n - Link to help article for fiscal type": { "@@Description for fiscal type@@": "Click here for more info" @@ -216,7 +217,6 @@ "SignupFrom Step1": "Date of birth" }, "Dashboard": "Dashboard", - "Data attribuzione": "", "Date": "Date", "Delete": "Delete", "Delete account": "Delete account", @@ -288,6 +288,7 @@ }, "Gross": "Gross", "Gross amount": "Gross amount", + "Gross total": "Gross total", "Have fun!": "Don't forget to have a good time!", "Here is the list of your all devices. Make sure to keep it updated in order to boost your chances to be selected for further projects.": "Here is the list of your all devices. Make sure to keep it updated in order to boost your chances to be selected for further projects.", "Here you can only change the version of your operating system. If you want to add another device click on \"Add device\"": "Here you can only change the version of your operating system. If you want to add another device click on \"Add device\"", @@ -541,12 +542,10 @@ "This is an invalid format. Should be formatted as +11000000000 or 0011000000000": "This is an invalid format. Should be formatted as +11000000000 or 0011000000000", "This is your personal dashboard. From here you can check out your stats, keep an eye on the progress of your work and find new campaigns to apply for. Have fun!": "This is your personal dashboard. From here you can check out your stats, keep an eye on the progress of your work and find new campaigns to apply for. Have fun!", "This value is invalid, you need to select a city with a province": "This value is invalid, you need to select a city with a province", - "Tipo attività": "", "Title": "Title", "Top 3 | level {{level}}": { "__RANKING_TITLE_LABEL_TOP_LEVEL_MAX: 25": "Top 3 | {{level}} level" }, - "Tot. lordo": "", "Try again.": "Try again.", "Type": "Type", "Type to search your city": "Type to search your city", @@ -688,8 +687,8 @@ "__WALLET_CARD-REQUEST_DISCLAIMER-PROCESSING MAX: 150": "You can request only one payment at a time: you alreay have a payment in process, this may take up to 20 working days.", "__WALLET_CARD-REQUEST_TITLE MAX: 40": "Manage your payment", "__WALLET_CARD-YOUR_WALLET_MAX: 15": "Your wallet", - "__WALLET_EXPIRED_TAB": "", - "__WALLET_HISTORY_TAB": "", + "__WALLET_EXPIRED_TAB": "Expired booties", + "__WALLET_HISTORY_TAB": "Payment history", "__WALLET_HOME-EMPTY_STATE_MAX: 105": "Your payment history is now empty. When you start requesting your payments, you will view them here.", "__WALLET_TABLE-HEADER_CTA-ICON-DETAILS MAX:": "View details", "__WALLET_TABLE-HEADER_CTA-ICON-PDF MAX:": "Download receipt", @@ -799,6 +798,7 @@ "BUGFORM_UPLOAD_PROGRESS": "{{num}} uploaded", "BUGFORM_UPLOAD_PROGRESS_plural": "{{num}} uploaded" }, + "Tipo attività": "", "Report a Bug": "", "Page Preview": "", "/my-account/": "/my-account/", diff --git a/src/locales/es/translation.json b/src/locales/es/translation.json index b10e4fbf..aaca07c3 100644 --- a/src/locales/es/translation.json +++ b/src/locales/es/translation.json @@ -76,6 +76,7 @@ "Approved bugs": "Bugs aprobados", "Area is a required field.": "El área / La esfera es un campo obligatorio", "As first step to be done, complete your profile with authentic and real data. This is the only way to be selected for the Campaigns and get your reward.": "Añade todos tus datos en la sección Perfil: los necesitaremos para seleccionarte cuando haya una campaña adecuada y para que puedas solicitar los pagos.", + "Attribution date": "Fecha de atribución", "Available booty": "Saldo Disponible", "Available tags \n - Link to help article for fiscal type": { "@@Description for fiscal type@@": "Haga clic aquí para obtener más información" @@ -216,7 +217,6 @@ "SignupFrom Step1": "Fecha de nacimiento" }, "Dashboard": "Dashboard", - "Data attribuzione": "", "Date": "Fecha", "Delete": "Eliminar", "Delete account": "Elímina account", @@ -288,6 +288,7 @@ }, "Gross": "Bruto", "Gross amount": "Cantidad bruta", + "Gross total": "Total bruto", "Have fun!": "¡No te olvides de pasarlo bien!", "Here is the list of your all devices. Make sure to keep it updated in order to boost your chances to be selected for further projects.": "Aquí está la lista de todos tus dispositivos. Asegúrete de mantenerla actualizada para aumentar tus posibilidades de ser seleccionado para proyectos futuros.", "Here you can only change the version of your operating system. If you want to add another device click on \"Add device\"": "Aquí solo puedes cambiar la versión de tu sistema operativo. Si deseas agregar otro dispositivo, haga clic en \"Agregar dispositivo\"", @@ -541,12 +542,10 @@ "This is an invalid format. Should be formatted as +11000000000 or 0011000000000": "Este es un formato no válido. Tiene que ser formateado como +11000000000 o 0011000000000", "This is your personal dashboard. From here you can check out your stats, keep an eye on the progress of your work and find new campaigns to apply for. Have fun!": "Este es tu dashboard personal. Desde aquí puedes consultar tus estadísticas, el progreso de tu trabajo y encontrar nuevas Campañas a las que postularte. ¡Diviértete!", "This value is invalid, you need to select a city with a province": "Este valor no es válido, es necesario seleccionar una ciudad con una provincia", - "Tipo attività": "", "Title": "Título", "Top 3 | level {{level}}": { "__RANKING_TITLE_LABEL_TOP_LEVEL_MAX: 25": "Top 3 | Nivel {{level}}" }, - "Tot. lordo": "", "Try again.": "Inténtelo de nuevo.", "Type": "Tipo", "Type to search your city": "Escriba para buscar tu ciudad", @@ -688,8 +687,8 @@ "__WALLET_CARD-REQUEST_DISCLAIMER-PROCESSING MAX: 150": "Solo puedes solicitar un pago a la vez: ya tienes una solicitud pendiente, ésta puede tardar hasta 20 días laborables.", "__WALLET_CARD-REQUEST_TITLE MAX: 40": "Gestiona el pago", "__WALLET_CARD-YOUR_WALLET_MAX: 15": "Tu monedero", - "__WALLET_EXPIRED_TAB": "", - "__WALLET_HISTORY_TAB": "", + "__WALLET_EXPIRED_TAB": "Ingresos caducados", + "__WALLET_HISTORY_TAB": "Historial de pagos", "__WALLET_HOME-EMPTY_STATE_MAX: 105": "Aún no has solicitado ningun pago. Cuando lo harás, podrás ver tus pagos aquí.", "__WALLET_TABLE-HEADER_CTA-ICON-DETAILS MAX:": "Ver detalles", "__WALLET_TABLE-HEADER_CTA-ICON-PDF MAX:": "Descargar recibo", @@ -799,6 +798,7 @@ "BUGFORM_UPLOAD_PROGRESS": "{{num}} subido", "BUGFORM_UPLOAD_PROGRESS_plural": "{{num}} subidos" }, + "Tipo attività": "", "Report a Bug": "", "Page Preview": "Page Preview", "/my-account/": "/perfil/", diff --git a/src/locales/fr/translation.json b/src/locales/fr/translation.json index 20ef7be8..aa825f64 100644 --- a/src/locales/fr/translation.json +++ b/src/locales/fr/translation.json @@ -76,6 +76,7 @@ "Approved bugs": "Bugs approuvés", "Area is a required field.": "Le domaine est un champ obligatoire.", "As first step to be done, complete your profile with authentic and real data. This is the only way to be selected for the Campaigns and get your reward.": "Indiquez vos coordonnées dans la section Profil : elles sont importantes pour être sélectionné pour des campagnes adaptées et pour demander les paiements.", + "Attribution date": "Date d'attribution", "Available booty": "Butin disponible", "Available tags \n - Link to help article for fiscal type": { "@@Description for fiscal type@@": "Cliquez ici pour plus d'infos" @@ -216,7 +217,6 @@ "SignupFrom Step1": "Date de naissance" }, "Dashboard": "Tableau de bord", - "Data attribuzione": "", "Date": "Date", "Delete": "Supprimer", "Delete account": "Supprimer le compte", @@ -288,6 +288,7 @@ }, "Gross": "Brut", "Gross amount": "Montant brut", + "Gross total": "Total brut", "Have fun!": "N'oubliez pas de vous amuser !", "Here is the list of your all devices. Make sure to keep it updated in order to boost your chances to be selected for further projects.": "Voici la liste de tous vos appareils. Assurez-vous de la tenir à jour pour augmenter vos chances d'être sélectionné pour d'autres projets.", "Here you can only change the version of your operating system. If you want to add another device click on \"Add device\"": "Ici, vous ne pouvez changer que la version de votre système d'exploitation. Si vous souhaitez ajouter un autre appareil, cliquez sur \"Ajouter un appareil\"", @@ -541,12 +542,10 @@ "This is an invalid format. Should be formatted as +11000000000 or 0011000000000": "Ce format est invalide. Il doit être formaté comme +11000000000 ou 0011000000000", "This is your personal dashboard. From here you can check out your stats, keep an eye on the progress of your work and find new campaigns to apply for. Have fun!": "Ceci est votre tableau de bord personnel. D'ici, vous pouvez consulter vos statistiques, surveiller l'avancement de votre travail et trouver de nouvelles campagnes pour lesquelles postuler. Amusez-vous bien !", "This value is invalid, you need to select a city with a province": "Cette valeur est invalide, vous devez sélectionner une ville avec une province", - "Tipo attività": "", "Title": "Titre", "Top 3 | level {{level}}": { "__RANKING_TITLE_LABEL_TOP_LEVEL_MAX: 25": "Top 3 | niveau {{level}}" }, - "Tot. lordo": "", "Try again.": "Réessayez.", "Type": "Type", "Type to search your city": "Tapez pour rechercher votre ville", @@ -688,8 +687,8 @@ "__WALLET_CARD-REQUEST_DISCLAIMER-PROCESSING MAX: 150": "Vous ne pouvez demander qu'un paiement à la fois : vous avez déjà un paiement en cours, cela peut prendre jusqu'à 20 jours ouvrables.", "__WALLET_CARD-REQUEST_TITLE MAX: 40": "Gérez votre paiement", "__WALLET_CARD-YOUR_WALLET_MAX: 15": "Votre portefeuille", - "__WALLET_EXPIRED_TAB": "", - "__WALLET_HISTORY_TAB": "", + "__WALLET_EXPIRED_TAB": "Butin expiré", + "__WALLET_HISTORY_TAB": "Historique des paiements", "__WALLET_HOME-EMPTY_STATE_MAX: 105": "Votre historique de paiement est actuellement vide. Lorsque vous commencerez à demander vos paiements, vous les verrez ici.", "__WALLET_TABLE-HEADER_CTA-ICON-DETAILS MAX:": "Voir les détails", "__WALLET_TABLE-HEADER_CTA-ICON-PDF MAX:": "Télécharger le reçu", @@ -799,6 +798,7 @@ "BUGFORM_UPLOAD_PROGRESS": "{{num}} téléchargé", "BUGFORM_UPLOAD_PROGRESS_plural": "{{num}} téléchargés" }, + "Tipo attività": "", "Report a Bug": "", "{{date}} {{at_time}} {{time}}": "", "Page Preview": "Page Preview", diff --git a/src/locales/it/translation.json b/src/locales/it/translation.json index 6fdf07b2..0b0a7771 100644 --- a/src/locales/it/translation.json +++ b/src/locales/it/translation.json @@ -76,6 +76,7 @@ "Approved bugs": "Bug approvati", "Area is a required field.": "L'area è un campo obbligatorio", "As first step to be done, complete your profile with authentic and real data. This is the only way to be selected for the Campaigns and get your reward.": "Inserisci tutti i tuoi dati nella sezione Profilo: servirà a noi per selezionarti quando c'è una campagna adatta e a te per richiedere il pagamento.", + "Attribution date": "Data di attribuzione", "Available booty": "Guadagni disponibili", "Available tags \n - Link to help article for fiscal type": { "@@Description for fiscal type@@": "Clicca qui per maggiori informazioni" @@ -216,7 +217,6 @@ "SignupFrom Step1": "Data di nascita" }, "Dashboard": "Dashboard", - "Data attribuzione": "", "Date": "Data", "Delete": "Rimuovi", "Delete account": "Elimina account", @@ -288,6 +288,7 @@ }, "Gross": "Lordo", "Gross amount": "Lordo", + "Gross total": "Tot. Lordo", "Have fun!": "Ricordati di divertirti!", "Here is the list of your all devices. Make sure to keep it updated in order to boost your chances to be selected for further projects.": "Ecco la lista dei tuoi dispositivi. Assicurati di tenerla sempre aggiornata per aumentare le possibilità di essere selezionat* nei prossimi progetti.", "Here you can only change the version of your operating system. If you want to add another device click on \"Add device\"": "Qui puoi solo cambiare la versione del tuo sistema operativo. Se vuoi aggiungere un altro dispositivo clicca su \"Aggiungi dispositivo\"", @@ -541,12 +542,10 @@ "This is an invalid format. Should be formatted as +11000000000 or 0011000000000": "Formato invalido. Deve essere formattato come +11000000000 o 0011000000000", "This is your personal dashboard. From here you can check out your stats, keep an eye on the progress of your work and find new campaigns to apply for. Have fun!": "Questa è la tua dashboard personale. Da qui puoi controllare le tue statistiche, tenere d'occhio lo stato di avanzamento del tuo lavoro e trovare nuove campagne a cui candidarti. Divertiti!", "This value is invalid, you need to select a city with a province": "Questo valore è invalido, devi selezionare una città con una provincia", - "Tipo attività": "", "Title": "Titolo", "Top 3 | level {{level}}": { "__RANKING_TITLE_LABEL_TOP_LEVEL_MAX: 25": "Top 3 | Livello {{level}}" }, - "Tot. lordo": "", "Try again.": "Riprova", "Type": "Tipo", "Type to search your city": "Digita per cercare la tua città", @@ -799,6 +798,7 @@ "BUGFORM_UPLOAD_PROGRESS": "{{num}} caricato", "BUGFORM_UPLOAD_PROGRESS_plural": "{{num}} caricati" }, + "Tipo attività": "", "Report a Bug": "Carica un Bug", "Page Preview": "Pagina di preview", "/my-account/": "/it/il-mio-account/", diff --git a/src/pages/Wallet/expiredTabColumns.ts b/src/pages/Wallet/expiredTabColumns.ts index 19baa4c6..fb0a015c 100644 --- a/src/pages/Wallet/expiredTabColumns.ts +++ b/src/pages/Wallet/expiredTabColumns.ts @@ -8,20 +8,20 @@ export const expiredTabColumns = ( ): Column[] => { return [ { - title: "Nome attività", + title: t("Activity name"), dataIndex: "activityName", key: "activityName", maxWidth: "max-content", }, { - title: t("Tipo attività"), + title: t("Activity"), dataIndex: "activityType", key: "activityType", role: "overline", hideIndex: true, }, { - title: t("Data attribuzione"), + title: t("Attribution date"), dataIndex: "attributionDate", key: "attributionDate", isSortable: true, @@ -30,7 +30,7 @@ export const expiredTabColumns = ( }, }, { - title: t("Tot. lordo"), + title: t("Gross total"), dataIndex: "gross", key: "gross", isSortable: true, From b2c0f70465749b71cd43d1a6fa701c253a7db6a0 Mon Sep 17 00:00:00 2001 From: Kariamos Date: Thu, 23 Oct 2025 17:51:04 +0200 Subject: [PATCH 23/37] feat: add wallet card expiration disclaimer to localization and UI --- src/locales/en/translation.json | 1 + src/locales/es/translation.json | 1 + src/locales/fr/translation.json | 1 + src/locales/it/translation.json | 1 + src/pages/Wallet/WalletManagment.tsx | 4 ++++ 5 files changed, 8 insertions(+) diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index bf232a60..f9cb658c 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -677,6 +677,7 @@ "__RANKING_TITLE_LABEL_POSITION_MAX: 15": "Position", "__RANKING_TITLE_WELCOM_MAX: 20": "Ranking", "__SELECT_DEFAULT_NO_OPTION": "No options", + "__WALLET_CARD-EXPIRATION_DISCLAIMER": "Keep in mind: every booty is valid for 12 months", "__WALLET_CARD-GUIDES_CTA MAX: 20": "Read our guides", "__WALLET_CARD-GUIDES_PARAGRAPH MAX: 60": "Discover how we manage your payment requests.", "__WALLET_CARD-GUIDES_TITLE MAX: 35": "Any questions on payment process?", diff --git a/src/locales/es/translation.json b/src/locales/es/translation.json index aaca07c3..d58ff176 100644 --- a/src/locales/es/translation.json +++ b/src/locales/es/translation.json @@ -677,6 +677,7 @@ "__RANKING_TITLE_LABEL_POSITION_MAX: 15": "Posición", "__RANKING_TITLE_WELCOM_MAX: 20": "Clasificación", "__SELECT_DEFAULT_NO_OPTION": "sin opciones", + "__WALLET_CARD-EXPIRATION_DISCLAIMER": "Cada en cuenta: cada ingreso es válido por 12 meses", "__WALLET_CARD-GUIDES_CTA MAX: 20": "Nuestras guías", "__WALLET_CARD-GUIDES_PARAGRAPH MAX: 60": "Descubre cómo gestionamos tus solicitudes de pago", "__WALLET_CARD-GUIDES_TITLE MAX: 35": "¿Dudas sobre el proceso de pago?", diff --git a/src/locales/fr/translation.json b/src/locales/fr/translation.json index aa825f64..ca75c432 100644 --- a/src/locales/fr/translation.json +++ b/src/locales/fr/translation.json @@ -677,6 +677,7 @@ "__RANKING_TITLE_LABEL_POSITION_MAX: 15": "Position", "__RANKING_TITLE_WELCOM_MAX: 20": "Classement", "__SELECT_DEFAULT_NO_OPTION": "Aucune option", + "__WALLET_CARD-EXPIRATION_DISCLAIMER": "Notez bien: chaque butin est valable pendant 12 mois.", "__WALLET_CARD-GUIDES_CTA MAX: 20": "Lisez nos guides", "__WALLET_CARD-GUIDES_PARAGRAPH MAX: 60": "Découvrez comment nous gérons vos demandes de paiement.", "__WALLET_CARD-GUIDES_TITLE MAX: 35": "Des questions sur le processus de paiement ?", diff --git a/src/locales/it/translation.json b/src/locales/it/translation.json index 0b0a7771..6bc68c99 100644 --- a/src/locales/it/translation.json +++ b/src/locales/it/translation.json @@ -677,6 +677,7 @@ "__RANKING_TITLE_LABEL_POSITION_MAX: 15": "Posizione", "__RANKING_TITLE_WELCOM_MAX: 20": "Classifica", "__SELECT_DEFAULT_NO_OPTION": "Nessuna opzione", + "__WALLET_CARD-EXPIRATION_DISCLAIMER": "Ricorda: ogni guadagno è valido per 12 mesi.", "__WALLET_CARD-GUIDES_CTA MAX: 20": "Le nostre guide", "__WALLET_CARD-GUIDES_PARAGRAPH MAX: 60": "Scopri come gestiamo le richieste di pagamenti", "__WALLET_CARD-GUIDES_TITLE MAX: 35": "Domande o dubbi sui pagamenti?", diff --git a/src/pages/Wallet/WalletManagment.tsx b/src/pages/Wallet/WalletManagment.tsx index 89bfa899..18593cd1 100644 --- a/src/pages/Wallet/WalletManagment.tsx +++ b/src/pages/Wallet/WalletManagment.tsx @@ -183,6 +183,10 @@ export const WalletManagment = () => { {getInfoText()} + + + + ); }; From 39c3da93e77a5dc070de0a300ab990157da37d28 Mon Sep 17 00:00:00 2001 From: Kariamos Date: Thu, 23 Oct 2025 17:53:08 +0200 Subject: [PATCH 24/37] feat: update localization for "Expired On" in English, Spanish, French, and Italian --- src/locales/en/translation.json | 2 +- src/locales/es/translation.json | 2 +- src/locales/fr/translation.json | 2 +- src/locales/it/translation.json | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index f9cb658c..2d3e1199 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -246,7 +246,7 @@ "End Date": "End Date", "Experience Points": "Experience Points", "Expiration date": "", - "Expired On": "", + "Expired On": "Expired on", "Extra Award": "Extra Award", "FAQ": "FAQ", "Facebook": "Facebook", diff --git a/src/locales/es/translation.json b/src/locales/es/translation.json index d58ff176..a9785067 100644 --- a/src/locales/es/translation.json +++ b/src/locales/es/translation.json @@ -246,7 +246,7 @@ "End Date": "Fecha Final", "Experience Points": "Puntos de Experiencia", "Expiration date": "", - "Expired On": "", + "Expired On": "Caducado el", "Extra Award": "Recompensa Extra", "FAQ": "Preguntas Frecuentes", "Facebook": "Facebook", diff --git a/src/locales/fr/translation.json b/src/locales/fr/translation.json index ca75c432..1c06eb20 100644 --- a/src/locales/fr/translation.json +++ b/src/locales/fr/translation.json @@ -246,7 +246,7 @@ "End Date": "Date de fin", "Experience Points": "Points d'expérience", "Expiration date": "", - "Expired On": "", + "Expired On": "Expiré le", "Extra Award": "Récompense supplémentaire", "FAQ": "FAQ", "Facebook": "Facebook", diff --git a/src/locales/it/translation.json b/src/locales/it/translation.json index 6bc68c99..f8a7f738 100644 --- a/src/locales/it/translation.json +++ b/src/locales/it/translation.json @@ -246,7 +246,7 @@ "End Date": "Fine", "Experience Points": "Punti esperienza", "Expiration date": "", - "Expired On": "", + "Expired On": "Scaduto il", "Extra Award": "Premio extra", "FAQ": "Domande frequenti", "Facebook": "Facebook", From bb9ac11e1a38b1a5ecd3034abf61ab20b81b23d9 Mon Sep 17 00:00:00 2001 From: Kariamos Date: Thu, 23 Oct 2025 18:04:13 +0200 Subject: [PATCH 25/37] feat: add description for expired wallet tab in English, Spanish, French, and Italian --- src/locales/en/translation.json | 1 + src/locales/es/translation.json | 1 + src/locales/fr/translation.json | 1 + src/locales/it/translation.json | 1 + src/pages/Wallet/WalletTable.tsx | 8 +++++++- 5 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index 2d3e1199..151782ec 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -689,6 +689,7 @@ "__WALLET_CARD-REQUEST_TITLE MAX: 40": "Manage your payment", "__WALLET_CARD-YOUR_WALLET_MAX: 15": "Your wallet", "__WALLET_EXPIRED_TAB": "Expired booties", + "__WALLET_EXPIRED_TAB-DESCRIPTION": "List of expired booty, for which more than 12 months have passed and it is no longer possible to request payment", "__WALLET_HISTORY_TAB": "Payment history", "__WALLET_HOME-EMPTY_STATE_MAX: 105": "Your payment history is now empty. When you start requesting your payments, you will view them here.", "__WALLET_TABLE-HEADER_CTA-ICON-DETAILS MAX:": "View details", diff --git a/src/locales/es/translation.json b/src/locales/es/translation.json index a9785067..83a9ed37 100644 --- a/src/locales/es/translation.json +++ b/src/locales/es/translation.json @@ -689,6 +689,7 @@ "__WALLET_CARD-REQUEST_TITLE MAX: 40": "Gestiona el pago", "__WALLET_CARD-YOUR_WALLET_MAX: 15": "Tu monedero", "__WALLET_EXPIRED_TAB": "Ingresos caducados", + "__WALLET_EXPIRED_TAB-DESCRIPTION": "Lista de ingresos caducados, para los cuales han pasado más de 12 meses y ya no es posible solicitar el pago", "__WALLET_HISTORY_TAB": "Historial de pagos", "__WALLET_HOME-EMPTY_STATE_MAX: 105": "Aún no has solicitado ningun pago. Cuando lo harás, podrás ver tus pagos aquí.", "__WALLET_TABLE-HEADER_CTA-ICON-DETAILS MAX:": "Ver detalles", diff --git a/src/locales/fr/translation.json b/src/locales/fr/translation.json index 1c06eb20..35246972 100644 --- a/src/locales/fr/translation.json +++ b/src/locales/fr/translation.json @@ -689,6 +689,7 @@ "__WALLET_CARD-REQUEST_TITLE MAX: 40": "Gérez votre paiement", "__WALLET_CARD-YOUR_WALLET_MAX: 15": "Votre portefeuille", "__WALLET_EXPIRED_TAB": "Butin expiré", + "__WALLET_EXPIRED_TAB-DESCRIPTION": "Liste du butin expiré, pour lequel plus de 12 mois se sont écoulés et il n’est plus possible de demander le paiement", "__WALLET_HISTORY_TAB": "Historique des paiements", "__WALLET_HOME-EMPTY_STATE_MAX: 105": "Votre historique de paiement est actuellement vide. Lorsque vous commencerez à demander vos paiements, vous les verrez ici.", "__WALLET_TABLE-HEADER_CTA-ICON-DETAILS MAX:": "Voir les détails", diff --git a/src/locales/it/translation.json b/src/locales/it/translation.json index f8a7f738..385cceb3 100644 --- a/src/locales/it/translation.json +++ b/src/locales/it/translation.json @@ -689,6 +689,7 @@ "__WALLET_CARD-REQUEST_TITLE MAX: 40": "Gestisci il pagamento", "__WALLET_CARD-YOUR_WALLET_MAX: 15": "Il tuo portafoglio", "__WALLET_EXPIRED_TAB": "Guadagni scaduti", + "__WALLET_EXPIRED_TAB-DESCRIPTION": "Elenco dei guadagni scaduti, per i quali sono trascorsi più di 12 mesi e non è più possibile richiedere il pagamento", "__WALLET_HISTORY_TAB": "Cronologia pagamenti", "__WALLET_HOME-EMPTY_STATE_MAX: 105": "Per ora non hai ancora richiesto un pagamento. Quando inizierai a richiederne, compariranno qui.", "__WALLET_TABLE-HEADER_CTA-ICON-DETAILS MAX:": "Vedi dettagli", diff --git a/src/pages/Wallet/WalletTable.tsx b/src/pages/Wallet/WalletTable.tsx index 68c5128f..6d8019fd 100644 --- a/src/pages/Wallet/WalletTable.tsx +++ b/src/pages/Wallet/WalletTable.tsx @@ -5,9 +5,10 @@ import { Table, TableType, Tabs, + Text, } from "@appquality/appquality-design-system"; import { useEffect, useState } from "react"; -import { useTranslation } from "react-i18next"; +import { Trans, useTranslation } from "react-i18next"; import { shallowEqual, useSelector } from "react-redux"; import detailsIcon from "src/pages/Wallet/assets/details.svg"; import detailsHoverIcon from "src/pages/Wallet/assets/detailsHover.svg"; @@ -331,6 +332,11 @@ export const WalletTable = () => { label={t("Order By", { context: "Sort Table Select" })} /> )} +
+ + + +
Date: Thu, 23 Oct 2025 18:06:37 +0200 Subject: [PATCH 26/37] feat: disable expired tab when there are no expired rows --- src/pages/Wallet/WalletTable.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pages/Wallet/WalletTable.tsx b/src/pages/Wallet/WalletTable.tsx index 6d8019fd..4b9278c0 100644 --- a/src/pages/Wallet/WalletTable.tsx +++ b/src/pages/Wallet/WalletTable.tsx @@ -320,6 +320,7 @@ export const WalletTable = () => { {t("__WALLET_EXPIRED_TAB")} } From 5adb63c784d231f9f4c7d009b2f069f114914ce4 Mon Sep 17 00:00:00 2001 From: Kariamos Date: Thu, 23 Oct 2025 18:07:03 +0200 Subject: [PATCH 27/37] feat: disable expired tab based on loading state --- src/pages/Wallet/WalletTable.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/Wallet/WalletTable.tsx b/src/pages/Wallet/WalletTable.tsx index 4b9278c0..67877fe6 100644 --- a/src/pages/Wallet/WalletTable.tsx +++ b/src/pages/Wallet/WalletTable.tsx @@ -320,7 +320,7 @@ export const WalletTable = () => { {t("__WALLET_EXPIRED_TAB")} } From 65a00ee444496e0f3ac0bba8b1594c95fad7ca07 Mon Sep 17 00:00:00 2001 From: Kariamos Date: Thu, 23 Oct 2025 18:53:09 +0200 Subject: [PATCH 28/37] feat: format query parameters for pending booty data retrieval --- src/pages/Wallet/WalletTable.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/pages/Wallet/WalletTable.tsx b/src/pages/Wallet/WalletTable.tsx index 67877fe6..cbd50f21 100644 --- a/src/pages/Wallet/WalletTable.tsx +++ b/src/pages/Wallet/WalletTable.tsx @@ -127,7 +127,9 @@ export const WalletTable = () => { }); const { data: expiredBootyData, isLoading: isExpiredBootyLoading } = - useGetUsersMePendingBootyQuery({ filterBy: { isExpired: 1 } }); + useGetUsersMePendingBootyQuery({ + filterBy: { isExpired: 1 }, + }); // initial requests useEffect(() => { const cols = walletColumns(dispatch, t); From eb56b8e53e24e096a7dd887f8104c15fa4bb1ee7 Mon Sep 17 00:00:00 2001 From: Kariamos Date: Thu, 23 Oct 2025 18:57:14 +0200 Subject: [PATCH 29/37] feat: refine parameter serialization for filterBy object in API queries --- src/services/tryberApi/api.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/services/tryberApi/api.ts b/src/services/tryberApi/api.ts index 16b88cde..ee5005a4 100644 --- a/src/services/tryberApi/api.ts +++ b/src/services/tryberApi/api.ts @@ -14,14 +14,14 @@ export const api = createApi({ return; } // iterate over nested objects - if (typeof value === "object") { - Object.entries(params[key]).forEach(([key, value]) => { - if (typeof value === "string") { - urlps.set(`filterBy[${key}]`, value); - } - }); - return; - } + if (key === "filterBy" && value && typeof value === "object") { + Object.entries(value as Record).forEach(([fk, fv]) => { + if (fv != null) { + urlps.set(`filterBy[${fk}]`, String(fv)); + } + }); + return; + } // or just set url param urlps.set(key, value); }); From 5a70ab9ba5e766cd1e50bce99424e4cedfb2e33f Mon Sep 17 00:00:00 2001 From: Davide Bizzi Date: Fri, 24 Oct 2025 10:07:21 +0200 Subject: [PATCH 30/37] feat: Use param serializer for api --- package.json | 2 + .../BootyDetailsModal/BootyDetailsModal.tsx | 3 + src/services/tryberApi/api.ts | 24 +-- yarn.lock | 145 ++++++++++++++++++ 4 files changed, 153 insertions(+), 21 deletions(-) diff --git a/package.json b/package.json index ee50c1bb..f80536fb 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "i18next": "^20.2.2", "i18next-browser-languagedetector": "^6.1.0", "lzutf8": "^0.6.0", + "qs": "^6.14.0", "query-string": "^7.0.0", "react": "17.0.2", "react-app-polyfill": "^2.0.0", @@ -102,6 +103,7 @@ "@rtk-query/codegen-openapi": "^1.0.0-alpha.1", "@sentry/cli": "^2.23.0", "@types/node": "^14.14.41", + "@types/qs": "^6.14.0", "@types/react": "17.0.9", "@types/react-dom": "17.0.9", "@types/react-gtm-module": "^2.0.0", diff --git a/src/pages/Wallet/BootyDetailsModal/BootyDetailsModal.tsx b/src/pages/Wallet/BootyDetailsModal/BootyDetailsModal.tsx index 2c2c63c9..84381bdd 100644 --- a/src/pages/Wallet/BootyDetailsModal/BootyDetailsModal.tsx +++ b/src/pages/Wallet/BootyDetailsModal/BootyDetailsModal.tsx @@ -40,6 +40,9 @@ export const BootyDetailsModal = () => { start, order, orderBy, + filterBy: { + isExpired: 0, + }, }); const { results, total } = data || {}; diff --git a/src/services/tryberApi/api.ts b/src/services/tryberApi/api.ts index ee5005a4..f3baa4f9 100644 --- a/src/services/tryberApi/api.ts +++ b/src/services/tryberApi/api.ts @@ -1,32 +1,14 @@ // Need to use the React-specific entry point to import createApi import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react"; +import { stringify } from "qs"; // Define a service using a base URL and expected endpoints export const api = createApi({ reducerPath: "tryberApi", baseQuery: fetchBaseQuery({ baseUrl: process.env.REACT_APP_API_URL, - paramsSerializer: (params) => { - let urlps = new URLSearchParams(); - Object.entries(params).forEach(([key, value]) => { - // remove undefined values - if (typeof value === "undefined") { - return; - } - // iterate over nested objects - if (key === "filterBy" && value && typeof value === "object") { - Object.entries(value as Record).forEach(([fk, fv]) => { - if (fv != null) { - urlps.set(`filterBy[${fk}]`, String(fv)); - } - }); - return; - } - // or just set url param - urlps.set(key, value); - }); - return urlps.toString(); - }, + paramsSerializer: (params) => stringify(params, { encodeValuesOnly: true }), + prepareHeaders: (headers, { getState }) => { const { publicUserPages } = getState() as { publicUserPages: { isPublic: boolean; token?: string }; diff --git a/yarn.lock b/yarn.lock index 01f4dd34..20c6cf3d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3592,6 +3592,11 @@ resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.7.tgz#5fe8cf91556bfb310d17f2e2b4263a7c12c2c2ca" integrity sha512-HBPgtzp44867rkL+IzQ3560/E/BlobwCjeXsuKqogrcE99SKgZR4tvBBCuNJZMhUFMz26M7cjKWZg785lllwpA== +"@types/qs@^6.14.0": + version "6.14.0" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.14.0.tgz#d8b60cecf62f2db0fb68e5e006077b9178b85de5" + integrity sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ== + "@types/react-dom@*", "@types/react-dom@17.0.9": version "17.0.9" resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-17.0.9.tgz#441a981da9d7be117042e1a6fd3dac4b30f55add" @@ -5162,6 +5167,14 @@ cache-base@^1.0.1: union-value "^1.0.0" unset-value "^1.0.0" +call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz#4b5428c222be985d79c3d82657479dbe0b59b2d6" + integrity sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ== + dependencies: + es-errors "^1.3.0" + function-bind "^1.1.2" + call-bind@^1.0.0, call-bind@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" @@ -5170,6 +5183,14 @@ call-bind@^1.0.0, call-bind@^1.0.2: function-bind "^1.1.1" get-intrinsic "^1.0.2" +call-bound@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/call-bound/-/call-bound-1.0.4.tgz#238de935d2a2a692928c538c7ccfa91067fd062a" + integrity sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg== + dependencies: + call-bind-apply-helpers "^1.0.2" + get-intrinsic "^1.3.0" + call-me-maybe@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.2.tgz#03f964f19522ba643b1b0693acb9152fe2074baa" @@ -6482,6 +6503,15 @@ draft-js@^0.11.7: immutable "~3.7.4" object-assign "^4.1.1" +dunder-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a" + integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A== + dependencies: + call-bind-apply-helpers "^1.0.1" + es-errors "^1.3.0" + gopd "^1.2.0" + duplexer@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" @@ -6675,6 +6705,16 @@ es-array-method-boxes-properly@^1.0.0: resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e" integrity sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA== +es-define-property@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa" + integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g== + +es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + es-iterator-helpers@^1.0.12, es-iterator-helpers@^1.0.15: version "1.0.15" resolved "https://registry.yarnpkg.com/es-iterator-helpers/-/es-iterator-helpers-1.0.15.tgz#bd81d275ac766431d19305923707c3efd9f1ae40" @@ -6695,6 +6735,13 @@ es-iterator-helpers@^1.0.12, es-iterator-helpers@^1.0.15: iterator.prototype "^1.1.2" safe-array-concat "^1.0.1" +es-object-atoms@^1.0.0, es-object-atoms@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz#1c4f2c4837327597ce69d2ca190a7fdd172338c1" + integrity sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA== + dependencies: + es-errors "^1.3.0" + es-set-tostringtag@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz#338d502f6f674301d710b80c8592de8a15f09cd8" @@ -7706,6 +7753,22 @@ get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@ has-proto "^1.0.1" has-symbols "^1.0.3" +get-intrinsic@^1.2.5, get-intrinsic@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz#743f0e3b6964a93a5491ed1bffaae054d7f98d01" + integrity sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ== + dependencies: + call-bind-apply-helpers "^1.0.2" + es-define-property "^1.0.1" + es-errors "^1.3.0" + es-object-atoms "^1.1.1" + function-bind "^1.1.2" + get-proto "^1.0.1" + gopd "^1.2.0" + has-symbols "^1.1.0" + hasown "^2.0.2" + math-intrinsics "^1.1.0" + get-own-enumerable-property-symbols@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664" @@ -7716,6 +7779,14 @@ get-package-type@^0.1.0: resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== +get-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/get-proto/-/get-proto-1.0.1.tgz#150b3f2743869ef3e851ec0c49d15b1d14d00ee1" + integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g== + dependencies: + dunder-proto "^1.0.1" + es-object-atoms "^1.0.0" + get-stream@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" @@ -7885,6 +7956,11 @@ gopd@^1.0.1: dependencies: get-intrinsic "^1.1.3" +gopd@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" + integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== + graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" @@ -7957,6 +8033,11 @@ has-symbols@^1.0.1, has-symbols@^1.0.2, has-symbols@^1.0.3: resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== +has-symbols@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338" + integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ== + has-tostringtag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" @@ -8024,6 +8105,13 @@ hasown@^2.0.0: dependencies: function-bind "^1.1.2" +hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + he@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" @@ -9990,6 +10078,11 @@ markdown-it@^14.0.0: punycode.js "^2.3.1" uc.micro "^2.1.0" +math-intrinsics@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9" + integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g== + md5.js@^1.3.4: version "1.3.5" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" @@ -10632,6 +10725,11 @@ object-inspect@^1.12.3, object-inspect@^1.9.0: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.0.tgz#42695d3879e1cd5bda6df5062164d80c996e23e2" integrity sha512-HQ4J+ic8hKrgIt3mqk6cVOVrW2ozL4KdvHlqpBv9vDYWx9ysAgENAdvy4FoGF+KFdhR7nQTNm5J0ctAeOwn+3g== +object-inspect@^1.13.3: + version "1.13.4" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.4.tgz#8375265e21bc20d0fa582c22e1b13485d6e00213" + integrity sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew== + object-is@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" @@ -12267,6 +12365,13 @@ qs@^6.11.2: dependencies: side-channel "^1.0.4" +qs@^6.14.0: + version "6.14.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.14.0.tgz#c63fa40680d2c5c941412a0e899c89af60c0a930" + integrity sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w== + dependencies: + side-channel "^1.1.0" + query-string@^4.1.0: version "4.3.4" resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb" @@ -13528,6 +13633,35 @@ should@^13.2.1: should-type-adaptors "^1.0.1" should-util "^1.0.0" +side-channel-list@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/side-channel-list/-/side-channel-list-1.0.0.tgz#10cb5984263115d3b7a0e336591e290a830af8ad" + integrity sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA== + dependencies: + es-errors "^1.3.0" + object-inspect "^1.13.3" + +side-channel-map@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/side-channel-map/-/side-channel-map-1.0.1.tgz#d6bb6b37902c6fef5174e5f533fab4c732a26f42" + integrity sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + get-intrinsic "^1.2.5" + object-inspect "^1.13.3" + +side-channel-weakmap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz#11dda19d5368e40ce9ec2bdc1fb0ecbc0790ecea" + integrity sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + get-intrinsic "^1.2.5" + object-inspect "^1.13.3" + side-channel-map "^1.0.1" + side-channel@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" @@ -13537,6 +13671,17 @@ side-channel@^1.0.4: get-intrinsic "^1.0.2" object-inspect "^1.9.0" +side-channel@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.1.0.tgz#c3fcff9c4da932784873335ec9765fa94ff66bc9" + integrity sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw== + dependencies: + es-errors "^1.3.0" + object-inspect "^1.13.3" + side-channel-list "^1.0.0" + side-channel-map "^1.0.1" + side-channel-weakmap "^1.0.2" + signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.7: version "3.0.7" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" From 8d4aaaaeb820f4871ba94222243da75aa1c417a6 Mon Sep 17 00:00:00 2001 From: Davide Bizzi Date: Fri, 24 Oct 2025 11:28:11 +0200 Subject: [PATCH 31/37] fix: Fix pagination and remove order --- src/pages/Wallet/ExpiredAttributionTable.tsx | 118 ++++++++++++++++++ src/pages/Wallet/WalletTable.tsx | 110 +++++----------- ...dTabColumns.ts => useExpiredTabColumns.ts} | 26 ++-- 3 files changed, 157 insertions(+), 97 deletions(-) create mode 100644 src/pages/Wallet/ExpiredAttributionTable.tsx rename src/pages/Wallet/{expiredTabColumns.ts => useExpiredTabColumns.ts} (53%) diff --git a/src/pages/Wallet/ExpiredAttributionTable.tsx b/src/pages/Wallet/ExpiredAttributionTable.tsx new file mode 100644 index 00000000..1ef4b84c --- /dev/null +++ b/src/pages/Wallet/ExpiredAttributionTable.tsx @@ -0,0 +1,118 @@ +import { Pagination, Table } from "@appquality/appquality-design-system"; +import { useTranslation } from "react-i18next"; +import { currencyTable } from "src/redux/wallet/utils"; +import { useGetUsersMePendingBootyQuery } from "src/services/tryberApi"; +import { useExpiredTabColumns } from "./useExpiredTabColumns"; + +const useExpiredRows = ({ start, limit }: { start: number; limit: number }) => { + const { data: expiredBootyData, isLoading: isExpiredBootyLoading } = + useGetUsersMePendingBootyQuery({ + filterBy: { isExpired: 1 }, + start, + limit, + }); + return { + expiredBootyData: (expiredBootyData?.results || []).map((req) => { + const attributionDate = new Date(req.attributionDate); + const expiredDate = new Date(attributionDate); + expiredDate.setMonth(expiredDate.getMonth() + 12); + return { + key: req.id, + activityName: { + title: req.name, + content: {req.name}, + }, + activityType: { + title: req.activity, + content: {req.activity}, + }, + attributionDate: { + title: req.attributionDate, + content: {req.attributionDate}, + }, + gross: { + title: "€ " + req.amount?.gross?.value, + content: ( + + {req.amount?.gross?.currency && + req.amount?.gross?.currency in currencyTable + ? currencyTable[req.amount?.gross?.currency] + : req.amount?.gross?.currency}{" "} + {req.amount?.gross?.value?.toFixed(2)} + + ), + }, + expiredDate: { + title: expiredDate.toISOString().split("T")[0], + content: {expiredDate.toLocaleDateString()}, + }, + }; + }), + isExpiredBootyLoading, + }; +}; + +const ExpiredAttributionTable = ({ + className, + start, + limit, +}: { + className?: string; + start: number; + limit: number; +}) => { + const { t } = useTranslation(); + + const expiredColumns = useExpiredTabColumns(); + + const { expiredBootyData: expiredRows, isExpiredBootyLoading } = + useExpiredRows({ + start, + limit, + }); + return ( +
+ ); +}; + +const ExpiredAttributionTablePagination = ({ + className, + start, + limit, + maxPages, + changePagination, +}: { + className?: string; + start: number; + limit: number; + maxPages: number; + changePagination: (newPage: number) => void; +}) => { + const { t } = useTranslation(); + + return ( + + t(`Page %current% / %total%`) + .replace("%current%", current.toString()) + .replace("%total%", total ? total.toString() : "0") + } + /> + ); +}; +export { ExpiredAttributionTablePagination }; +export default ExpiredAttributionTable; diff --git a/src/pages/Wallet/WalletTable.tsx b/src/pages/Wallet/WalletTable.tsx index cbd50f21..f51cf260 100644 --- a/src/pages/Wallet/WalletTable.tsx +++ b/src/pages/Wallet/WalletTable.tsx @@ -18,6 +18,7 @@ import pdfDisabledIcon from "src/pages/Wallet/assets/pdfDisabled.svg"; import pdfHoverIcon from "src/pages/Wallet/assets/pdfHover.svg"; import twIcon from "src/pages/Wallet/assets/transferwise.svg"; import { walletColumns } from "src/pages/Wallet/columns"; +import useTabFragment from "src/pages/Wallet/WalletTabFragment"; import { useAppDispatch } from "src/redux/provider"; import { updatePagination } from "src/redux/wallet/actionCreator"; import { openPaymentDetailsModal } from "src/redux/wallet/actions/openPaymentDetailsModal"; @@ -27,8 +28,9 @@ import { useGetUsersMePendingBootyQuery, } from "src/services/tryberApi"; import styled from "styled-components"; -import useTabFragment from "src/pages/Wallet/WalletTabFragment"; -import { expiredTabColumns } from "./expiredTabColumns"; +import ExpiredAttributionTable, { + ExpiredAttributionTablePagination, +} from "./ExpiredAttributionTable"; const ActionsCell = styled.div` display: flex; @@ -107,10 +109,10 @@ export const WalletTable = () => { const { t } = useTranslation(); const dispatch = useAppDispatch(); const [columns, setcolumns] = useState([]); - const [expiredColumns, setExpiredColumns] = useState([]); + const expirationTableLimit = 10; + const [expirationTableStart, setExpirationTableStart] = useState(0); const [rows, setRows] = useState([]); - const [expiredRows, setExpiredRows] = useState([]); const { activeTab, setActiveTab } = useTabFragment(); @@ -134,8 +136,6 @@ export const WalletTable = () => { useEffect(() => { const cols = walletColumns(dispatch, t); setcolumns(cols); - const expiredCols = expiredTabColumns(dispatch, t); - setExpiredColumns(expiredCols); }, []); // update datasource for the table useEffect(() => { @@ -243,48 +243,6 @@ export const WalletTable = () => { } }, [data]); - useEffect(() => { - if (typeof expiredBootyData?.results !== "undefined") { - setExpiredRows( - expiredBootyData.results.map((req) => { - const attributionDate = new Date(req.attributionDate); - const expiredDate = new Date(attributionDate); - expiredDate.setMonth(expiredDate.getMonth() + 12); - return { - key: req.id, - activityName: { - title: req.name, - content: {req.name}, - }, - activityType: { - title: req.activity, - content: {req.activity}, - }, - attributionDate: { - title: req.attributionDate, - content: {req.attributionDate}, - }, - gross: { - title: "€ " + req.amount?.gross?.value, - content: ( - - {req.amount?.gross?.currency && - req.amount?.gross?.currency in currencyTable - ? currencyTable[req.amount?.gross?.currency] - : req.amount?.gross?.currency}{" "} - {req.amount?.gross?.value?.toFixed(2)} - - ), - }, - expiredDate: { - title: expiredDate.toISOString().split("T")[0], - content: {expiredDate.toLocaleDateString()}, - }, - }; - }) - ); - } - }, [expiredBootyData]); const changePagination = (newPage: number) => { const newStart = limit * (newPage - 1); dispatch(updatePagination(newStart)); @@ -319,53 +277,47 @@ export const WalletTable = () => { empty: t("__WALLET_HOME-EMPTY_STATE_MAX: 105"), }} /> + + t(`Page %current% / %total%`) + .replace("%current%", current.toString()) + .replace("%total%", total ? total.toString() : "0") + } + /> {t("__WALLET_EXPIRED_TAB")} } > - {columns.length > 0 && ( - - )}

-
+ { + const newStart = expirationTableLimit * (page - 1); + setExpirationTableStart(newStart); }} + start={expirationTableStart} + limit={expirationTableLimit} + maxPages={Math.ceil((data?.total || 0) / expirationTableLimit)} /> - - t(`Page %current% / %total%`) - .replace("%current%", current.toString()) - .replace("%total%", total ? total.toString() : "0") - } - /> ); }; diff --git a/src/pages/Wallet/expiredTabColumns.ts b/src/pages/Wallet/useExpiredTabColumns.ts similarity index 53% rename from src/pages/Wallet/expiredTabColumns.ts rename to src/pages/Wallet/useExpiredTabColumns.ts index fb0a015c..f8a92831 100644 --- a/src/pages/Wallet/expiredTabColumns.ts +++ b/src/pages/Wallet/useExpiredTabColumns.ts @@ -1,16 +1,14 @@ import { Column } from "@appquality/appquality-design-system/dist/stories/table/_types"; -import { TFunction } from "react-i18next"; -import { updateSortingOptions } from "src/redux/wallet/actionCreator"; +import { useTranslation } from "react-i18next"; -export const expiredTabColumns = ( - dispatch: AppDispatch, - t: TFunction<"translation"> -): Column[] => { +export const useExpiredTabColumns = (): Column[] => { + const { t } = useTranslation(); return [ { title: t("Activity name"), dataIndex: "activityName", key: "activityName", + isSortable: false, maxWidth: "max-content", }, { @@ -18,34 +16,26 @@ export const expiredTabColumns = ( dataIndex: "activityType", key: "activityType", role: "overline", + isSortable: false, hideIndex: true, }, { title: t("Attribution date"), dataIndex: "attributionDate", key: "attributionDate", - isSortable: true, - onSort: (newOrder) => { - // dispatch(updateSortingOptions(newOrder, "attributionDate")); - }, + isSortable: false, }, { title: t("Gross total"), dataIndex: "gross", key: "gross", - isSortable: true, - onSort: (newOrder) => { - dispatch(updateSortingOptions(newOrder, "gross")); - }, + isSortable: false, }, { title: t("Expired On"), dataIndex: "expiredDate", key: "expiredDate", - isSortable: true, - onSort: (newOrder: OrderType) => { - // dispatch(updateSortingOptions(newOrder, "expiredDate")); - }, + isSortable: false, }, ]; }; From 88ab2430240ad5ec59226b7602f534f5a302bc4e Mon Sep 17 00:00:00 2001 From: Kariamos Date: Fri, 24 Oct 2025 14:34:17 +0200 Subject: [PATCH 32/37] feat: Format dates in Italian locale for attribution and expiration dates --- src/pages/Wallet/ExpiredAttributionTable.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/pages/Wallet/ExpiredAttributionTable.tsx b/src/pages/Wallet/ExpiredAttributionTable.tsx index 1ef4b84c..831d60ce 100644 --- a/src/pages/Wallet/ExpiredAttributionTable.tsx +++ b/src/pages/Wallet/ExpiredAttributionTable.tsx @@ -28,7 +28,11 @@ const useExpiredRows = ({ start, limit }: { start: number; limit: number }) => { }, attributionDate: { title: req.attributionDate, - content: {req.attributionDate}, + content: ( + + {new Date(req.attributionDate).toLocaleDateString("it-IT")} + + ), }, gross: { title: "€ " + req.amount?.gross?.value, @@ -44,7 +48,7 @@ const useExpiredRows = ({ start, limit }: { start: number; limit: number }) => { }, expiredDate: { title: expiredDate.toISOString().split("T")[0], - content: {expiredDate.toLocaleDateString()}, + content: {expiredDate.toLocaleDateString("it-IT")}, }, }; }), From 4ee4dc28cca3cc3e2982f1feaff0da6f1c53e20f Mon Sep 17 00:00:00 2001 From: ZecD Date: Mon, 27 Oct 2025 17:59:10 +0100 Subject: [PATCH 33/37] Added limitations to video and image files to dropzone manual --- src/pages/Manual/UseCases/MediaDropzone.tsx | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/pages/Manual/UseCases/MediaDropzone.tsx b/src/pages/Manual/UseCases/MediaDropzone.tsx index 37f59cb6..83aea05e 100644 --- a/src/pages/Manual/UseCases/MediaDropzone.tsx +++ b/src/pages/Manual/UseCases/MediaDropzone.tsx @@ -77,6 +77,18 @@ export const MediaDropzone = ({ const uploadMedia = async (files: File[]) => { files.forEach((f) => { + if (f.type && !f.type.includes("image/") && !f.type.includes("video/")) { + dispatch( + appendMediaList( + createFilesElementList({ + files: [f], + status: "failed", + taskId, + }) + ) + ); + return; + } const formData = new FormData(); formData.append("media", f, normalizeFileName(f.name)); if (!campaign) return; From 1183b285a8fd9ad636474bbd818a66a9dfebc255 Mon Sep 17 00:00:00 2001 From: ZecD Date: Tue, 28 Oct 2025 11:24:58 +0100 Subject: [PATCH 34/37] added mimetype --- src/pages/Manual/UseCases/MediaDropzone.tsx | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/src/pages/Manual/UseCases/MediaDropzone.tsx b/src/pages/Manual/UseCases/MediaDropzone.tsx index 83aea05e..39d41a03 100644 --- a/src/pages/Manual/UseCases/MediaDropzone.tsx +++ b/src/pages/Manual/UseCases/MediaDropzone.tsx @@ -77,18 +77,6 @@ export const MediaDropzone = ({ const uploadMedia = async (files: File[]) => { files.forEach((f) => { - if (f.type && !f.type.includes("image/") && !f.type.includes("video/")) { - dispatch( - appendMediaList( - createFilesElementList({ - files: [f], - status: "failed", - taskId, - }) - ) - ); - return; - } const formData = new FormData(); formData.append("media", f, normalizeFileName(f.name)); if (!campaign) return; @@ -158,14 +146,7 @@ export const MediaDropzone = ({ m.status !== "uploading" ? onDelete({ From a2972be85268a1eb12fe9cf27f40faf0985a046f Mon Sep 17 00:00:00 2001 From: Kariamos Date: Tue, 28 Oct 2025 12:36:42 +0100 Subject: [PATCH 35/37] fix: Update expired booty tab disabled state logic --- src/pages/Wallet/WalletTable.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pages/Wallet/WalletTable.tsx b/src/pages/Wallet/WalletTable.tsx index f51cf260..52cfeee4 100644 --- a/src/pages/Wallet/WalletTable.tsx +++ b/src/pages/Wallet/WalletTable.tsx @@ -132,6 +132,7 @@ export const WalletTable = () => { useGetUsersMePendingBootyQuery({ filterBy: { isExpired: 1 }, }); + // initial requests useEffect(() => { const cols = walletColumns(dispatch, t); @@ -291,7 +292,7 @@ export const WalletTable = () => { {t("__WALLET_EXPIRED_TAB")} } From a1f343f98f355c14fb0648574300c28c2df085c8 Mon Sep 17 00:00:00 2001 From: ZecD Date: Tue, 28 Oct 2025 13:00:23 +0100 Subject: [PATCH 36/37] fixed file upload broken link --- src/pages/Manual/UseCases/MediaDropzone.tsx | 16 ++++++++++++---- src/services/tryberApi/index.ts | 1 + src/utils/schema.ts | 1 + 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/pages/Manual/UseCases/MediaDropzone.tsx b/src/pages/Manual/UseCases/MediaDropzone.tsx index 39d41a03..2cee9552 100644 --- a/src/pages/Manual/UseCases/MediaDropzone.tsx +++ b/src/pages/Manual/UseCases/MediaDropzone.tsx @@ -98,7 +98,6 @@ export const MediaDropzone = ({ ); }); }; - return ( <> @@ -146,7 +146,15 @@ export const MediaDropzone = ({ m.status !== "uploading" ? onDelete({ diff --git a/src/services/tryberApi/index.ts b/src/services/tryberApi/index.ts index 597aceca..0f17ed6b 100644 --- a/src/services/tryberApi/index.ts +++ b/src/services/tryberApi/index.ts @@ -2859,6 +2859,7 @@ export type GetUsersMeCampaignsByCampaignIdTasksAndTaskIdMediaApiResponse = id: number; location: string; name: string; + mimetype?: string; }[]; }; export type GetUsersMeCampaignsByCampaignIdTasksAndTaskIdMediaApiArg = { diff --git a/src/utils/schema.ts b/src/utils/schema.ts index 6e52f5c7..774f0d9f 100644 --- a/src/utils/schema.ts +++ b/src/utils/schema.ts @@ -4424,6 +4424,7 @@ export interface operations { id: number; location: string; name: string; + mimetype?: string; }[]; }; }; From 4fa7af01364e9d55433ab2dff922b309b64f4a0a Mon Sep 17 00:00:00 2001 From: "Luca Cannarozzo (@cannarocks)" Date: Tue, 28 Oct 2025 15:11:15 +0100 Subject: [PATCH 37/37] fix: Update iframe source URLs in FeedbackModal and FiscalResidenceModal --- src/pages/Dashboard/FeedbackModal.tsx | 8 ++++---- .../Profile/TabFiscal/components/FiscalResidenceModal.tsx | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/pages/Dashboard/FeedbackModal.tsx b/src/pages/Dashboard/FeedbackModal.tsx index 594ac55c..8e083a05 100644 --- a/src/pages/Dashboard/FeedbackModal.tsx +++ b/src/pages/Dashboard/FeedbackModal.tsx @@ -1,5 +1,5 @@ import { Button, Modal, ModalBody } from "@appquality/appquality-design-system"; -import { ChatLeftDots } from "react-bootstrap-icons"; +import { Headset } from "react-bootstrap-icons"; import { useTranslation } from "react-i18next"; import { useGetUsersMeQuery } from "src/services/tryberApi"; import styled from "styled-components"; @@ -27,7 +27,7 @@ export const FeedbackModal = ({