From 5741209aa91bbe32bec9abdfb05d9314a9e45ce4 Mon Sep 17 00:00:00 2001 From: Johannes <72809645+jobenjada@users.noreply.github.com> Date: Mon, 17 Nov 2025 03:51:49 -0800 Subject: [PATCH] fix: resolve metadata in hover confusion + other UI tweaks (#6821) Co-authored-by: Dhruwang --- .../airtable/components/AirtableWrapper.tsx | 4 - .../airtable/components/ManageIntegration.tsx | 13 +- .../project/integrations/airtable/page.tsx | 1 - .../components/GoogleSheetWrapper.tsx | 1 - .../components/ManageIntegration.tsx | 12 +- .../notion/components/ManageIntegration.tsx | 12 +- .../notion/components/NotionWrapper.tsx | 1 - .../slack/components/ManageIntegration.tsx | 12 +- .../slack/components/SlackWrapper.tsx | 1 - .../summary/components/SummaryList.tsx | 19 +- apps/web/i18n.lock | 6 +- apps/web/locales/de-DE.json | 6 +- apps/web/locales/en-US.json | 6 +- apps/web/locales/es-ES.json | 6 +- apps/web/locales/fr-FR.json | 6 +- apps/web/locales/ja-JP.json | 6 +- apps/web/locales/nl-NL.json | 6 +- apps/web/locales/pt-BR.json | 6 +- apps/web/locales/pt-PT.json | 6 +- apps/web/locales/ro-RO.json | 6 +- apps/web/locales/zh-Hans-CN.json | 6 +- apps/web/locales/zh-Hant-TW.json | 6 +- .../components/ResponseTagsWrapper.tsx | 25 +-- .../components/SingleResponseCardHeader.tsx | 195 ++++-------------- .../components/SingleResponseCardMetadata.tsx | 163 +++++++++++++++ .../components/SingleResponseCard/index.tsx | 2 + .../[contactId]/components/response-feed.tsx | 6 +- .../ee/contacts/components/contacts-table.tsx | 2 +- .../segments/components/segment-table.tsx | 1 + .../webhooks/components/webhook-table.tsx | 9 +- .../tags/components/edit-tags-wrapper.tsx | 17 +- .../modules/projects/settings/tags/page.tsx | 3 +- .../ui/components/code-block/style.css | 4 +- .../ui/components/editor/styles-editor.css | 2 +- .../components/empty-space-filler/index.tsx | 157 -------------- .../ui/components/empty-state/index.tsx | 19 ++ .../ui/components/tags-combobox/index.tsx | 4 +- apps/web/modules/ui/globals.css | 7 +- 38 files changed, 291 insertions(+), 473 deletions(-) create mode 100644 apps/web/modules/analysis/components/SingleResponseCard/components/SingleResponseCardMetadata.tsx delete mode 100644 apps/web/modules/ui/components/empty-space-filler/index.tsx create mode 100644 apps/web/modules/ui/components/empty-state/index.tsx diff --git a/apps/web/app/(app)/environments/[environmentId]/project/integrations/airtable/components/AirtableWrapper.tsx b/apps/web/app/(app)/environments/[environmentId]/project/integrations/airtable/components/AirtableWrapper.tsx index 2a5cbca21a..d0b3c4a07a 100644 --- a/apps/web/app/(app)/environments/[environmentId]/project/integrations/airtable/components/AirtableWrapper.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/project/integrations/airtable/components/AirtableWrapper.tsx @@ -1,7 +1,6 @@ "use client"; import { useState } from "react"; -import { TEnvironment } from "@formbricks/types/environment"; import { TIntegrationItem } from "@formbricks/types/integration"; import { TIntegrationAirtable } from "@formbricks/types/integration/airtable"; import { TSurvey } from "@formbricks/types/surveys/types"; @@ -16,7 +15,6 @@ interface AirtableWrapperProps { airtableArray: TIntegrationItem[]; airtableIntegration?: TIntegrationAirtable; surveys: TSurvey[]; - environment: TEnvironment; isEnabled: boolean; webAppUrl: string; locale: TUserLocale; @@ -27,7 +25,6 @@ export const AirtableWrapper = ({ airtableArray, airtableIntegration, surveys, - environment, isEnabled, webAppUrl, locale, @@ -48,7 +45,6 @@ export const AirtableWrapper = ({ void; surveys: TSurvey[]; @@ -29,7 +27,7 @@ interface ManageIntegrationProps { } export const ManageIntegration = (props: ManageIntegrationProps) => { - const { airtableIntegration, environment, environmentId, setIsConnected, surveys, airtableArray } = props; + const { airtableIntegration, environmentId, setIsConnected, surveys, airtableArray } = props; const { t } = useTranslation(); const tableHeaders = [ @@ -132,12 +130,7 @@ export const ManageIntegration = (props: ManageIntegrationProps) => { ) : (
- +
)} diff --git a/apps/web/app/(app)/environments/[environmentId]/project/integrations/airtable/page.tsx b/apps/web/app/(app)/environments/[environmentId]/project/integrations/airtable/page.tsx index 09e4413f48..5c92d4c14f 100644 --- a/apps/web/app/(app)/environments/[environmentId]/project/integrations/airtable/page.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/project/integrations/airtable/page.tsx @@ -51,7 +51,6 @@ const Page = async (props) => { airtableArray={airtableArray} environmentId={environment.id} surveys={surveys} - environment={environment} webAppUrl={WEBAPP_URL} locale={locale} /> diff --git a/apps/web/app/(app)/environments/[environmentId]/project/integrations/google-sheets/components/GoogleSheetWrapper.tsx b/apps/web/app/(app)/environments/[environmentId]/project/integrations/google-sheets/components/GoogleSheetWrapper.tsx index 125c0a5f46..137485ecb4 100644 --- a/apps/web/app/(app)/environments/[environmentId]/project/integrations/google-sheets/components/GoogleSheetWrapper.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/project/integrations/google-sheets/components/GoogleSheetWrapper.tsx @@ -60,7 +60,6 @@ export const GoogleSheetWrapper = ({ selectedIntegration={selectedIntegration} /> void; setIsConnected: (v: boolean) => void; @@ -27,7 +25,6 @@ interface ManageIntegrationProps { } export const ManageIntegration = ({ - environment, googleSheetIntegration, setOpenAddIntegrationModal, setIsConnected, @@ -90,12 +87,7 @@ export const ManageIntegration = ({ {!integrationArray || integrationArray.length === 0 ? (
- +
) : (
diff --git a/apps/web/app/(app)/environments/[environmentId]/project/integrations/notion/components/ManageIntegration.tsx b/apps/web/app/(app)/environments/[environmentId]/project/integrations/notion/components/ManageIntegration.tsx index 4e6b30f816..75df75c2c3 100644 --- a/apps/web/app/(app)/environments/[environmentId]/project/integrations/notion/components/ManageIntegration.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/project/integrations/notion/components/ManageIntegration.tsx @@ -4,7 +4,6 @@ import { RefreshCcwIcon, Trash2Icon } from "lucide-react"; import React, { useState } from "react"; import toast from "react-hot-toast"; import { useTranslation } from "react-i18next"; -import { TEnvironment } from "@formbricks/types/environment"; import { TIntegrationNotion, TIntegrationNotionConfigData } from "@formbricks/types/integration/notion"; import { TUserLocale } from "@formbricks/types/user"; import { deleteIntegrationAction } from "@/app/(app)/environments/[environmentId]/project/integrations/actions"; @@ -12,11 +11,10 @@ import { timeSince } from "@/lib/time"; import { getFormattedErrorMessage } from "@/lib/utils/helper"; import { Button } from "@/modules/ui/components/button"; import { DeleteDialog } from "@/modules/ui/components/delete-dialog"; -import { EmptySpaceFiller } from "@/modules/ui/components/empty-space-filler"; +import { EmptyState } from "@/modules/ui/components/empty-state"; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/modules/ui/components/tooltip"; interface ManageIntegrationProps { - environment: TEnvironment; notionIntegration: TIntegrationNotion; setOpenAddIntegrationModal: React.Dispatch>; setIsConnected: React.Dispatch>; @@ -28,7 +26,6 @@ interface ManageIntegrationProps { } export const ManageIntegration = ({ - environment, notionIntegration, setOpenAddIntegrationModal, setIsConnected, @@ -101,12 +98,7 @@ export const ManageIntegration = ({
{!integrationArray || integrationArray.length === 0 ? (
- +
) : (
diff --git a/apps/web/app/(app)/environments/[environmentId]/project/integrations/notion/components/NotionWrapper.tsx b/apps/web/app/(app)/environments/[environmentId]/project/integrations/notion/components/NotionWrapper.tsx index 3066f0c37d..8d7d85fdd8 100644 --- a/apps/web/app/(app)/environments/[environmentId]/project/integrations/notion/components/NotionWrapper.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/project/integrations/notion/components/NotionWrapper.tsx @@ -64,7 +64,6 @@ export const NotionWrapper = ({ selectedIntegration={selectedIntegration} /> >; setIsConnected: React.Dispatch>; @@ -29,7 +27,6 @@ interface ManageIntegrationProps { } export const ManageIntegration = ({ - environment, slackIntegration, setOpenAddIntegrationModal, setIsConnected, @@ -106,12 +103,7 @@ export const ManageIntegration = ({
{!integrationArray || integrationArray.length === 0 ? (
- +
) : (
diff --git a/apps/web/app/(app)/environments/[environmentId]/project/integrations/slack/components/SlackWrapper.tsx b/apps/web/app/(app)/environments/[environmentId]/project/integrations/slack/components/SlackWrapper.tsx index 47ed0dee36..c52e8c9588 100644 --- a/apps/web/app/(app)/environments/[environmentId]/project/integrations/slack/components/SlackWrapper.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/project/integrations/slack/components/SlackWrapper.tsx @@ -78,7 +78,6 @@ export const SlackWrapper = ({ selectedIntegration={selectedIntegration} /> ) : responseCount === 0 ? ( - + ) : ( summary.map((questionSummary) => { if (questionSummary.type === TSurveyQuestionTypeEnum.OpenText) { diff --git a/apps/web/i18n.lock b/apps/web/i18n.lock index dba398fa78..59f85b263b 100644 --- a/apps/web/i18n.lock +++ b/apps/web/i18n.lock @@ -811,7 +811,6 @@ checksums: environments/project/tags/add_tag: 2cfa04ceea966149f2b5d40d9c131141 environments/project/tags/count: 9c5848662eb8024ddf360f7e4001a968 environments/project/tags/delete_tag_confirmation: a9fb98064cd156242899643f3d2ef032 - environments/project/tags/empty_message: da71bd7c7b5bf634469d20e010d25503 environments/project/tags/manage_tags: 2761d558b82b6104befbc240ae2379c6 environments/project/tags/manage_tags_description: ce7cc42da3646fba960502d7e4e49cd2 environments/project/tags/merge: 95051c859b8778be51226b43be6f1075 @@ -1600,7 +1599,7 @@ checksums: environments/surveys/responses/last_name: 2c9a7de7738ca007ba9023c385149c26 environments/surveys/responses/not_completed: df34eab65a6291f2c5e15a0e349c4eba environments/surveys/responses/os: a4c753bb2c004a58d02faeed6b4da476 - environments/surveys/responses/person_attributes: 8f7f8a9040ce8efb3cb54ce33b590866 + environments/surveys/responses/person_attributes: 07ae67ae73d7a2a7c67008694a83f0a3 environments/surveys/responses/phone: b9537ee90fc5b0116942e0af29d926cc environments/surveys/responses/respondent_skipped_questions: d85daf579ade534dc7e639689156fcd5 environments/surveys/responses/response_deleted_successfully: 6cec5427c271800619fee8c812d7db18 @@ -1718,7 +1717,6 @@ checksums: environments/surveys/summary/filtered_responses_csv: aad66a98be6a09cac8bef9e4db4a75cf environments/surveys/summary/filtered_responses_excel: 06e57bae9e41979fd7fc4b8bfe3466f9 environments/surveys/summary/generating_qr_code: 5026d4a76f995db458195e5215d9bbd9 - environments/surveys/summary/go_to_setup_checklist: d70bd018d651d01c41ae10370e71d0be environments/surveys/summary/impressions: 7fe38d42d68a64d3fd8436a063751584 environments/surveys/summary/impressions_tooltip: 4d0823cbf360304770c7c5913e33fdc8 environments/surveys/summary/in_app/connection_description: 9710bbf8048a8a5c3b2b56db9d946b73 @@ -1750,7 +1748,6 @@ checksums: environments/surveys/summary/in_app/title: a2d1b633244d0e0504ec6f8f561c7a6b environments/surveys/summary/includes_all: b0e3679282417c62d511c258362f860e environments/surveys/summary/includes_either: 186d6923c1693e80d7b664b8367d4221 - environments/surveys/summary/install_widget: 55d403de32e3d0da7513ab199f1d1934 environments/surveys/summary/is_equal_to: f4aab30ef188eb25dcc0e392cf8e86bb environments/surveys/summary/is_less_than: 6109d595ba21497c59b1c91d7fd09a13 environments/surveys/summary/last_30_days: a738894cfc5e592052f1e16787744568 @@ -1787,7 +1784,6 @@ checksums: environments/surveys/summary/ttc_tooltip: 9b1cbe32cc81111314bd3b6fd050c2e7 environments/surveys/summary/unknown_question_type: e4152a7457d2b94f48dcc70aaba9922f environments/surveys/summary/use_personal_links: da2b3e7e1aaf2ea2bd4efed2dda4247c - environments/surveys/summary/waiting_for_response: 0194a84e0850b8e98435632d5331a916 environments/surveys/summary/whats_next: d920145bfa2147014062f6f2d1d451a4 environments/surveys/summary/your_survey_is_public: 3f5cb5949a5f4020a3d4d74fdfc95e83 environments/surveys/summary/youre_not_plugged_in_yet: 9217467742cdcf7edf8d59cc1472ede6 diff --git a/apps/web/locales/de-DE.json b/apps/web/locales/de-DE.json index 213fd94b56..63c1005dd5 100644 --- a/apps/web/locales/de-DE.json +++ b/apps/web/locales/de-DE.json @@ -872,7 +872,6 @@ "add_tag": "Tag hinzufügen", "count": "zählen", "delete_tag_confirmation": "Bist Du sicher, dass Du diesen Tag löschen möchtest?", - "empty_message": "Markiere eine Antwort, um deine Liste der Tags hier zu finden.", "manage_tags": "Tags verwalten", "manage_tags_description": "Zusammenführen und Antwort-Tags entfernen.", "merge": "Zusammenführen", @@ -1691,7 +1690,7 @@ "last_name": "Nachname", "not_completed": "Nicht abgeschlossen ⏳", "os": "Betriebssystem", - "person_attributes": "Personenattribute", + "person_attributes": "Personenattribute zum Zeitpunkt der Einreichung", "phone": "Telefon", "respondent_skipped_questions": "Der Befragte hat diese Fragen übersprungen.", "response_deleted_successfully": "Antwort erfolgreich gelöscht.", @@ -1827,7 +1826,6 @@ "filtered_responses_csv": "Gefilterte Antworten (CSV)", "filtered_responses_excel": "Gefilterte Antworten (Excel)", "generating_qr_code": "QR-Code wird generiert", - "go_to_setup_checklist": "Gehe zur Einrichtungs-Checkliste 👉", "impressions": "Eindrücke", "impressions_tooltip": "Anzahl der Aufrufe der Umfrage.", "in_app": { @@ -1861,7 +1859,6 @@ }, "includes_all": "Beinhaltet alles", "includes_either": "Beinhaltet entweder", - "install_widget": "Formbricks Widget installieren", "is_equal_to": "Ist gleich", "is_less_than": "ist weniger als", "last_30_days": "Letzte 30 Tage", @@ -1898,7 +1895,6 @@ "ttc_tooltip": "Durchschnittliche Zeit zum Beantworten der Frage.", "unknown_question_type": "Unbekannter Fragetyp", "use_personal_links": "Nutze persönliche Links", - "waiting_for_response": "Warte auf eine Antwort 🧘‍♂️", "whats_next": "Was kommt als Nächstes?", "your_survey_is_public": "Deine Umfrage ist öffentlich", "youre_not_plugged_in_yet": "Du bist noch nicht verbunden!" diff --git a/apps/web/locales/en-US.json b/apps/web/locales/en-US.json index d61a930619..9142d817a6 100644 --- a/apps/web/locales/en-US.json +++ b/apps/web/locales/en-US.json @@ -872,7 +872,6 @@ "add_tag": "Add Tag", "count": "Count", "delete_tag_confirmation": "Are you sure you want to delete this tag?", - "empty_message": "Tag a submission to find your list of tags here.", "manage_tags": "Manage Tags", "manage_tags_description": "Merge and remove response tags.", "merge": "Merge", @@ -1691,7 +1690,7 @@ "last_name": "Last Name", "not_completed": "Not Completed ⏳", "os": "OS", - "person_attributes": "Person attributes", + "person_attributes": "Person attributes at time of submission", "phone": "Phone", "respondent_skipped_questions": "Respondent skipped these questions.", "response_deleted_successfully": "Response deleted successfully.", @@ -1827,7 +1826,6 @@ "filtered_responses_csv": "Filtered responses (CSV)", "filtered_responses_excel": "Filtered responses (Excel)", "generating_qr_code": "Generating QR code", - "go_to_setup_checklist": "Go to Setup Checklist \uD83D\uDC49", "impressions": "Impressions", "impressions_tooltip": "Number of times the survey has been viewed.", "in_app": { @@ -1861,7 +1859,6 @@ }, "includes_all": "Includes all", "includes_either": "Includes either", - "install_widget": "Install Formbricks Widget", "is_equal_to": "Is equal to", "is_less_than": "Is less than", "last_30_days": "Last 30 days", @@ -1898,7 +1895,6 @@ "ttc_tooltip": "Average time to complete the question.", "unknown_question_type": "Unknown Question Type", "use_personal_links": "Use personal links", - "waiting_for_response": "Waiting for a response \uD83E\uDDD8‍♂️", "whats_next": "What's next?", "your_survey_is_public": "Your survey is public", "youre_not_plugged_in_yet": "You're not plugged in yet!" diff --git a/apps/web/locales/es-ES.json b/apps/web/locales/es-ES.json index 580b5efaaf..078adc2ed9 100644 --- a/apps/web/locales/es-ES.json +++ b/apps/web/locales/es-ES.json @@ -872,7 +872,6 @@ "add_tag": "Añadir etiqueta", "count": "Recuento", "delete_tag_confirmation": "¿Estás seguro de que quieres eliminar esta etiqueta?", - "empty_message": "Etiqueta un envío para encontrar tu lista de etiquetas aquí.", "manage_tags": "Gestionar etiquetas", "manage_tags_description": "Fusionar y eliminar etiquetas de respuesta.", "merge": "Fusionar", @@ -1691,7 +1690,7 @@ "last_name": "Apellido", "not_completed": "No completado ⏳", "os": "Sistema operativo", - "person_attributes": "Atributos de persona", + "person_attributes": "Atributos de la persona en el momento del envío", "phone": "Teléfono", "respondent_skipped_questions": "El encuestado omitió estas preguntas.", "response_deleted_successfully": "Respuesta eliminada correctamente.", @@ -1827,7 +1826,6 @@ "filtered_responses_csv": "Respuestas filtradas (CSV)", "filtered_responses_excel": "Respuestas filtradas (Excel)", "generating_qr_code": "Generando código QR", - "go_to_setup_checklist": "Ir a la lista de configuración 👉", "impressions": "Impresiones", "impressions_tooltip": "Número de veces que se ha visto la encuesta.", "in_app": { @@ -1861,7 +1859,6 @@ }, "includes_all": "Incluye todo", "includes_either": "Incluye cualquiera", - "install_widget": "Instalar widget de Formbricks", "is_equal_to": "Es igual a", "is_less_than": "Es menor que", "last_30_days": "Últimos 30 días", @@ -1898,7 +1895,6 @@ "ttc_tooltip": "Tiempo medio para completar la pregunta.", "unknown_question_type": "Tipo de pregunta desconocido", "use_personal_links": "Usar enlaces personales", - "waiting_for_response": "Esperando una respuesta 🧘‍♂️", "whats_next": "¿Qué sigue?", "your_survey_is_public": "Tu encuesta es pública", "youre_not_plugged_in_yet": "¡Aún no estás conectado!" diff --git a/apps/web/locales/fr-FR.json b/apps/web/locales/fr-FR.json index 309b207d0c..945f0d17c5 100644 --- a/apps/web/locales/fr-FR.json +++ b/apps/web/locales/fr-FR.json @@ -872,7 +872,6 @@ "add_tag": "Ajouter une étiquette", "count": "Compter", "delete_tag_confirmation": "Êtes-vous sûr de vouloir supprimer cette étiquette ?", - "empty_message": "Ajoutez une balise à une réponse pour afficher votre liste de balises.", "manage_tags": "Gérer les étiquettes", "manage_tags_description": "Vous pouvez fusionner et supprimer des balises de réponse.", "merge": "Fusionner", @@ -1691,7 +1690,7 @@ "last_name": "Nom de famille", "not_completed": "Non terminé ⏳", "os": "Système d'exploitation", - "person_attributes": "Attributs de la personne", + "person_attributes": "Attributs de la personne au moment de la soumission", "phone": "Téléphone", "respondent_skipped_questions": "Le répondant a sauté ces questions.", "response_deleted_successfully": "Réponse supprimée avec succès.", @@ -1827,7 +1826,6 @@ "filtered_responses_csv": "Réponses filtrées (CSV)", "filtered_responses_excel": "Réponses filtrées (Excel)", "generating_qr_code": "Génération du code QR", - "go_to_setup_checklist": "Allez à la liste de contrôle de configuration 👉", "impressions": "Impressions", "impressions_tooltip": "Nombre de fois que l'enquête a été consultée.", "in_app": { @@ -1861,7 +1859,6 @@ }, "includes_all": "Comprend tous", "includes_either": "Comprend soit", - "install_widget": "Installer le widget Formbricks", "is_equal_to": "Est égal à", "is_less_than": "est inférieur à", "last_30_days": "30 derniers jours", @@ -1898,7 +1895,6 @@ "ttc_tooltip": "Temps moyen pour compléter la question.", "unknown_question_type": "Type de question inconnu", "use_personal_links": "Utilisez des liens personnels", - "waiting_for_response": "En attente d'une réponse 🧘‍♂️", "whats_next": "Qu'est-ce qui vient ensuite ?", "your_survey_is_public": "Votre enquête est publique.", "youre_not_plugged_in_yet": "Vous n'êtes pas encore branché !" diff --git a/apps/web/locales/ja-JP.json b/apps/web/locales/ja-JP.json index 55c3135415..b5eaf3d67a 100644 --- a/apps/web/locales/ja-JP.json +++ b/apps/web/locales/ja-JP.json @@ -872,7 +872,6 @@ "add_tag": "タグを追加", "count": "件数", "delete_tag_confirmation": "このタグを削除してもよろしいですか?", - "empty_message": "送信にタグ付けすると、ここにタグ一覧が表示されます。", "manage_tags": "タグを管理", "manage_tags_description": "回答タグを統合・削除します。", "merge": "統合", @@ -1691,7 +1690,7 @@ "last_name": "姓", "not_completed": "未完了 ⏳", "os": "OS", - "person_attributes": "人物属性", + "person_attributes": "回答時の個人属性", "phone": "電話", "respondent_skipped_questions": "回答者はこれらの質問をスキップしました。", "response_deleted_successfully": "回答を正常に削除しました。", @@ -1827,7 +1826,6 @@ "filtered_responses_csv": "フィルター済み回答 (CSV)", "filtered_responses_excel": "フィルター済み回答 (Excel)", "generating_qr_code": "QRコードを生成中", - "go_to_setup_checklist": "セットアップチェックリストへ移動 👉", "impressions": "表示回数", "impressions_tooltip": "フォームが表示された回数。", "in_app": { @@ -1861,7 +1859,6 @@ }, "includes_all": "すべてを含む", "includes_either": "どちらかを含む", - "install_widget": "Formbricksウィジェットをインストール", "is_equal_to": "と等しい", "is_less_than": "より小さい", "last_30_days": "過去30日間", @@ -1898,7 +1895,6 @@ "ttc_tooltip": "フォームを完了するまでの平均時間。", "unknown_question_type": "不明な質問の種類", "use_personal_links": "個人リンクを使用", - "waiting_for_response": "回答を待っています 🧘‍♂️", "whats_next": "次は何をしますか?", "your_survey_is_public": "あなたのフォームは公開されています", "youre_not_plugged_in_yet": "まだ接続されていません!" diff --git a/apps/web/locales/nl-NL.json b/apps/web/locales/nl-NL.json index 49ce57fa6c..07eed49b8d 100644 --- a/apps/web/locales/nl-NL.json +++ b/apps/web/locales/nl-NL.json @@ -872,7 +872,6 @@ "add_tag": "Label toevoegen", "count": "Graaf", "delete_tag_confirmation": "Weet u zeker dat u deze tag wilt verwijderen?", - "empty_message": "Tag een inzending om hier uw lijst met tags te vinden.", "manage_tags": "Beheer tags", "manage_tags_description": "Reactietags samenvoegen en verwijderen.", "merge": "Samenvoegen", @@ -1691,7 +1690,7 @@ "last_name": "Achternaam", "not_completed": "Niet voltooid ⏳", "os": "Besturingssysteem", - "person_attributes": "Persoonsattributen", + "person_attributes": "Persoonskenmerken op het moment van indiening", "phone": "Telefoon", "respondent_skipped_questions": "Respondent heeft deze vragen overgeslagen.", "response_deleted_successfully": "Reactie is succesvol verwijderd.", @@ -1827,7 +1826,6 @@ "filtered_responses_csv": "Gefilterde reacties (CSV)", "filtered_responses_excel": "Gefilterde reacties (Excel)", "generating_qr_code": "QR-code genereren", - "go_to_setup_checklist": "Ga naar Installatiechecklist 👉", "impressions": "Indrukken", "impressions_tooltip": "Aantal keren dat de enquête is bekeken.", "in_app": { @@ -1861,7 +1859,6 @@ }, "includes_all": "Inclusief alles", "includes_either": "Inclusief beide", - "install_widget": "Installeer Formbricks-widget", "is_equal_to": "Is gelijk aan", "is_less_than": "Is minder dan", "last_30_days": "Laatste 30 dagen", @@ -1898,7 +1895,6 @@ "ttc_tooltip": "Gemiddelde tijd om de vraag te beantwoorden.", "unknown_question_type": "Onbekend vraagtype", "use_personal_links": "Gebruik persoonlijke links", - "waiting_for_response": "Wachten op een reactie 🧘‍♂️", "whats_next": "Wat is het volgende?", "your_survey_is_public": "Uw enquête is openbaar", "youre_not_plugged_in_yet": "Je bent nog niet aangesloten!" diff --git a/apps/web/locales/pt-BR.json b/apps/web/locales/pt-BR.json index 32bf1edb8a..f9e51be34c 100644 --- a/apps/web/locales/pt-BR.json +++ b/apps/web/locales/pt-BR.json @@ -872,7 +872,6 @@ "add_tag": "Adicionar Tag", "count": "Contar", "delete_tag_confirmation": "Tem certeza de que quer deletar essa tag?", - "empty_message": "Marque uma submissão para encontrar sua lista de tags aqui.", "manage_tags": "Gerenciar Tags", "manage_tags_description": "Mesclar e remover tags de resposta.", "merge": "mesclar", @@ -1691,7 +1690,7 @@ "last_name": "Sobrenome", "not_completed": "Não Concluído ⏳", "os": "sistema operacional", - "person_attributes": "Atributos da pessoa", + "person_attributes": "Atributos da pessoa no momento do envio", "phone": "Celular", "respondent_skipped_questions": "Respondente pulou essas perguntas.", "response_deleted_successfully": "Resposta deletada com sucesso.", @@ -1827,7 +1826,6 @@ "filtered_responses_csv": "Respostas filtradas (CSV)", "filtered_responses_excel": "Respostas filtradas (Excel)", "generating_qr_code": "Gerando código QR", - "go_to_setup_checklist": "Vai para a Lista de Configuração 👉", "impressions": "Impressões", "impressions_tooltip": "Número de vezes que a pesquisa foi visualizada.", "in_app": { @@ -1861,7 +1859,6 @@ }, "includes_all": "Inclui tudo", "includes_either": "Inclui ou", - "install_widget": "Instalar Widget do Formbricks", "is_equal_to": "É igual a", "is_less_than": "É menor que", "last_30_days": "Últimos 30 dias", @@ -1898,7 +1895,6 @@ "ttc_tooltip": "Tempo médio para completar a pergunta.", "unknown_question_type": "Tipo de pergunta desconhecido", "use_personal_links": "Use links pessoais", - "waiting_for_response": "Aguardando uma resposta 🧘‍♂️", "whats_next": "E agora?", "your_survey_is_public": "Sua pesquisa é pública", "youre_not_plugged_in_yet": "Você ainda não tá conectado!" diff --git a/apps/web/locales/pt-PT.json b/apps/web/locales/pt-PT.json index ac0c485950..75bc319802 100644 --- a/apps/web/locales/pt-PT.json +++ b/apps/web/locales/pt-PT.json @@ -872,7 +872,6 @@ "add_tag": "Adicionar Etiqueta", "count": "Contagem", "delete_tag_confirmation": "Tem a certeza de que deseja eliminar esta etiqueta?", - "empty_message": "Crie etiquetas para as suas submissões e veja-as aqui", "manage_tags": "Gerir Etiquetas", "manage_tags_description": "Junte e remova etiquetas de resposta", "merge": "Fundir", @@ -1691,7 +1690,7 @@ "last_name": "Apelido", "not_completed": "Não Concluído ⏳", "os": "SO", - "person_attributes": "Atributos da pessoa", + "person_attributes": "Atributos da pessoa no momento da submissão", "phone": "Telefone", "respondent_skipped_questions": "O respondente saltou estas perguntas.", "response_deleted_successfully": "Resposta eliminada com sucesso.", @@ -1827,7 +1826,6 @@ "filtered_responses_csv": "Respostas filtradas (CSV)", "filtered_responses_excel": "Respostas filtradas (Excel)", "generating_qr_code": "A gerar código QR", - "go_to_setup_checklist": "Ir para a Lista de Verificação de Configuração 👉", "impressions": "Impressões", "impressions_tooltip": "Número de vezes que o inquérito foi visualizado.", "in_app": { @@ -1861,7 +1859,6 @@ }, "includes_all": "Inclui tudo", "includes_either": "Inclui qualquer um", - "install_widget": "Instalar Widget Formbricks", "is_equal_to": "É igual a", "is_less_than": "É menos que", "last_30_days": "Últimos 30 dias", @@ -1898,7 +1895,6 @@ "ttc_tooltip": "Tempo médio para concluir a pergunta.", "unknown_question_type": "Tipo de Pergunta Desconhecido", "use_personal_links": "Utilize links pessoais", - "waiting_for_response": "A aguardar uma resposta 🧘‍♂️", "whats_next": "O que se segue?", "your_survey_is_public": "O seu inquérito é público", "youre_not_plugged_in_yet": "Ainda não está ligado!" diff --git a/apps/web/locales/ro-RO.json b/apps/web/locales/ro-RO.json index 7419a7e84c..a0a235293d 100644 --- a/apps/web/locales/ro-RO.json +++ b/apps/web/locales/ro-RO.json @@ -872,7 +872,6 @@ "add_tag": "Adaugă Etichetă", "count": "Număr", "delete_tag_confirmation": "Sigur doriți să ștergeți această etichetă?", - "empty_message": "Marcați o trimitere pentru a găsi lista de etichete aici.", "manage_tags": "Gestionați etichetele", "manage_tags_description": "Îmbinați și eliminați etichetele de răspuns.", "merge": "Îmbinare", @@ -1691,7 +1690,7 @@ "last_name": "Nume de familie", "not_completed": "Necompletat ⏳", "os": "SO", - "person_attributes": "Atribute persoană", + "person_attributes": "Atributele persoanei la momentul trimiterii", "phone": "Telefon", "respondent_skipped_questions": "Respondenții au sărit peste aceste întrebări.", "response_deleted_successfully": "Răspuns șters cu succes.", @@ -1827,7 +1826,6 @@ "filtered_responses_csv": "Răspunsuri filtrate (CSV)", "filtered_responses_excel": "Răspunsuri filtrate (Excel)", "generating_qr_code": "Se generează codul QR", - "go_to_setup_checklist": "Mergi la lista de verificare a configurării 👉", "impressions": "Impresii", "impressions_tooltip": "Număr de ori când sondajul a fost vizualizat.", "in_app": { @@ -1861,7 +1859,6 @@ }, "includes_all": "Include tot", "includes_either": "Include fie", - "install_widget": "Instalați Widgetul Formbricks", "is_equal_to": "Este egal cu", "is_less_than": "Este mai puțin de", "last_30_days": "Ultimele 30 de zile", @@ -1898,7 +1895,6 @@ "ttc_tooltip": "Timp mediu pentru a completa întrebarea.", "unknown_question_type": "Tip de întrebare necunoscut", "use_personal_links": "Folosește linkuri personale", - "waiting_for_response": "Așteptând un răspuns 🧘‍♂️", "whats_next": "Ce urmează?", "your_survey_is_public": "Sondajul tău este public", "youre_not_plugged_in_yet": "Nu sunteţi încă conectat!" diff --git a/apps/web/locales/zh-Hans-CN.json b/apps/web/locales/zh-Hans-CN.json index 634e462082..df14dca050 100644 --- a/apps/web/locales/zh-Hans-CN.json +++ b/apps/web/locales/zh-Hans-CN.json @@ -872,7 +872,6 @@ "add_tag": "添加 标签", "count": "数量", "delete_tag_confirmation": "您 确定 要 删除 此 标签 吗?", - "empty_message": "标记一个提交以在此处找到您的标签列表。", "manage_tags": "管理标签", "manage_tags_description": "合并 和 删除 response 标签。", "merge": "合并", @@ -1691,7 +1690,7 @@ "last_name": "姓", "not_completed": "未完成 ⏳", "os": "操作系统", - "person_attributes": "人员 属性", + "person_attributes": "提交时的个人属性", "phone": "电话", "respondent_skipped_questions": "受访者跳过 这些问题。", "response_deleted_successfully": "响应 删除 成功", @@ -1827,7 +1826,6 @@ "filtered_responses_csv": "过滤 反馈 (CSV)", "filtered_responses_excel": "过滤 反馈 (Excel)", "generating_qr_code": "正在生成二维码", - "go_to_setup_checklist": "前往 设置 检查列表 👉", "impressions": "印象", "impressions_tooltip": "调查 被 查看 的 次数", "in_app": { @@ -1861,7 +1859,6 @@ }, "includes_all": "包括所有 ", "includes_either": "包含 任意一个", - "install_widget": "安装 Formbricks 小组件", "is_equal_to": "等于", "is_less_than": "少于", "last_30_days": "最近 30 天", @@ -1898,7 +1895,6 @@ "ttc_tooltip": "完成 本 问题 的 平均 时间", "unknown_question_type": "未知 问题 类型", "use_personal_links": "使用 个人 链接", - "waiting_for_response": "等待回复 🧘‍♂️", "whats_next": "接下来 是 什么?", "your_survey_is_public": "您的 调查 是 公共 的", "youre_not_plugged_in_yet": "您 还 没 有 连 接!" diff --git a/apps/web/locales/zh-Hant-TW.json b/apps/web/locales/zh-Hant-TW.json index b176bf6a04..db7c645cea 100644 --- a/apps/web/locales/zh-Hant-TW.json +++ b/apps/web/locales/zh-Hant-TW.json @@ -872,7 +872,6 @@ "add_tag": "新增標籤", "count": "計數", "delete_tag_confirmation": "您確定要刪除此標籤嗎?", - "empty_message": "標記提交內容,在此處找到您的標籤清單。", "manage_tags": "管理標籤", "manage_tags_description": "合併和移除回應標籤。", "merge": "合併", @@ -1691,7 +1690,7 @@ "last_name": "姓氏", "not_completed": "未完成 ⏳", "os": "作業系統", - "person_attributes": "人員屬性", + "person_attributes": "提交時的個人屬性", "phone": "電話", "respondent_skipped_questions": "回應者跳過這些問題。", "response_deleted_successfully": "回應已成功刪除。", @@ -1827,7 +1826,6 @@ "filtered_responses_csv": "篩選回應 (CSV)", "filtered_responses_excel": "篩選回應 (Excel)", "generating_qr_code": "正在生成 QR code", - "go_to_setup_checklist": "前往設定檢查清單 👉", "impressions": "曝光數", "impressions_tooltip": "問卷已檢視的次數。", "in_app": { @@ -1861,7 +1859,6 @@ }, "includes_all": "包含全部", "includes_either": "包含其中一個", - "install_widget": "安裝 Formbricks 小工具", "is_equal_to": "等於", "is_less_than": "小於", "last_30_days": "過去 30 天", @@ -1898,7 +1895,6 @@ "ttc_tooltip": "完成 問題 的 平均 時間。", "unknown_question_type": "未知的問題類型", "use_personal_links": "使用 個人 連結", - "waiting_for_response": "正在等待回應 🧘‍♂️", "whats_next": "下一步是什麼?", "your_survey_is_public": "您的問卷是公開的", "youre_not_plugged_in_yet": "您尚未插入任何內容!" diff --git a/apps/web/modules/analysis/components/SingleResponseCard/components/ResponseTagsWrapper.tsx b/apps/web/modules/analysis/components/SingleResponseCard/components/ResponseTagsWrapper.tsx index 1522db4646..f1142a2334 100644 --- a/apps/web/modules/analysis/components/SingleResponseCard/components/ResponseTagsWrapper.tsx +++ b/apps/web/modules/analysis/components/SingleResponseCard/components/ResponseTagsWrapper.tsx @@ -1,18 +1,18 @@ "use client"; -import { SettingsIcon } from "lucide-react"; -import { useRouter } from "next/navigation"; import React, { useEffect, useState } from "react"; import toast from "react-hot-toast"; import { useTranslation } from "react-i18next"; import { logger } from "@formbricks/logger"; +import { TResponse } from "@formbricks/types/responses"; import { TTag } from "@formbricks/types/tags"; +import { TUserLocale } from "@formbricks/types/user"; import { getFormattedErrorMessage } from "@/lib/utils/helper"; import { TagError } from "@/modules/projects/settings/types/tag"; -import { Button } from "@/modules/ui/components/button"; import { Tag } from "@/modules/ui/components/tag"; import { TagsCombobox } from "@/modules/ui/components/tags-combobox"; import { createTagAction, createTagToResponseAction, deleteTagOnResponseAction } from "../actions"; +import { SingleResponseCardMetadata } from "./SingleResponseCardMetadata"; interface ResponseTagsWrapperProps { tags: { @@ -24,6 +24,8 @@ interface ResponseTagsWrapperProps { environmentTags: TTag[]; updateFetchedResponses: () => void; isReadOnly?: boolean; + response: TResponse; + locale: TUserLocale; } export const ResponseTagsWrapper: React.FC = ({ @@ -33,9 +35,10 @@ export const ResponseTagsWrapper: React.FC = ({ environmentTags, updateFetchedResponses, isReadOnly, + response, + locale, }) => { const { t } = useTranslation(); - const router = useRouter(); const [searchValue, setSearchValue] = useState(""); const [open, setOpen] = React.useState(false); const [tagsState, setTagsState] = useState(tags); @@ -79,7 +82,6 @@ export const ResponseTagsWrapper: React.FC = ({ if (errorMessage?.code === TagError.TAG_NAME_ALREADY_EXISTS) { toast.error(t("environments.surveys.responses.tag_already_exists"), { duration: 2000, - icon: , }); } else { toast.error(t("environments.surveys.responses.an_error_occurred_creating_the_tag")); @@ -131,6 +133,7 @@ export const ResponseTagsWrapper: React.FC = ({ return (
+ {tagsState?.map((tag) => ( = ({ /> )}
- - {!isReadOnly && ( - - )}
); }; diff --git a/apps/web/modules/analysis/components/SingleResponseCard/components/SingleResponseCardHeader.tsx b/apps/web/modules/analysis/components/SingleResponseCard/components/SingleResponseCardHeader.tsx index 105d7af6a0..e0006ad71b 100644 --- a/apps/web/modules/analysis/components/SingleResponseCard/components/SingleResponseCardHeader.tsx +++ b/apps/web/modules/analysis/components/SingleResponseCard/components/SingleResponseCardHeader.tsx @@ -1,10 +1,8 @@ "use client"; -import { LanguagesIcon, TrashIcon } from "lucide-react"; +import { TrashIcon } from "lucide-react"; import Link from "next/link"; -import { ReactNode } from "react"; import { useTranslation } from "react-i18next"; -import { getLanguageLabel } from "@formbricks/i18n-utils/src/utils"; import { TEnvironment } from "@formbricks/types/environment"; import { TResponse } from "@formbricks/types/responses"; import { TSurvey } from "@formbricks/types/surveys/types"; @@ -12,17 +10,12 @@ import { TUser, TUserLocale } from "@formbricks/types/user"; import { timeSince } from "@/lib/time"; import { getContactIdentifier } from "@/lib/utils/contact"; import { PersonAvatar } from "@/modules/ui/components/avatars"; +import { Button } from "@/modules/ui/components/button"; import { IdBadge } from "@/modules/ui/components/id-badge"; import { SurveyStatusIndicator } from "@/modules/ui/components/survey-status-indicator"; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/modules/ui/components/tooltip"; import { isSubmissionTimeMoreThan5Minutes } from "../util"; -interface TooltipRendererProps { - shouldRender: boolean; - tooltipContent: ReactNode; - children: ReactNode; -} - interface SingleResponseCardHeaderProps { pageType: "people" | "response"; response: TResponse; @@ -54,140 +47,40 @@ export const SingleResponseCardHeader = ({ ? true : isSubmissionTimeMoreThan5Minutes(response.updatedAt); - const TooltipRenderer = ({ children, shouldRender, tooltipContent }: TooltipRendererProps) => { - return shouldRender ? ( - - - {children} - - {tooltipContent} - - - - ) : ( - <>{children} - ); - }; - - const renderTooltip = Boolean( - (response.contactAttributes && Object.keys(response.contactAttributes).length > 0) || - (response.meta.userAgent && Object.keys(response.meta.userAgent).length > 0) - ); - - const tooltipContent = ( - <> - {response.singleUseId && ( -
-

- {t("environments.surveys.responses.single_use_id")}: -

- {response.singleUseId} -
- )} - {response.contactAttributes && Object.keys(response.contactAttributes).length > 0 && ( -
-

- {t("environments.surveys.responses.person_attributes")}: -

- {Object.keys(response.contactAttributes).map((key) => ( -

- {key}:{" "} - - {response.contactAttributes && response.contactAttributes[key]} - -

- ))} -
- )} - - {response.meta.userAgent && Object.keys(response.meta.userAgent).length > 0 && ( -
- {response.contactAttributes && Object.keys(response.contactAttributes).length > 0 && ( -
- )} -

{t("environments.surveys.responses.device_info")}:

- {response.meta.userAgent?.browser && ( -

- {t("environments.surveys.responses.browser")}: {response.meta.userAgent.browser} -

- )} - {response.meta.userAgent?.os && ( -

- {t("environments.surveys.responses.os")}: {response.meta.userAgent.os} -

- )} - {response.meta.userAgent && ( -

- {t("environments.surveys.responses.device")}:{" "} - {response.meta.userAgent.device ? response.meta.userAgent.device : "PC / Generic device"} -

- )} - {response.meta.url && ( -

- {t("common.url")}: {response.meta.url} -

- )} - {response.meta.action && ( -

- {t("common.action")}: {response.meta.action} -

- )} - {response.meta.source && ( -

- {t("environments.surveys.responses.source")}: {response.meta.source} -

- )} - {response.meta.country && ( -

- {t("environments.surveys.responses.country")}: {response.meta.country} -

- )} -
- )} - - ); const deleteSubmissionToolTip = <>{t("environments.surveys.responses.this_response_is_in_progress")}; return (
-
+
{pageType === "response" && ( - -
- {response.contact?.id ? ( - user ? ( - - -

- {displayIdentifier} -

- {response.contact.userId && } - - ) : ( -
- -

- {displayIdentifier} -

- {response.contact.userId && } -
- ) + <> + {response.contact?.id ? ( + user ? ( + + +

+ {displayIdentifier} +

+ ) : ( -
- -

{t("common.anonymous")}

+
+ +

+ {displayIdentifier} +

- )} -
- + ) + ) : ( +
+ +

{t("common.anonymous")}

+
+ )} + {response.contact?.userId && } + )} {pageType === "people" && ( @@ -202,34 +95,34 @@ export const SingleResponseCardHeader = ({
)} - {response.language && response.language !== "default" && ( -
-
{getLanguageLabel(response.language, locale)}
- -
- )}
-
+
{user && !isReadOnly && (canResponseBeDeleted ? ( - setDeleteDialogOpen(true)} - className="h-4 w-4 cursor-pointer text-slate-500 hover:text-red-700" - aria-label="Delete response" - /> + aria-label="Delete response"> + + ) : ( - - + + {deleteSubmissionToolTip} diff --git a/apps/web/modules/analysis/components/SingleResponseCard/components/SingleResponseCardMetadata.tsx b/apps/web/modules/analysis/components/SingleResponseCard/components/SingleResponseCardMetadata.tsx new file mode 100644 index 0000000000..99a3ad2e0b --- /dev/null +++ b/apps/web/modules/analysis/components/SingleResponseCard/components/SingleResponseCardMetadata.tsx @@ -0,0 +1,163 @@ +"use client"; + +import { LanguagesIcon, LucideIcon, MonitorIcon, SmartphoneIcon, Tag } from "lucide-react"; +import { ReactNode } from "react"; +import { useTranslation } from "react-i18next"; +import { getLanguageLabel } from "@formbricks/i18n-utils/src/utils"; +import { TResponse } from "@formbricks/types/responses"; +import { TUserLocale } from "@formbricks/types/user"; +import { Button } from "@/modules/ui/components/button"; +import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/modules/ui/components/tooltip"; + +interface InfoIconButtonProps { + icon: LucideIcon; + tooltipContent: ReactNode; + ariaLabel: string; + maxWidth?: string; +} + +const InfoIconButton = ({ + icon: Icon, + tooltipContent, + ariaLabel, + maxWidth = "max-w-[75vw]", +}: InfoIconButtonProps) => { + return ( + + + + + + + {tooltipContent} + + + + ); +}; + +interface SingleResponseCardMetadataProps { + response: TResponse; + locale: TUserLocale; +} + +export const SingleResponseCardMetadata = ({ response, locale }: SingleResponseCardMetadataProps) => { + const { t } = useTranslation(); + + const hasContactAttributes = + response.contactAttributes && Object.keys(response.contactAttributes).length > 0; + const hasUserAgent = response.meta.userAgent && Object.keys(response.meta.userAgent).length > 0; + const hasLanguage = response.language && response.language !== "default"; + + if (!hasContactAttributes && !hasUserAgent && !hasLanguage) { + return null; + } + + const userAgentDeviceIcon = (() => { + if (!hasUserAgent || !response.meta.userAgent?.device) return MonitorIcon; + const device = response.meta.userAgent.device.toLowerCase(); + return device.includes("mobile") || device.includes("phone") ? SmartphoneIcon : MonitorIcon; + })(); + + const contactAttributesTooltipContent = hasContactAttributes ? ( +
+ {response.singleUseId && ( +
+

+ {t("environments.surveys.responses.single_use_id")} +

+ {response.singleUseId} +
+ )} +

+ {t("environments.surveys.responses.person_attributes")} +

+ {Object.keys(response.contactAttributes || {}).map((key) => ( +

+ {key}: {response.contactAttributes?.[key]} +

+ ))} +
+ ) : null; + + const userAgentTooltipContent = hasUserAgent ? ( +
+

{t("environments.surveys.responses.device_info")}

+ {response.meta.userAgent?.browser && ( +

+ {t("environments.surveys.responses.browser")}: {response.meta.userAgent.browser} +

+ )} + {response.meta.userAgent?.os && ( +

+ {t("environments.surveys.responses.os")}: {response.meta.userAgent.os} +

+ )} + {response.meta.userAgent && ( +

+ {t("environments.surveys.responses.device")}:{" "} + {response.meta.userAgent.device ? response.meta.userAgent.device : "PC / Generic device"} +

+ )} + {response.meta.url && ( +

+ {t("common.url")}: {response.meta.url} +

+ )} + {response.meta.action && ( +

+ {t("common.action")}: {response.meta.action} +

+ )} + {response.meta.source && ( +

+ {t("environments.surveys.responses.source")}: {response.meta.source} +

+ )} + {response.meta.country && ( +

+ {t("environments.surveys.responses.country")}: {response.meta.country} +

+ )} +
+ ) : null; + + const languageTooltipContent = + hasLanguage && response.language ? ( +
+

{t("common.language")}

+

{getLanguageLabel(response.language, locale)}

+
+ ) : null; + + return ( +
+ {hasContactAttributes && contactAttributesTooltipContent && ( + + )} + {hasUserAgent && userAgentTooltipContent && ( + + )} + {hasLanguage && languageTooltipContent && ( + + )} +
+ ); +}; diff --git a/apps/web/modules/analysis/components/SingleResponseCard/index.tsx b/apps/web/modules/analysis/components/SingleResponseCard/index.tsx index 21c441490a..2793c88074 100644 --- a/apps/web/modules/analysis/components/SingleResponseCard/index.tsx +++ b/apps/web/modules/analysis/components/SingleResponseCard/index.tsx @@ -143,6 +143,8 @@ export const SingleResponseCard = ({ environmentTags={environmentTags} updateFetchedResponses={updateFetchedResponses} isReadOnly={isReadOnly} + response={response} + locale={locale} /> { + const { t } = useTranslation(); const [fetchedResponses, setFetchedResponses] = useState(responses); useEffect(() => { @@ -50,7 +52,7 @@ export const ResponseFeed = ({ return ( <> {fetchedResponses.length === 0 ? ( - + ) : ( fetchedResponses.map((response) => (
- {data && hasMore && data.length > 0 && ( + {data && hasMore && data.length > 0 && isDataLoaded && (
diff --git a/apps/web/modules/ee/contacts/segments/components/segment-table.tsx b/apps/web/modules/ee/contacts/segments/components/segment-table.tsx index e196f859a4..66ad4aa5ac 100644 --- a/apps/web/modules/ee/contacts/segments/components/segment-table.tsx +++ b/apps/web/modules/ee/contacts/segments/components/segment-table.tsx @@ -33,6 +33,7 @@ export const SegmentTable = async ({ <> {segments.map((segment) => ( {webhooks.length === 0 ? ( - + ) : (
{TableHeading} diff --git a/apps/web/modules/projects/settings/tags/components/edit-tags-wrapper.tsx b/apps/web/modules/projects/settings/tags/components/edit-tags-wrapper.tsx index 3bab4ec28d..d3d9309bdb 100644 --- a/apps/web/modules/projects/settings/tags/components/edit-tags-wrapper.tsx +++ b/apps/web/modules/projects/settings/tags/components/edit-tags-wrapper.tsx @@ -2,13 +2,11 @@ import React from "react"; import { useTranslation } from "react-i18next"; -import { TEnvironment } from "@formbricks/types/environment"; import { TTag, TTagsCount } from "@formbricks/types/tags"; import { SingleTag } from "@/modules/projects/settings/tags/components/single-tag"; -import { EmptySpaceFiller } from "@/modules/ui/components/empty-space-filler"; +import { EmptyState } from "@/modules/ui/components/empty-state"; interface EditTagsWrapperProps { - environment: TEnvironment; environmentTags: TTag[]; environmentTagsCount: TTagsCount; isReadOnly: boolean; @@ -16,7 +14,12 @@ interface EditTagsWrapperProps { export const EditTagsWrapper: React.FC = (props) => { const { t } = useTranslation(); - const { environment, environmentTags, environmentTagsCount, isReadOnly } = props; + const { environmentTags, environmentTagsCount, isReadOnly } = props; + + if (!environmentTags?.length) { + return ; + } + return (
@@ -27,11 +30,7 @@ export const EditTagsWrapper: React.FC = (props) => { )}
- {!environmentTags?.length ? ( - - ) : null} - - {environmentTags?.map((tag) => ( + {environmentTags.map((tag) => ( { const params = await props.params; const t = await getTranslate(); - const { isReadOnly, environment } = await getEnvironmentAuth(params.environmentId); + const { isReadOnly } = await getEnvironmentAuth(params.environmentId); const [tags, environmentTagsCount] = await Promise.all([ getTagsByEnvironmentId(params.environmentId), @@ -28,7 +28,6 @@ export const TagsPage = async (props) => { title={t("environments.project.tags.manage_tags")} description={t("environments.project.tags.manage_tags_description")}> { - const { t } = useTranslation(); - if (type === "table") { - return ( -
-
-
-
- {!environment.appSetupCompleted && !noWidgetRequired && ( - - - {t("environments.surveys.summary.install_widget")}{" "} - {t("environments.surveys.summary.go_to_setup_checklist")} - - - )} - {((environment.appSetupCompleted || noWidgetRequired) && emptyMessage) || - t("environments.surveys.summary.waiting_for_response")} -
- -
-
-
- ); - } - - if (type === "response") { - return ( -
-
-
-
-
-
-
-
- {!environment.appSetupCompleted && !noWidgetRequired && ( - - - {t("environments.surveys.summary.install_widget")}{" "} - {t("environments.surveys.summary.go_to_setup_checklist")} - - - )} - {(environment.appSetupCompleted || noWidgetRequired) && ( - - {emptyMessage ?? t("environments.surveys.summary.waiting_for_response")} - - )} -
-
-
-
- ); - } - - if (type === "tag") { - return ( -
-
-
-
-
-
-
-
- {!environment.appSetupCompleted && !noWidgetRequired && ( - - - {t("environments.surveys.summary.install_widget")}{" "} - {t("environments.surveys.summary.go_to_setup_checklist")} 👉 - - - )} - {(environment.appSetupCompleted || noWidgetRequired) && ( - {t("environments.project.tags.empty_message")} - )} -
-
-
-
- ); - } - - if (type === "summary") { - return ( -
- -
-
-
-
-
-
-
-
-
-
-
-
-
- ); - } - - return ( -
-
-
-
-
-
-
-
- {!environment.appSetupCompleted && !noWidgetRequired && ( - - - {t("environments.surveys.summary.install_widget")}{" "} - {t("environments.surveys.summary.go_to_setup_checklist")} 👉 - - - )} - {(environment.appSetupCompleted || noWidgetRequired) && ( - {t("environments.surveys.summary.waiting_for_response")} - )} -
-
-
-
- ); -}; diff --git a/apps/web/modules/ui/components/empty-state/index.tsx b/apps/web/modules/ui/components/empty-state/index.tsx new file mode 100644 index 0000000000..e23dc6ed82 --- /dev/null +++ b/apps/web/modules/ui/components/empty-state/index.tsx @@ -0,0 +1,19 @@ +"use client"; + +interface EmptyStateProps { + text: string; +} + +export const EmptyState = ({ text }: EmptyStateProps) => { + return ( +
+
+
+
+ {text} +
+
+
+
+ ); +}; diff --git a/apps/web/modules/ui/components/tags-combobox/index.tsx b/apps/web/modules/ui/components/tags-combobox/index.tsx index 376ad88d19..5b666ee195 100644 --- a/apps/web/modules/ui/components/tags-combobox/index.tsx +++ b/apps/web/modules/ui/components/tags-combobox/index.tsx @@ -63,9 +63,7 @@ export const TagsCombobox = ({ return ( - +