diff --git a/CHANGELOG.md b/CHANGELOG.md index c298aa6d..caceb6de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] +### Added + +- Feature related to one to many feature, it's possible to change the current organization by using the user widget on the top of storefront + +### Changed + +- it was grouped the graphql Queries in order to improve the performance on the storefront user widget + ## [1.14.3] - 2022-10-21 ### Changed diff --git a/messages/ar.json b/messages/ar.json index 3d21f03a..30b4cc07 100644 --- a/messages/ar.json +++ b/messages/ar.json @@ -286,5 +286,7 @@ "store/b2b-organizations.user-widget.impersonating": "تعيين مستخدم:", "store/b2b-organizations.request-new-organization.submit-button.create-new-request": "إنشاء طلب جديد", "store/b2b-organizations.stop-impersonation": "إيقاف تعيين المستخدم", - "store/b2b-organizations.stop-impersonation-error": "خطأ في إيقاف تعيين المستخدم. راجع وحدة التحكم للحصول على التفاصيل." + "store/b2b-organizations.stop-impersonation-error": "خطأ في إيقاف تعيين المستخدم. راجع وحدة التحكم للحصول على التفاصيل.", + "store/b2b-organizations.set-current-organization": "Set current organization", + "store/b2b-organizations.set-organization-error": "Error setting current organization. See console for details." } diff --git a/messages/bg.json b/messages/bg.json index 7e9ea410..aa2f5c59 100644 --- a/messages/bg.json +++ b/messages/bg.json @@ -286,5 +286,7 @@ "store/b2b-organizations.user-widget.impersonating": "Въплъщаване:", "store/b2b-organizations.request-new-organization.submit-button.create-new-request": "Създаване на нова заявка", "store/b2b-organizations.stop-impersonation": "Спиране на въплъщаването", - "store/b2b-organizations.stop-impersonation-error": "Грешка при спиране на въплъщаването. Вижте конзолата за подробности." + "store/b2b-organizations.stop-impersonation-error": "Грешка при спиране на въплъщаването. Вижте конзолата за подробности.", + "store/b2b-organizations.set-current-organization": "Set current organization", + "store/b2b-organizations.set-organization-error": "Error setting current organization. See console for details." } diff --git a/messages/ca.json b/messages/ca.json index 797f11bd..c45f8a6a 100644 --- a/messages/ca.json +++ b/messages/ca.json @@ -286,5 +286,7 @@ "store/b2b-organizations.user-widget.impersonating": "S'està suplantant:", "store/b2b-organizations.request-new-organization.submit-button.create-new-request": "Crea una sol·licitud", "store/b2b-organizations.stop-impersonation": "Atura la suplantació", - "store/b2b-organizations.stop-impersonation-error": "S'ha produït un error en aturar la suplantació. Per obtenir-ne més informació, consulteu la consola." + "store/b2b-organizations.stop-impersonation-error": "S'ha produït un error en aturar la suplantació. Per obtenir-ne més informació, consulteu la consola.", + "store/b2b-organizations.set-current-organization": "Set current organization", + "store/b2b-organizations.set-organization-error": "Error setting current organization. See console for details." } diff --git a/messages/context.json b/messages/context.json index cf9b6480..592737b5 100644 --- a/messages/context.json +++ b/messages/context.json @@ -286,5 +286,7 @@ "store/b2b-organizations.user-widget.impersonating": "store/b2b-organizations.user-widget.impersonating", "store/b2b-organizations.request-new-organization.submit-button.create-new-request": "store/b2b-organizations.request-new-organization.submit-button.create-new-request", "store/b2b-organizations.stop-impersonation": "store/b2b-organizations.stop-impersonation", - "store/b2b-organizations.stop-impersonation-error": "store/b2b-organizations.stop-impersonation-error" + "store/b2b-organizations.stop-impersonation-error": "store/b2b-organizations.stop-impersonation-error", + "store/b2b-organizations.set-current-organization": "store/b2b-organizations.set-current-organization", + "store/b2b-organizations.set-organization-error": "store/b2b-organizations.set-organization-error" } diff --git a/messages/cs.json b/messages/cs.json index 23c59ec3..a8388dda 100644 --- a/messages/cs.json +++ b/messages/cs.json @@ -286,5 +286,7 @@ "store/b2b-organizations.user-widget.impersonating": "Vydává se za:", "store/b2b-organizations.request-new-organization.submit-button.create-new-request": "Vytvořit novou žádost", "store/b2b-organizations.stop-impersonation": "Přestat se vydávat za jiného uživatele", - "store/b2b-organizations.stop-impersonation-error": "Zastavení vydávání se za jiného uživatele selhalo. Podrobnosti naleznete v konzoli." + "store/b2b-organizations.stop-impersonation-error": "Zastavení vydávání se za jiného uživatele selhalo. Podrobnosti naleznete v konzoli.", + "store/b2b-organizations.set-current-organization": "Set current organization", + "store/b2b-organizations.set-organization-error": "Error setting current organization. See console for details." } diff --git a/messages/da.json b/messages/da.json index 3852db27..ea01dfa9 100644 --- a/messages/da.json +++ b/messages/da.json @@ -286,5 +286,7 @@ "store/b2b-organizations.user-widget.impersonating": "Efterligner:", "store/b2b-organizations.request-new-organization.submit-button.create-new-request": "Opret ny forespørgsel", "store/b2b-organizations.stop-impersonation": "Stop efterligning", - "store/b2b-organizations.stop-impersonation-error": "Fejl med at stoppe efterligning. Se konsol for detaljer." + "store/b2b-organizations.stop-impersonation-error": "Fejl med at stoppe efterligning. Se konsol for detaljer.", + "store/b2b-organizations.set-current-organization": "Set current organization", + "store/b2b-organizations.set-organization-error": "Error setting current organization. See console for details." } diff --git a/messages/de.json b/messages/de.json index 1eade004..1d92d465 100644 --- a/messages/de.json +++ b/messages/de.json @@ -286,5 +286,7 @@ "store/b2b-organizations.user-widget.impersonating": "Identitätswechsel:", "store/b2b-organizations.request-new-organization.submit-button.create-new-request": "Neue Anfrage erstellen", "store/b2b-organizations.stop-impersonation": "Identitätswechsel abbrechen", - "store/b2b-organizations.stop-impersonation-error": "Fehler beim Abbruch des Identitätswechsels. Siehe Konsole für Details." + "store/b2b-organizations.stop-impersonation-error": "Fehler beim Abbruch des Identitätswechsels. Siehe Konsole für Details.", + "store/b2b-organizations.set-current-organization": "Set current organization", + "store/b2b-organizations.set-organization-error": "Error setting current organization. See console for details." } diff --git a/messages/el.json b/messages/el.json index 101b3841..82be05f5 100644 --- a/messages/el.json +++ b/messages/el.json @@ -286,5 +286,7 @@ "store/b2b-organizations.user-widget.impersonating": "Γίνεται προσωποποίηση:", "store/b2b-organizations.request-new-organization.submit-button.create-new-request": "Δημιουργία νέου αιτήματος", "store/b2b-organizations.stop-impersonation": "Διακοπή προσωποποίησης", - "store/b2b-organizations.stop-impersonation-error": "Σφάλμα κατά τη διακοπή της προσωποποίησης. Δείτε την κονσόλα για λεπτομέρειες." + "store/b2b-organizations.stop-impersonation-error": "Σφάλμα κατά τη διακοπή της προσωποποίησης. Δείτε την κονσόλα για λεπτομέρειες.", + "store/b2b-organizations.set-current-organization": "Set current organization", + "store/b2b-organizations.set-organization-error": "Error setting current organization. See console for details." } diff --git a/messages/en.json b/messages/en.json index 6a041871..0bd32017 100644 --- a/messages/en.json +++ b/messages/en.json @@ -286,5 +286,7 @@ "store/b2b-organizations.user-widget.impersonating": "Impersonating:", "store/b2b-organizations.request-new-organization.submit-button.create-new-request": "Create New Request", "store/b2b-organizations.stop-impersonation": "Stop Impersonation", - "store/b2b-organizations.stop-impersonation-error": "Error stopping impersonation. See console for details." + "store/b2b-organizations.stop-impersonation-error": "Error stopping impersonation. See console for details.", + "store/b2b-organizations.set-current-organization": "Set current organization", + "store/b2b-organizations.set-organization-error": "Error setting current organization. See console for details." } diff --git a/messages/es.json b/messages/es.json index fa8408e4..41490a5a 100644 --- a/messages/es.json +++ b/messages/es.json @@ -286,5 +286,7 @@ "store/b2b-organizations.user-widget.impersonating": "Suplantando a:", "store/b2b-organizations.request-new-organization.submit-button.create-new-request": "Crear nueva solicitud", "store/b2b-organizations.stop-impersonation": "Detener suplantación", - "store/b2b-organizations.stop-impersonation-error": "Error al detener la suplantación. Consulta la consola para ver los detalles." + "store/b2b-organizations.stop-impersonation-error": "Error al detener la suplantación. Consulta la consola para ver los detalles.", + "store/b2b-organizations.set-current-organization": "Set current organization", + "store/b2b-organizations.set-organization-error": "Error setting current organization. See console for details." } diff --git a/messages/fi.json b/messages/fi.json index 51995bfe..32ab54e0 100644 --- a/messages/fi.json +++ b/messages/fi.json @@ -286,5 +286,7 @@ "store/b2b-organizations.user-widget.impersonating": "Esiinny käyttäjänä:", "store/b2b-organizations.request-new-organization.submit-button.create-new-request": "Luo uusi pyyntö", "store/b2b-organizations.stop-impersonation": "Lopeta tekeytyminen toiseksi käyttäjäksi", - "store/b2b-organizations.stop-impersonation-error": "Virhe toiseksi käyttäjäksi tekeytymisen lopettamisessa. Katso lisätietoja konsolista." + "store/b2b-organizations.stop-impersonation-error": "Virhe toiseksi käyttäjäksi tekeytymisen lopettamisessa. Katso lisätietoja konsolista.", + "store/b2b-organizations.set-current-organization": "Set current organization", + "store/b2b-organizations.set-organization-error": "Error setting current organization. See console for details." } diff --git a/messages/fr.json b/messages/fr.json index 1d3cc76c..2b64414f 100644 --- a/messages/fr.json +++ b/messages/fr.json @@ -286,5 +286,7 @@ "store/b2b-organizations.user-widget.impersonating": "Emprunt d’identité :", "store/b2b-organizations.request-new-organization.submit-button.create-new-request": "Créer une nouvelle demande", "store/b2b-organizations.stop-impersonation": "Arrêter l’emprunt d’identité", - "store/b2b-organizations.stop-impersonation-error": "Erreur lors de l’arrêt de l’emprunt d’identité. Voir la console pour plus de détails." + "store/b2b-organizations.stop-impersonation-error": "Erreur lors de l’arrêt de l’emprunt d’identité. Voir la console pour plus de détails.", + "store/b2b-organizations.set-current-organization": "Set current organization", + "store/b2b-organizations.set-organization-error": "Error setting current organization. See console for details." } diff --git a/messages/it.json b/messages/it.json index fe9cf5a7..360f0e0a 100644 --- a/messages/it.json +++ b/messages/it.json @@ -286,5 +286,7 @@ "store/b2b-organizations.user-widget.impersonating": "Impersonando:", "store/b2b-organizations.request-new-organization.submit-button.create-new-request": "Crea nuova richiesta", "store/b2b-organizations.stop-impersonation": "Interrompi personificazione", - "store/b2b-organizations.stop-impersonation-error": "Errore durante il tentativo di interrompere la personificazione. Visualizza la console per i dettagli." + "store/b2b-organizations.stop-impersonation-error": "Errore durante il tentativo di interrompere la personificazione. Visualizza la console per i dettagli.", + "store/b2b-organizations.set-current-organization": "Set current organization", + "store/b2b-organizations.set-organization-error": "Error setting current organization. See console for details." } diff --git a/messages/ja.json b/messages/ja.json index e8cd1203..b6ce25db 100644 --- a/messages/ja.json +++ b/messages/ja.json @@ -286,5 +286,7 @@ "store/b2b-organizations.user-widget.impersonating": "偽装中:", "store/b2b-organizations.request-new-organization.submit-button.create-new-request": "新規リクエストを作成します", "store/b2b-organizations.stop-impersonation": "偽装を停止する", - "store/b2b-organizations.stop-impersonation-error": "偽装の停止中にエラーが発生しました。詳細はコンソールを確認してください。" + "store/b2b-organizations.stop-impersonation-error": "偽装の停止中にエラーが発生しました。詳細はコンソールを確認してください。", + "store/b2b-organizations.set-current-organization": "Set current organization", + "store/b2b-organizations.set-organization-error": "Error setting current organization. See console for details." } diff --git a/messages/ko.json b/messages/ko.json index efc710e4..78f486b1 100644 --- a/messages/ko.json +++ b/messages/ko.json @@ -286,5 +286,7 @@ "store/b2b-organizations.user-widget.impersonating": "가장:", "store/b2b-organizations.request-new-organization.submit-button.create-new-request": "새 요청 만들기", "store/b2b-organizations.stop-impersonation": "가장 중지", - "store/b2b-organizations.stop-impersonation-error": "가장을 중지하는 동안 오류가 발생했습니다. 자세한 내용은 콘솔을 참조하세요." + "store/b2b-organizations.stop-impersonation-error": "가장을 중지하는 동안 오류가 발생했습니다. 자세한 내용은 콘솔을 참조하세요.", + "store/b2b-organizations.set-current-organization": "Set current organization", + "store/b2b-organizations.set-organization-error": "Error setting current organization. See console for details." } diff --git a/messages/nl.json b/messages/nl.json index 446314e1..7f201a11 100644 --- a/messages/nl.json +++ b/messages/nl.json @@ -286,5 +286,7 @@ "store/b2b-organizations.user-widget.impersonating": "Impersoneer:", "store/b2b-organizations.request-new-organization.submit-button.create-new-request": "Nieuwe aanvraag aanmaken", "store/b2b-organizations.stop-impersonation": "Stop impersonatie", - "store/b2b-organizations.stop-impersonation-error": "Fout bij stoppen impersonatie. Zie console voor details." + "store/b2b-organizations.stop-impersonation-error": "Fout bij stoppen impersonatie. Zie console voor details.", + "store/b2b-organizations.set-current-organization": "Set current organization", + "store/b2b-organizations.set-organization-error": "Error setting current organization. See console for details." } diff --git a/messages/no.json b/messages/no.json index ec862671..642f3e0b 100644 --- a/messages/no.json +++ b/messages/no.json @@ -286,5 +286,7 @@ "store/b2b-organizations.user-widget.impersonating": "Etterligner:", "store/b2b-organizations.request-new-organization.submit-button.create-new-request": "Opprett ny forespørsel", "store/b2b-organizations.stop-impersonation": "Stopp etterligning", - "store/b2b-organizations.stop-impersonation-error": "Feil ved stopp av etterligning. Se konsoll for mer informasjon." + "store/b2b-organizations.stop-impersonation-error": "Feil ved stopp av etterligning. Se konsoll for mer informasjon.", + "store/b2b-organizations.set-current-organization": "Set current organization", + "store/b2b-organizations.set-organization-error": "Error setting current organization. See console for details." } diff --git a/messages/pl.json b/messages/pl.json index 2ea4f717..b545fb5f 100644 --- a/messages/pl.json +++ b/messages/pl.json @@ -286,5 +286,7 @@ "store/b2b-organizations.user-widget.impersonating": "Odgrywanie roli:", "store/b2b-organizations.request-new-organization.submit-button.create-new-request": "Utwórz nowe żądanie", "store/b2b-organizations.stop-impersonation": "Zatrzymaj odgrywanie roli", - "store/b2b-organizations.stop-impersonation-error": "Wystąpił błąd podczas zatrzymywania odgrywania roli. Zobacz konsolę, aby poznać szczegóły." + "store/b2b-organizations.stop-impersonation-error": "Wystąpił błąd podczas zatrzymywania odgrywania roli. Zobacz konsolę, aby poznać szczegóły.", + "store/b2b-organizations.set-current-organization": "Set current organization", + "store/b2b-organizations.set-organization-error": "Error setting current organization. See console for details." } diff --git a/messages/pt.json b/messages/pt.json index bfd375d4..6cf68649 100644 --- a/messages/pt.json +++ b/messages/pt.json @@ -286,5 +286,7 @@ "store/b2b-organizations.user-widget.impersonating": "Personificando:", "store/b2b-organizations.request-new-organization.submit-button.create-new-request": "Criar nova solicitação", "store/b2b-organizations.stop-impersonation": "Interromper personificação", - "store/b2b-organizations.stop-impersonation-error": "Erro ao interromper a personificação. Consulte o console para mais detalhes." + "store/b2b-organizations.stop-impersonation-error": "Erro ao interromper a personificação. Consulte o console para mais detalhes.", + "store/b2b-organizations.set-current-organization": "Set current organization", + "store/b2b-organizations.set-organization-error": "Error setting current organization. See console for details." } diff --git a/messages/ro.json b/messages/ro.json index 049a3125..011a2225 100644 --- a/messages/ro.json +++ b/messages/ro.json @@ -286,5 +286,7 @@ "store/b2b-organizations.user-widget.impersonating": "Înlocuiește:", "store/b2b-organizations.request-new-organization.submit-button.create-new-request": "Creare solicitare nouă", "store/b2b-organizations.stop-impersonation": "Oprește înlocuirea", - "store/b2b-organizations.stop-impersonation-error": "Eroare la oprirea înlocuirii. Vezi consola pentru detalii." + "store/b2b-organizations.stop-impersonation-error": "Eroare la oprirea înlocuirii. Vezi consola pentru detalii.", + "store/b2b-organizations.set-current-organization": "Set current organization", + "store/b2b-organizations.set-organization-error": "Error setting current organization. See console for details." } diff --git a/messages/ru.json b/messages/ru.json index 91746bda..0ba403d9 100644 --- a/messages/ru.json +++ b/messages/ru.json @@ -286,5 +286,7 @@ "store/b2b-organizations.user-widget.impersonating": "Работа от имени другого лица:", "store/b2b-organizations.request-new-organization.submit-button.create-new-request": "Создать новый запрос", "store/b2b-organizations.stop-impersonation": "Остановить работу от имени другого лица", - "store/b2b-organizations.stop-impersonation-error": "Сбой остановки работы от имени другого лица. Подробная информация доступна на консоли." + "store/b2b-organizations.stop-impersonation-error": "Сбой остановки работы от имени другого лица. Подробная информация доступна на консоли.", + "store/b2b-organizations.set-current-organization": "Set current organization", + "store/b2b-organizations.set-organization-error": "Error setting current organization. See console for details." } diff --git a/messages/sk.json b/messages/sk.json index 55e96293..19ce9d37 100644 --- a/messages/sk.json +++ b/messages/sk.json @@ -286,5 +286,7 @@ "store/b2b-organizations.user-widget.impersonating": "Vydávanie sa za používateľa:", "store/b2b-organizations.request-new-organization.submit-button.create-new-request": "Vytvoriť novú požiadavku", "store/b2b-organizations.stop-impersonation": "Zastaviť vydávanie sa za používateľa", - "store/b2b-organizations.stop-impersonation-error": "Vyskytla sa chyba pri zastavení vydávanie sa za používateľa. Podrobnosti nájdete v konzole." + "store/b2b-organizations.stop-impersonation-error": "Vyskytla sa chyba pri zastavení vydávanie sa za používateľa. Podrobnosti nájdete v konzole.", + "store/b2b-organizations.set-current-organization": "Set current organization", + "store/b2b-organizations.set-organization-error": "Error setting current organization. See console for details." } diff --git a/messages/sl.json b/messages/sl.json index b954661d..991fc9a7 100644 --- a/messages/sl.json +++ b/messages/sl.json @@ -286,5 +286,7 @@ "store/b2b-organizations.user-widget.impersonating": "Oponašanje:", "store/b2b-organizations.request-new-organization.submit-button.create-new-request": "Ustvari novo zahtevo", "store/b2b-organizations.stop-impersonation": "Nehaj oponašati", - "store/b2b-organizations.stop-impersonation-error": "Napaka pri zaustavitvi oponašanja. Za podrobnosti glejte konzolo." + "store/b2b-organizations.stop-impersonation-error": "Napaka pri zaustavitvi oponašanja. Za podrobnosti glejte konzolo.", + "store/b2b-organizations.set-current-organization": "Set current organization", + "store/b2b-organizations.set-organization-error": "Error setting current organization. See console for details." } diff --git a/messages/sv.json b/messages/sv.json index 32c2c4ce..92bb82fa 100644 --- a/messages/sv.json +++ b/messages/sv.json @@ -286,5 +286,7 @@ "store/b2b-organizations.user-widget.impersonating": "Uppträder som:", "store/b2b-organizations.request-new-organization.submit-button.create-new-request": "Skapa ny förfrågan", "store/b2b-organizations.stop-impersonation": "Sluta uppträdandet", - "store/b2b-organizations.stop-impersonation-error": "Det inge inte att stoppa uppträdandet. Se konsolen för detaljer." + "store/b2b-organizations.stop-impersonation-error": "Det inge inte att stoppa uppträdandet. Se konsolen för detaljer.", + "store/b2b-organizations.set-current-organization": "Set current organization", + "store/b2b-organizations.set-organization-error": "Error setting current organization. See console for details." } diff --git a/messages/th.json b/messages/th.json index 75744e74..68499604 100644 --- a/messages/th.json +++ b/messages/th.json @@ -286,5 +286,7 @@ "store/b2b-organizations.user-widget.impersonating": "การเลียนแบบ", "store/b2b-organizations.request-new-organization.submit-button.create-new-request": "สร้างคำขอใหม่", "store/b2b-organizations.stop-impersonation": "หยุดการเลียนแบบ", - "store/b2b-organizations.stop-impersonation-error": "มีข้อผิดพลาดในการหยุดเลียนแบบ โปรดดูรายละเอียดในคอนโซล" + "store/b2b-organizations.stop-impersonation-error": "มีข้อผิดพลาดในการหยุดเลียนแบบ โปรดดูรายละเอียดในคอนโซล", + "store/b2b-organizations.set-current-organization": "Set current organization", + "store/b2b-organizations.set-organization-error": "Error setting current organization. See console for details." } diff --git a/messages/uk.json b/messages/uk.json index a6a9674b..c94e8d83 100644 --- a/messages/uk.json +++ b/messages/uk.json @@ -286,5 +286,7 @@ "store/b2b-organizations.user-widget.impersonating": "Імітація:", "store/b2b-organizations.request-new-organization.submit-button.create-new-request": "Створити новий запит", "store/b2b-organizations.stop-impersonation": "Зупинити імітацію", - "store/b2b-organizations.stop-impersonation-error": "Помилка при зупинці імітації. Докладніша інформація доступна на консолі." + "store/b2b-organizations.stop-impersonation-error": "Помилка при зупинці імітації. Докладніша інформація доступна на консолі.", + "store/b2b-organizations.set-current-organization": "Set current organization", + "store/b2b-organizations.set-organization-error": "Error setting current organization. See console for details." } diff --git a/react/components/UserWidget.tsx b/react/components/UserWidget.tsx index 8b72911d..5875aa67 100644 --- a/react/components/UserWidget.tsx +++ b/react/components/UserWidget.tsx @@ -1,18 +1,19 @@ -import React, { useState } from 'react' +import React, { Fragment, useEffect, useState } from 'react' import type { FunctionComponent } from 'react' import { useQuery, useMutation } from 'react-apollo' import { useIntl, FormattedMessage } from 'react-intl' -import { Button, Tag } from 'vtex.styleguide' +import { AutocompleteInput, Button, Tag } from 'vtex.styleguide' import { useCssHandles } from 'vtex.css-handles' import { useRuntime } from 'vtex.render-runtime' -import { userWidgetMessages as messages } from './utils/messages' +import { + organizationMessages as storeMessages, + userWidgetMessages as messages, +} from './utils/messages' import storageFactory from '../utils/storage' import { useSessionResponse } from '../modules/session' -import GET_PERMISSIONS from '../graphql/getPermissions.graphql' -import GET_ORGANIZATION from '../graphql/getOrganizationStorefront.graphql' -import GET_COST_CENTER from '../graphql/getCostCenterStorefront.graphql' -import CHECK_IMPERSONATION from '../graphql/checkImpersonation.graphql' +import USER_WIDGET_QUERY from '../graphql/userWidgetQuery.graphql' +import SET_CURRENT_ORGANIZATION from '../graphql/setCurrentOrganization.graphql' import STOP_IMPERSONATION from '../graphql/impersonateUser.graphql' import { B2B_CHECKOUT_SESSION_KEY } from '../utils/constants' @@ -24,6 +25,7 @@ const CSS_HANDLES = [ 'userWidgetImpersonationItem', 'userWidgetImpersonationButton', 'userWidgetImpersonationError', + 'userWidgetOrganizationError', ] as const const localStore = storageFactory(() => localStorage) @@ -31,12 +33,74 @@ let isAuthenticated = JSON.parse(String(localStore.getItem('b2b-organizations_isAuthenticated'))) ?? false +const CustomOrganizationOption = (props: any) => { + const { roundedBottom, searchTerm, value, selected, onClick } = props + const [highlightOption, setHighlightOption] = useState(false) + + const renderOptionHighlightedText = () => { + const highlightableText = typeof value === 'string' ? value : value.label + const index = highlightableText + .toLowerCase() + .indexOf(searchTerm.toLowerCase()) + + if (index === -1) { + return highlightableText + } + + const prefix = highlightableText.substring(0, index) + const match = highlightableText.substr(index, searchTerm.length) + const suffix = highlightableText.substring(`${index}${match.length}`) + + return ( + + {prefix} + {match} + {suffix} + + ) + } + + const buttonClasses = `bn w-100 tl pointer pa4 f6 ${ + roundedBottom ? 'br2 br--bottom' : '' + } ${highlightOption || selected ? 'bg-muted-5' : 'bg-base'}` + + // --- This is a good practice. Use + ) +} + const UserWidget: FunctionComponent = () => { const { navigate, rootPath } = useRuntime() const { formatMessage } = useIntl() const handles = useCssHandles(CSS_HANDLES) const [loadingState, setLoadingState] = useState(false) const [errorState, setErrorState] = useState(false) + const [errorOrganization, setErrorOrganization] = useState(false) + + const [organizationsState, setOrganizationsState] = useState({ + organizationOptions: [], + costCenterOptions: [], + organizationInput: '', + costCenterInput: '', + currentOrganization: '', + currentCostCenter: '', + currentOrganizationStatus: '', + }) const sessionResponse: any = useSessionResponse() @@ -50,27 +114,13 @@ const UserWidget: FunctionComponent = () => { ) } - const { data: permissionsData } = useQuery(GET_PERMISSIONS, { - ssr: false, - skip: !isAuthenticated, - }) - - const { data: organizationData } = useQuery(GET_ORGANIZATION, { - ssr: false, - skip: !isAuthenticated, - }) - - const { data: costCenterData } = useQuery(GET_COST_CENTER, { - ssr: false, - skip: !isAuthenticated, - }) - - const { data: impersonationData } = useQuery(CHECK_IMPERSONATION, { + const { data: userWidgetData } = useQuery(USER_WIDGET_QUERY, { ssr: false, skip: !isAuthenticated, - }) + }) as any const [stopImpersonation] = useMutation(STOP_IMPERSONATION) + const [setCurrentOrganization] = useMutation(SET_CURRENT_ORGANIZATION) const handleStopImpersonation = async () => { setLoadingState(true) @@ -91,6 +141,87 @@ const UserWidget: FunctionComponent = () => { }) } + const handleSetCurrentOrganization = async () => { + setLoadingState(true) + try { + await setCurrentOrganization({ + variables: { + orgId: organizationsState.currentOrganization, + costId: organizationsState.currentCostCenter, + }, + }) + } catch (error) { + setErrorOrganization(true) + } finally { + setLoadingState(false) + } + + window.location.reload() + } + + const organizationAutoCompleteInput = { + onChange: (text: string) => { + setOrganizationsState({ + ...organizationsState, + organizationInput: text, + }) + }, + placeholder: `${formatMessage(storeMessages.autocompleteSearching)}...`, + value: organizationsState.organizationInput, + } + + const costCenterAutoCompleteInput = { + onChange: (text: string) => { + setOrganizationsState({ + ...organizationsState, + costCenterInput: text, + }) + }, + placeholder: `${formatMessage(storeMessages.autocompleteSearching)}...`, + value: organizationsState.costCenterInput, + } + + useEffect(() => { + if (!userWidgetData?.getOrganizationsByEmail) { + return + } + + const currentOrganization = + userWidgetData?.getOrganizationByIdStorefront?.id + + const currentCostCenter = userWidgetData?.getCostCenterByIdStorefront?.id + + setOrganizationsState({ + ...organizationsState, + costCenterInput: userWidgetData?.getCostCenterByIdStorefront?.name, + organizationInput: userWidgetData?.getOrganizationByIdStorefront?.name, + organizationOptions: userWidgetData?.getOrganizationsByEmail.map( + (organization: { + orgId: string + organizationName: string + organizationStatus: string + }) => ({ + value: organization.orgId, + label: organization.organizationName, + status: organization.organizationStatus, + }) + ), + costCenterOptions: userWidgetData?.getOrganizationsByEmail + .filter( + (organization: { orgId: string }) => + organization.orgId === currentOrganization + ) + .map((organization: { costId: string; costCenterName: string }) => ({ + value: organization.costId, + label: organization.costCenterName, + })), + currentOrganization, + currentCostCenter, + currentOrganizationStatus: + userWidgetData?.getOrganizationByIdStorefront?.status, + }) + }, [userWidgetData]) + const handleStatusMessage = (status: string) => { switch (status) { case 'active': @@ -119,11 +250,42 @@ const UserWidget: FunctionComponent = () => { } } + const autoCompleteOrganizationOptions = { + value: organizationsState.organizationOptions, + renderOption: (props: any) => , + onSelect: (itemSelected: { value: string }) => { + setOrganizationsState({ + ...organizationsState, + costCenterInput: '', + currentOrganization: itemSelected.value, + costCenterOptions: userWidgetData?.getOrganizationsByEmail + .filter( + (organization: { orgId: string }) => + organization.orgId === itemSelected.value + ) + .map((organization: { costId: string; costCenterName: string }) => ({ + value: organization.costId, + label: organization.costCenterName, + })) as [], + }) + }, + } + + const autoCompleteCostCentersOptions = { + value: organizationsState.costCenterOptions, + onSelect: (itemSelected: { value: string }) => { + setOrganizationsState({ + ...organizationsState, + currentCostCenter: itemSelected.value, + }) + }, + } + if ( !isAuthenticated || - !permissionsData || - !organizationData || - !costCenterData + !userWidgetData?.checkUserPermission || + !userWidgetData?.getOrganizationByIdStorefront || + !userWidgetData?.getCostCenterByIdStorefront ) return null @@ -131,29 +293,75 @@ const UserWidget: FunctionComponent = () => {
-
+
- {`${formatMessage(messages.organization)} ${ - organizationData?.getOrganizationByIdStorefront?.name - }`}{' '} - {handleStatusMessage( - organizationData?.getOrganizationByIdStorefront?.status ?? '' + {(!userWidgetData?.checkImpersonation?.email && + organizationsState.organizationOptions.length > 1 && ( + + )) || ( + + {`${formatMessage(messages.organization)} ${ + userWidgetData?.getOrganizationByIdStorefront?.name + }`} + {handleStatusMessage( + userWidgetData?.getOrganizationByIdStorefront?.status ?? '' + )} + )}
- {`${formatMessage(messages.costCenter)} ${ - costCenterData?.getCostCenterByIdStorefront?.name - }`} + {(!userWidgetData?.checkImpersonation?.email && + organizationsState.organizationOptions.length > 1 && ( + + )) || ( + + {`${formatMessage(messages.costCenter)} ${ + userWidgetData?.getCostCenterByIdStorefront?.name + }`} + + )}
+ {!userWidgetData?.checkImpersonation?.email && + organizationsState.organizationOptions.length > 1 && ( +
+ + {errorOrganization && ( +
+ +
+ )} +
+ )}
{`${formatMessage(messages.role)} ${ - permissionsData?.checkUserPermission?.role?.name + userWidgetData?.checkUserPermission?.role?.name }`}
@@ -170,15 +378,15 @@ const UserWidget: FunctionComponent = () => {
- {impersonationData?.checkImpersonation?.email && ( + {userWidgetData?.checkImpersonation?.email && (
{`${formatMessage(messages.impersonating)} ${ - impersonationData.checkImpersonation.email + userWidgetData?.checkImpersonation.email }`}
diff --git a/react/components/utils/messages.ts b/react/components/utils/messages.ts index efeb0380..922d75f6 100644 --- a/react/components/utils/messages.ts +++ b/react/components/utils/messages.ts @@ -336,4 +336,7 @@ export const userWidgetMessages = defineMessages({ stopImpersonation: { id: `${storePrefix}stop-impersonation`, }, + setCurrentOrganization: { + id: `${storePrefix}set-current-organization`, + }, }) diff --git a/react/graphql/getOrganizationsByEmail.graphql b/react/graphql/getOrganizationsByEmail.graphql new file mode 100644 index 00000000..4e808952 --- /dev/null +++ b/react/graphql/getOrganizationsByEmail.graphql @@ -0,0 +1,14 @@ +query GetOrganizationsByEmail($email: String!) { + getOrganizationsByEmail(email: $email) + @context(provider: "vtex.b2b-organizations-graphql") { + id + costCenterName + costId + organizationName + orgId + role { + id + name + } + } +} diff --git a/react/graphql/setCurrentOrganization.graphql b/react/graphql/setCurrentOrganization.graphql new file mode 100644 index 00000000..dedb101a --- /dev/null +++ b/react/graphql/setCurrentOrganization.graphql @@ -0,0 +1,7 @@ +mutation CurrentOrganization($orgId: ID!, $costId: ID!) { + setCurrentOrganization(orgId: $orgId, costId: $costId) + @context(provider: "vtex.storefront-permissions") { + status + message + } +} diff --git a/react/graphql/userWidgetQuery.graphql b/react/graphql/userWidgetQuery.graphql new file mode 100644 index 00000000..57a8f9ba --- /dev/null +++ b/react/graphql/userWidgetQuery.graphql @@ -0,0 +1,67 @@ +query userWidgetQuery($orgId: ID) { + getOrganizationsByEmail @context(provider: "vtex.b2b-organizations-graphql") { + id + costCenterName + costId + organizationName + organizationStatus + orgId + role { + id + name + } + } + + checkUserPermission @context(provider: "vtex.storefront-permissions") { + role { + id + name + slug + } + permissions + } + + getOrganizationByIdStorefront(id: $orgId) + @context(provider: "vtex.b2b-organizations-graphql") { + id + name + status + paymentTerms { + id + name + } + } + + getCostCenterByIdStorefront(id: $orgId) + @context(provider: "vtex.b2b-organizations-graphql") { + id + name + organization + paymentTerms { + id + name + } + addresses { + addressId + addressType + addressQuery + postalCode + country + receiverName + city + state + street + number + complement + neighborhood + geoCoordinates + reference + } + phoneNumber + businessDocument + } + + checkImpersonation @context(provider: "vtex.storefront-permissions") { + email + } +}