mirror of
https://github.com/formbricks/formbricks.git
synced 2026-04-16 03:21:30 -05:00
Compare commits
3 Commits
tweak/add-
...
fix/rating
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2ebc493a7b | ||
|
|
8618ab8b06 | ||
|
|
439dd0b44e |
@@ -0,0 +1,22 @@
|
||||
"use client";
|
||||
|
||||
import { PageContentWrapper } from "@/modules/ui/components/page-content-wrapper";
|
||||
import { PageHeader } from "@/modules/ui/components/page-header";
|
||||
import { SkeletonLoader } from "@/modules/ui/components/skeleton-loader";
|
||||
|
||||
const Loading = () => {
|
||||
return (
|
||||
<PageContentWrapper>
|
||||
<PageHeader pageTitle="" />
|
||||
<div className="flex h-9 animate-pulse gap-2">
|
||||
<div className="h-9 w-36 rounded-full bg-slate-200" />
|
||||
<div className="h-9 w-36 rounded-full bg-slate-200" />
|
||||
<div className="h-9 w-36 rounded-full bg-slate-200" />
|
||||
<div className="h-9 w-36 rounded-full bg-slate-200" />
|
||||
</div>
|
||||
<SkeletonLoader type="summary" />
|
||||
</PageContentWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export default Loading;
|
||||
@@ -0,0 +1,23 @@
|
||||
"use client";
|
||||
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { PageContentWrapper } from "@/modules/ui/components/page-content-wrapper";
|
||||
import { PageHeader } from "@/modules/ui/components/page-header";
|
||||
import { SkeletonLoader } from "@/modules/ui/components/skeleton-loader";
|
||||
|
||||
const Loading = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<PageContentWrapper>
|
||||
<PageHeader pageTitle={t("common.responses")} />
|
||||
<div className="flex h-9 animate-pulse gap-1.5">
|
||||
<div className="h-9 w-36 rounded-full bg-slate-200" />
|
||||
<div className="h-9 w-36 rounded-full bg-slate-200" />
|
||||
</div>
|
||||
<SkeletonLoader type="responseTable" />
|
||||
</PageContentWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export default Loading;
|
||||
@@ -1289,7 +1289,7 @@ checksums:
|
||||
environments/surveys/edit/audience: a4d9fab4214a641e2d358fbb28f010e0
|
||||
environments/surveys/edit/auto_close_on_inactivity: 093db516799315ccd4242a3675693012
|
||||
environments/surveys/edit/auto_progress_rating_and_nps: 76b98e95a5b850850baa0ccc3c7fbf7c
|
||||
environments/surveys/edit/auto_progress_rating_and_nps_description: 2a992dd8a5b9532f178f9a21881feb9a
|
||||
environments/surveys/edit/auto_progress_rating_and_nps_description: cbf676789b9f3f47e36bdf35fa58282b
|
||||
environments/surveys/edit/auto_save_disabled: f7411fb0dcfb8f7b19b85f0be54f2231
|
||||
environments/surveys/edit/auto_save_disabled_tooltip: 77322e1e866b7d29f7641a88bbd3b681
|
||||
environments/surveys/edit/auto_save_on: 1524d466830b00c5d727c701db404963
|
||||
@@ -2181,12 +2181,12 @@ checksums:
|
||||
environments/workspace/look/advanced_styling_field_track_bg_description: 8a56258273dfe49e83fe752ea9e8daed
|
||||
environments/workspace/look/advanced_styling_field_track_height: 9ce57cb4583039c224a37e013efb6b8f
|
||||
environments/workspace/look/advanced_styling_field_track_height_description: 90243a4374e15d9118ad0fd93d5f3614
|
||||
environments/workspace/look/advanced_styling_field_upper_label_color: 65d75c60dfdba88e5fed38bcb24a0a5d
|
||||
environments/workspace/look/advanced_styling_field_upper_label_color_description: ae2276506807c7ceeb7a8b87723a8dd4
|
||||
environments/workspace/look/advanced_styling_field_upper_label_size: ea0ca9a3ffa1650f97a31df453b0afc7
|
||||
environments/workspace/look/advanced_styling_field_upper_label_size_description: 061668625be0f7a68ebc2e2ebe49e5a9
|
||||
environments/workspace/look/advanced_styling_field_upper_label_weight: 946c5836d2cfaaee21e494424d550887
|
||||
environments/workspace/look/advanced_styling_field_upper_label_weight_description: 916b03c719a8dead351679336aabcf53
|
||||
environments/workspace/look/advanced_styling_field_upper_label_color: 896bc12d6c77f162abf189589e11287e
|
||||
environments/workspace/look/advanced_styling_field_upper_label_color_description: 1bc4b92821ff694c18396a872ca0fb60
|
||||
environments/workspace/look/advanced_styling_field_upper_label_size: 0d915cf63b845a0c4c6004efc731babf
|
||||
environments/workspace/look/advanced_styling_field_upper_label_size_description: 8e9e348318b72837c9e04f81701b2fb6
|
||||
environments/workspace/look/advanced_styling_field_upper_label_weight: 9128dcfea0e5b1e0fdf4f5902f6ea2d6
|
||||
environments/workspace/look/advanced_styling_field_upper_label_weight_description: 3a9006a41ab84aea98d4291a6d5db9db
|
||||
environments/workspace/look/advanced_styling_section_buttons: 3b44d6e2800e7bf3f133f1bce435f4c2
|
||||
environments/workspace/look/advanced_styling_section_headlines: 6def704c0ac2ecb5951400c806856a41
|
||||
environments/workspace/look/advanced_styling_section_inputs: 76bbeb561122a72fd3ec8c49eff7c563
|
||||
|
||||
@@ -1360,7 +1360,7 @@
|
||||
"audience": "Publikum",
|
||||
"auto_close_on_inactivity": "Automatisches Schließen bei Inaktivität",
|
||||
"auto_progress_rating_and_nps": "Bewertungs- und NPS-Fragen automatisch fortsetzen",
|
||||
"auto_progress_rating_and_nps_description": "Automatisches Weitergehen bei Einzelfragen-Blöcken. Pflichtfragen blenden Weiter aus, außer wenn \"Sonstiges\" ausgewählt ist.",
|
||||
"auto_progress_rating_and_nps_description": "Fahre automatisch fort, sobald Befragte eine Antwort bei Bewertungs- oder NPS-Fragen auswählen. Dies gilt nur für Blöcke mit einer einzelnen Frage. Bei Pflichtfragen wird die Weiter-Schaltfläche ausgeblendet; bei optionalen Fragen bleibt sie zum Überspringen sichtbar.",
|
||||
"auto_save_disabled": "Automatisches Speichern deaktiviert",
|
||||
"auto_save_disabled_tooltip": "Ihre Umfrage wird nur im Entwurfsmodus automatisch gespeichert. So wird sichergestellt, dass öffentliche Umfragen nicht unbeabsichtigt aktualisiert werden.",
|
||||
"auto_save_on": "Automatisches Speichern an",
|
||||
@@ -2298,11 +2298,11 @@
|
||||
"advanced_styling_field_track_bg_description": "Färbt den nicht ausgefüllten Teil des Balkens.",
|
||||
"advanced_styling_field_track_height": "Track-Höhe",
|
||||
"advanced_styling_field_track_height_description": "Steuert die Dicke des Fortschrittsbalkens.",
|
||||
"advanced_styling_field_upper_label_color": "Farbe des oberen Labels",
|
||||
"advanced_styling_field_upper_label_color_description": "Färbt die kleine Beschriftung über Eingabefeldern.",
|
||||
"advanced_styling_field_upper_label_size": "Schriftgröße des oberen Labels",
|
||||
"advanced_styling_field_upper_label_size_description": "Skaliert die kleine Beschriftung über Eingabefeldern.",
|
||||
"advanced_styling_field_upper_label_weight": "Schriftstärke des oberen Labels",
|
||||
"advanced_styling_field_upper_label_color": "Labelfarbe",
|
||||
"advanced_styling_field_upper_label_color_description": "Färbt die kleine Beschriftung über Eingabefeldern und Skalenbeschriftungen.",
|
||||
"advanced_styling_field_upper_label_size": "Label-Schriftgröße",
|
||||
"advanced_styling_field_upper_label_size_description": "Skaliert die kleine Beschriftung über Eingabefeldern und Skalenbeschriftungen.",
|
||||
"advanced_styling_field_upper_label_weight": "Label-Schriftstärke",
|
||||
"advanced_styling_field_upper_label_weight_description": "Macht die Beschriftung leichter oder fetter.",
|
||||
"advanced_styling_section_buttons": "Buttons",
|
||||
"advanced_styling_section_headlines": "Überschriften & Beschreibungen",
|
||||
|
||||
@@ -1360,7 +1360,7 @@
|
||||
"audience": "Audience",
|
||||
"auto_close_on_inactivity": "Auto close on inactivity",
|
||||
"auto_progress_rating_and_nps": "Auto-progress rating and NPS questions",
|
||||
"auto_progress_rating_and_nps_description": "Auto-advance in single-question blocks. Required questions hide Next, except when \"Other\" is selected.",
|
||||
"auto_progress_rating_and_nps_description": "Automatically advance when respondents select an answer on rating or NPS questions. This only applies to single-question blocks. Required questions hide the Next button; optional questions still show it for skipping.",
|
||||
"auto_save_disabled": "Auto-save disabled",
|
||||
"auto_save_disabled_tooltip": "Your survey is only auto-saved when in draft. This assures public surveys are not unintentionally updated.",
|
||||
"auto_save_on": "Auto-save on",
|
||||
@@ -2298,12 +2298,12 @@
|
||||
"advanced_styling_field_track_bg_description": "Colors the unfilled portion of the bar.",
|
||||
"advanced_styling_field_track_height": "Track Height",
|
||||
"advanced_styling_field_track_height_description": "Controls the progress bar thickness.",
|
||||
"advanced_styling_field_upper_label_color": "Headline Label Color",
|
||||
"advanced_styling_field_upper_label_color_description": "Colors the small label above inputs.",
|
||||
"advanced_styling_field_upper_label_size": "Headline Label Font Size",
|
||||
"advanced_styling_field_upper_label_size_description": "Scales the small label above inputs.",
|
||||
"advanced_styling_field_upper_label_weight": "Headline Label Font Weight",
|
||||
"advanced_styling_field_upper_label_weight_description": "Makes the label lighter or bolder.",
|
||||
"advanced_styling_field_upper_label_color": "Label Color",
|
||||
"advanced_styling_field_upper_label_color_description": "Colors the small labels above inputs and scale labels.",
|
||||
"advanced_styling_field_upper_label_size": "Label Font Size",
|
||||
"advanced_styling_field_upper_label_size_description": "Scales the small labels above inputs and scale labels.",
|
||||
"advanced_styling_field_upper_label_weight": "Label Font Weight",
|
||||
"advanced_styling_field_upper_label_weight_description": "Makes the labels lighter or bolder.",
|
||||
"advanced_styling_section_buttons": "Buttons",
|
||||
"advanced_styling_section_headlines": "Headlines & Descriptions",
|
||||
"advanced_styling_section_inputs": "Inputs",
|
||||
|
||||
@@ -1360,7 +1360,7 @@
|
||||
"audience": "Audiencia",
|
||||
"auto_close_on_inactivity": "Cierre automático por inactividad",
|
||||
"auto_progress_rating_and_nps": "Avanzar automáticamente en preguntas de valoración y NPS",
|
||||
"auto_progress_rating_and_nps_description": "Avance automático en bloques de una sola pregunta. Las preguntas obligatorias ocultan Siguiente, excepto cuando se selecciona \"Otro\".",
|
||||
"auto_progress_rating_and_nps_description": "Avanza automáticamente cuando los encuestados seleccionen una respuesta en preguntas de valoración o NPS. Esto solo se aplica a bloques de una sola pregunta. Las preguntas obligatorias ocultan el botón Siguiente; las preguntas opcionales aún lo muestran para omitirlas.",
|
||||
"auto_save_disabled": "Guardado automático desactivado",
|
||||
"auto_save_disabled_tooltip": "Su encuesta solo se guarda automáticamente cuando está en borrador. Esto asegura que las encuestas públicas no se actualicen involuntariamente.",
|
||||
"auto_save_on": "Guardado automático activado",
|
||||
@@ -2298,12 +2298,12 @@
|
||||
"advanced_styling_field_track_bg_description": "Colorea la parte no rellenada de la barra.",
|
||||
"advanced_styling_field_track_height": "Altura de la pista",
|
||||
"advanced_styling_field_track_height_description": "Controla el grosor de la barra de progreso.",
|
||||
"advanced_styling_field_upper_label_color": "Color de la etiqueta del titular",
|
||||
"advanced_styling_field_upper_label_color_description": "Colorea la etiqueta pequeña sobre los campos de entrada.",
|
||||
"advanced_styling_field_upper_label_size": "Tamaño de fuente de la etiqueta del titular",
|
||||
"advanced_styling_field_upper_label_size_description": "Escala la etiqueta pequeña sobre los campos de entrada.",
|
||||
"advanced_styling_field_upper_label_weight": "Grosor de fuente de la etiqueta del titular",
|
||||
"advanced_styling_field_upper_label_weight_description": "Hace que la etiqueta sea más ligera o más gruesa.",
|
||||
"advanced_styling_field_upper_label_color": "Color de la etiqueta",
|
||||
"advanced_styling_field_upper_label_color_description": "Colorea las etiquetas pequeñas sobre los campos de entrada y las etiquetas de escala.",
|
||||
"advanced_styling_field_upper_label_size": "Tamaño de fuente de la etiqueta",
|
||||
"advanced_styling_field_upper_label_size_description": "Escala las etiquetas pequeñas sobre los campos de entrada y las etiquetas de escala.",
|
||||
"advanced_styling_field_upper_label_weight": "Grosor de fuente de la etiqueta",
|
||||
"advanced_styling_field_upper_label_weight_description": "Hace que las etiquetas sean más ligeras o más gruesas.",
|
||||
"advanced_styling_section_buttons": "Botones",
|
||||
"advanced_styling_section_headlines": "Títulos y descripciones",
|
||||
"advanced_styling_section_inputs": "Campos de entrada",
|
||||
|
||||
@@ -1360,7 +1360,7 @@
|
||||
"audience": "Public",
|
||||
"auto_close_on_inactivity": "Fermeture automatique en cas d'inactivité",
|
||||
"auto_progress_rating_and_nps": "Progression automatique pour les questions d'évaluation et NPS",
|
||||
"auto_progress_rating_and_nps_description": "Avancement automatique dans les blocs à question unique. Les questions obligatoires masquent le bouton Suivant, sauf lorsque « Autre » est sélectionné.",
|
||||
"auto_progress_rating_and_nps_description": "Passe automatiquement à la question suivante lorsque les répondants sélectionnent une réponse aux questions d'évaluation ou NPS. Cela s'applique uniquement aux blocs à question unique. Les questions obligatoires masquent le bouton Suivant ; les questions facultatives l'affichent toujours pour permettre de passer la question.",
|
||||
"auto_save_disabled": "Sauvegarde automatique désactivée",
|
||||
"auto_save_disabled_tooltip": "Votre sondage n'est sauvegardé automatiquement que lorsqu'il est en brouillon. Cela garantit que les sondages publics ne sont pas mis à jour involontairement.",
|
||||
"auto_save_on": "Sauvegarde automatique activée",
|
||||
@@ -2298,12 +2298,12 @@
|
||||
"advanced_styling_field_track_bg_description": "Colore la partie non remplie de la barre.",
|
||||
"advanced_styling_field_track_height": "Hauteur de la piste",
|
||||
"advanced_styling_field_track_height_description": "Contrôle l'épaisseur de la barre de progression.",
|
||||
"advanced_styling_field_upper_label_color": "Couleur de l'étiquette du titre",
|
||||
"advanced_styling_field_upper_label_color_description": "Colore le petit libellé au-dessus des champs de saisie.",
|
||||
"advanced_styling_field_upper_label_size": "Taille de police de l'étiquette du titre",
|
||||
"advanced_styling_field_upper_label_size_description": "Ajuste la taille du petit libellé au-dessus des champs de saisie.",
|
||||
"advanced_styling_field_upper_label_weight": "Graisse de police de l'étiquette du titre",
|
||||
"advanced_styling_field_upper_label_weight_description": "Rend le libellé plus léger ou plus gras.",
|
||||
"advanced_styling_field_upper_label_color": "Couleur de l'étiquette",
|
||||
"advanced_styling_field_upper_label_color_description": "Colore les petits libellés au-dessus des champs de saisie et les libellés d'échelle.",
|
||||
"advanced_styling_field_upper_label_size": "Taille de police de l'étiquette",
|
||||
"advanced_styling_field_upper_label_size_description": "Ajuste la taille des petits libellés au-dessus des champs de saisie et des libellés d'échelle.",
|
||||
"advanced_styling_field_upper_label_weight": "Graisse de police de l'étiquette",
|
||||
"advanced_styling_field_upper_label_weight_description": "Rend les libellés plus légers ou plus gras.",
|
||||
"advanced_styling_section_buttons": "Boutons",
|
||||
"advanced_styling_section_headlines": "Titres et descriptions",
|
||||
"advanced_styling_section_inputs": "Champs de saisie",
|
||||
|
||||
@@ -1360,7 +1360,7 @@
|
||||
"audience": "Közönség",
|
||||
"auto_close_on_inactivity": "Automatikus lezárás tétlenségnél",
|
||||
"auto_progress_rating_and_nps": "Automatikus továbblépés értékelési és NPS kérdéseknél",
|
||||
"auto_progress_rating_and_nps_description": "Automatikus továbblépés egy kérdést tartalmazó blokkokban. A kötelező kérdések elrejtik a Tovább gombot, kivéve amikor az „Egyéb“ opció van kiválasztva.",
|
||||
"auto_progress_rating_and_nps_description": "Automatikus továbblépés, amikor a válaszadók kiválasztanak egy választ az értékelési vagy NPS kérdéseknél. Ez csak az egykérdéses blokkokra vonatkozik. A kötelező kérdések elrejtik a Tovább gombot; az opcionális kérdések továbbra is megjelenítik azt a kihagyás lehetősége érdekében.",
|
||||
"auto_save_disabled": "Az automatikus mentés letiltva",
|
||||
"auto_save_disabled_tooltip": "A kérdőív csak akkor kerül automatikusan mentésre, ha piszkozatban van. Ez biztosítja, hogy a nyilvános kérdőívek ne legyenek véletlenül frissítve.",
|
||||
"auto_save_on": "Automatikus mentés bekapcsolva",
|
||||
@@ -2298,12 +2298,12 @@
|
||||
"advanced_styling_field_track_bg_description": "Kiszínezi a sáv kitöltetlen részét.",
|
||||
"advanced_styling_field_track_height": "Követés magassága",
|
||||
"advanced_styling_field_track_height_description": "A folyamatjelző vastagságát vezérli.",
|
||||
"advanced_styling_field_upper_label_color": "Címsor címkéjének színe",
|
||||
"advanced_styling_field_upper_label_color_description": "Kiszínezi a beviteli mezők fölötti kis címkéket.",
|
||||
"advanced_styling_field_upper_label_size": "Címsor címkéjének betűmérete",
|
||||
"advanced_styling_field_upper_label_size_description": "Átméretezi a beviteli mezők fölötti kis címkéket.",
|
||||
"advanced_styling_field_upper_label_weight": "Címsor címkéjének betűvastagsága",
|
||||
"advanced_styling_field_upper_label_weight_description": "Vékonyabbá vagy vastagabbá teszi a címkét.",
|
||||
"advanced_styling_field_upper_label_color": "Címke színe",
|
||||
"advanced_styling_field_upper_label_color_description": "Kiszínezi a beviteli mezők fölötti kis címkéket és a skálacímkéket.",
|
||||
"advanced_styling_field_upper_label_size": "Címke betűmérete",
|
||||
"advanced_styling_field_upper_label_size_description": "Átméretezi a beviteli mezők fölötti kis címkéket és a skálacímkéket.",
|
||||
"advanced_styling_field_upper_label_weight": "Címke betűvastagsága",
|
||||
"advanced_styling_field_upper_label_weight_description": "Vékonyabbá vagy vastagabbá teszi a címkéket.",
|
||||
"advanced_styling_section_buttons": "Gombok",
|
||||
"advanced_styling_section_headlines": "Címsorok és leírások",
|
||||
"advanced_styling_section_inputs": "Beviteli mezők",
|
||||
|
||||
@@ -1360,7 +1360,7 @@
|
||||
"audience": "オーディエンス",
|
||||
"auto_close_on_inactivity": "非アクティブ時に自動閉鎖",
|
||||
"auto_progress_rating_and_nps": "評価とNPSの質問を自動進行",
|
||||
"auto_progress_rating_and_nps_description": "単一質問ブロックで自動的に次へ進みます。必須質問では「次へ」ボタンが非表示になりますが、「その他」が選択された場合は表示されます。",
|
||||
"auto_progress_rating_and_nps_description": "評価またはNPSの質問で回答者が選択肢を選んだ際に自動的に次へ進みます。これは単一質問ブロックにのみ適用されます。必須の質問では「次へ」ボタンが非表示になり、任意の質問ではスキップ用に引き続き表示されます。",
|
||||
"auto_save_disabled": "自動保存が無効",
|
||||
"auto_save_disabled_tooltip": "アンケートは下書き状態の時のみ自動保存されます。これにより、公開中のアンケートが意図せず更新されることを防ぎます。",
|
||||
"auto_save_on": "自動保存オン",
|
||||
@@ -2298,11 +2298,11 @@
|
||||
"advanced_styling_field_track_bg_description": "バーの未入力部分の色を設定します。",
|
||||
"advanced_styling_field_track_height": "トラックの高さ",
|
||||
"advanced_styling_field_track_height_description": "プログレスバーの太さを調整します。",
|
||||
"advanced_styling_field_upper_label_color": "見出しラベルの色",
|
||||
"advanced_styling_field_upper_label_color_description": "入力フィールド上部の小さなラベルの色を設定します。",
|
||||
"advanced_styling_field_upper_label_size": "見出しラベルのフォントサイズ",
|
||||
"advanced_styling_field_upper_label_size_description": "入力フィールド上部の小さなラベルのサイズを調整します。",
|
||||
"advanced_styling_field_upper_label_weight": "見出しラベルのフォントの太さ",
|
||||
"advanced_styling_field_upper_label_color": "ラベルの色",
|
||||
"advanced_styling_field_upper_label_color_description": "入力フィールド上部の小さなラベルとスケールラベルの色を設定します。",
|
||||
"advanced_styling_field_upper_label_size": "ラベルのフォントサイズ",
|
||||
"advanced_styling_field_upper_label_size_description": "入力フィールド上部の小さなラベルとスケールラベルのサイズを調整します。",
|
||||
"advanced_styling_field_upper_label_weight": "ラベルのフォントの太さ",
|
||||
"advanced_styling_field_upper_label_weight_description": "ラベルを細くまたは太くします。",
|
||||
"advanced_styling_section_buttons": "ボタン",
|
||||
"advanced_styling_section_headlines": "見出しと説明",
|
||||
|
||||
@@ -1360,7 +1360,7 @@
|
||||
"audience": "Publiek",
|
||||
"auto_close_on_inactivity": "Automatisch sluiten bij inactiviteit",
|
||||
"auto_progress_rating_and_nps": "Automatisch doorgaan bij beoordelings- en NPS-vragen",
|
||||
"auto_progress_rating_and_nps_description": "Automatisch doorgaan bij blokken met één vraag. Verplichte vragen verbergen Volgende, behalve wanneer \"Anders\" is geselecteerd.",
|
||||
"auto_progress_rating_and_nps_description": "Ga automatisch verder wanneer respondenten een antwoord selecteren bij beoordelings- of NPS-vragen. Dit geldt alleen voor blokken met één vraag. Bij verplichte vragen wordt de Volgende-knop verborgen; bij optionele vragen blijft deze zichtbaar om de vraag over te slaan.",
|
||||
"auto_save_disabled": "Automatisch opslaan uitgeschakeld",
|
||||
"auto_save_disabled_tooltip": "Uw enquête wordt alleen automatisch opgeslagen wanneer deze een concept is. Dit zorgt ervoor dat openbare enquêtes niet onbedoeld worden bijgewerkt.",
|
||||
"auto_save_on": "Automatisch opslaan aan",
|
||||
@@ -2298,12 +2298,12 @@
|
||||
"advanced_styling_field_track_bg_description": "Kleurt het ongevulde gedeelte van de balk.",
|
||||
"advanced_styling_field_track_height": "Spoorhoogte",
|
||||
"advanced_styling_field_track_height_description": "Regelt de dikte van de voortgangsbalk.",
|
||||
"advanced_styling_field_upper_label_color": "Koplabelkleur",
|
||||
"advanced_styling_field_upper_label_color_description": "Kleurt het kleine label boven invoervelden.",
|
||||
"advanced_styling_field_upper_label_size": "Lettergrootte koplabel",
|
||||
"advanced_styling_field_upper_label_size_description": "Schaalt het kleine label boven invoervelden.",
|
||||
"advanced_styling_field_upper_label_weight": "Letterdikte koplabel",
|
||||
"advanced_styling_field_upper_label_weight_description": "Maakt het label lichter of vetter.",
|
||||
"advanced_styling_field_upper_label_color": "Labelkleur",
|
||||
"advanced_styling_field_upper_label_color_description": "Kleurt de kleine labels boven invoervelden en schaallabels.",
|
||||
"advanced_styling_field_upper_label_size": "Lettergrootte label",
|
||||
"advanced_styling_field_upper_label_size_description": "Schaalt de kleine labels boven invoervelden en schaallabels.",
|
||||
"advanced_styling_field_upper_label_weight": "Letterdikte label",
|
||||
"advanced_styling_field_upper_label_weight_description": "Maakt de labels lichter of vetter.",
|
||||
"advanced_styling_section_buttons": "Knoppen",
|
||||
"advanced_styling_section_headlines": "Koppen & beschrijvingen",
|
||||
"advanced_styling_section_inputs": "Invoervelden",
|
||||
|
||||
@@ -1360,7 +1360,7 @@
|
||||
"audience": "Público",
|
||||
"auto_close_on_inactivity": "Fechar automaticamente por inatividade",
|
||||
"auto_progress_rating_and_nps": "Avançar automaticamente em perguntas de avaliação e NPS",
|
||||
"auto_progress_rating_and_nps_description": "Avança automaticamente em blocos de pergunta única. Perguntas obrigatórias ocultam o botão Próximo, exceto quando \"Outro\" está selecionado.",
|
||||
"auto_progress_rating_and_nps_description": "Avança automaticamente quando os respondentes selecionam uma resposta em perguntas de avaliação ou NPS. Isso se aplica apenas a blocos com uma única pergunta. Perguntas obrigatórias ocultam o botão Próximo; perguntas opcionais ainda o exibem para permitir pular.",
|
||||
"auto_save_disabled": "Salvamento automático desativado",
|
||||
"auto_save_disabled_tooltip": "Sua pesquisa só é salva automaticamente quando está em rascunho. Isso garante que pesquisas públicas não sejam atualizadas involuntariamente.",
|
||||
"auto_save_on": "Salvamento automático ativado",
|
||||
@@ -2298,12 +2298,12 @@
|
||||
"advanced_styling_field_track_bg_description": "Colore a porção não preenchida da barra.",
|
||||
"advanced_styling_field_track_height": "Altura da trilha",
|
||||
"advanced_styling_field_track_height_description": "Controla a espessura da barra de progresso.",
|
||||
"advanced_styling_field_upper_label_color": "Cor do rótulo do título",
|
||||
"advanced_styling_field_upper_label_color_description": "Colore o pequeno rótulo acima dos campos de entrada.",
|
||||
"advanced_styling_field_upper_label_size": "Tamanho da fonte do rótulo do título",
|
||||
"advanced_styling_field_upper_label_size_description": "Ajusta o tamanho do pequeno rótulo acima dos campos de entrada.",
|
||||
"advanced_styling_field_upper_label_weight": "Peso da fonte do rótulo do título",
|
||||
"advanced_styling_field_upper_label_weight_description": "Torna o rótulo mais leve ou mais negrito.",
|
||||
"advanced_styling_field_upper_label_color": "Cor do rótulo",
|
||||
"advanced_styling_field_upper_label_color_description": "Colore os pequenos rótulos acima dos campos de entrada e os rótulos de escala.",
|
||||
"advanced_styling_field_upper_label_size": "Tamanho da fonte do rótulo",
|
||||
"advanced_styling_field_upper_label_size_description": "Ajusta o tamanho dos pequenos rótulos acima dos campos de entrada e dos rótulos de escala.",
|
||||
"advanced_styling_field_upper_label_weight": "Peso da fonte do rótulo",
|
||||
"advanced_styling_field_upper_label_weight_description": "Torna os rótulos mais leves ou mais negritos.",
|
||||
"advanced_styling_section_buttons": "Botões",
|
||||
"advanced_styling_section_headlines": "Títulos e descrições",
|
||||
"advanced_styling_section_inputs": "Campos de entrada",
|
||||
|
||||
@@ -1360,7 +1360,7 @@
|
||||
"audience": "Público",
|
||||
"auto_close_on_inactivity": "Fechar automaticamente por inatividade",
|
||||
"auto_progress_rating_and_nps": "Avançar automaticamente em perguntas de classificação e NPS",
|
||||
"auto_progress_rating_and_nps_description": "Avança automaticamente em blocos de pergunta única. Perguntas obrigatórias ocultam o botão Seguinte, exceto quando \"Outro\" está selecionado.",
|
||||
"auto_progress_rating_and_nps_description": "Avança automaticamente quando os inquiridos selecionam uma resposta em perguntas de classificação ou NPS. Isto aplica-se apenas a blocos com uma única pergunta. Perguntas obrigatórias ocultam o botão Seguinte; perguntas opcionais continuam a mostrá-lo para permitir saltar.",
|
||||
"auto_save_disabled": "Guardar automático desativado",
|
||||
"auto_save_disabled_tooltip": "O seu inquérito só é guardado automaticamente quando está em rascunho. Isto garante que os inquéritos públicos não sejam atualizados involuntariamente.",
|
||||
"auto_save_on": "Guardar automático ativado",
|
||||
@@ -2298,12 +2298,12 @@
|
||||
"advanced_styling_field_track_bg_description": "Colore a porção não preenchida da barra.",
|
||||
"advanced_styling_field_track_height": "Altura da faixa",
|
||||
"advanced_styling_field_track_height_description": "Controla a espessura da barra de progresso.",
|
||||
"advanced_styling_field_upper_label_color": "Cor da etiqueta do título",
|
||||
"advanced_styling_field_upper_label_color_description": "Colore a pequena etiqueta acima dos campos de entrada.",
|
||||
"advanced_styling_field_upper_label_size": "Tamanho da fonte da etiqueta do título",
|
||||
"advanced_styling_field_upper_label_size_description": "Ajusta o tamanho da pequena etiqueta acima dos campos de entrada.",
|
||||
"advanced_styling_field_upper_label_weight": "Peso da fonte da etiqueta do título",
|
||||
"advanced_styling_field_upper_label_weight_description": "Torna a etiqueta mais leve ou mais negrito.",
|
||||
"advanced_styling_field_upper_label_color": "Cor da etiqueta",
|
||||
"advanced_styling_field_upper_label_color_description": "Colore as pequenas etiquetas acima dos campos de entrada e as etiquetas de escala.",
|
||||
"advanced_styling_field_upper_label_size": "Tamanho da fonte da etiqueta",
|
||||
"advanced_styling_field_upper_label_size_description": "Ajusta o tamanho das pequenas etiquetas acima dos campos de entrada e das etiquetas de escala.",
|
||||
"advanced_styling_field_upper_label_weight": "Peso da fonte da etiqueta",
|
||||
"advanced_styling_field_upper_label_weight_description": "Torna as etiquetas mais leves ou mais negritas.",
|
||||
"advanced_styling_section_buttons": "Botões",
|
||||
"advanced_styling_section_headlines": "Títulos e descrições",
|
||||
"advanced_styling_section_inputs": "Campos de entrada",
|
||||
|
||||
@@ -1360,7 +1360,7 @@
|
||||
"audience": "Public",
|
||||
"auto_close_on_inactivity": "Închidere automată la inactivitate",
|
||||
"auto_progress_rating_and_nps": "Avansare automată pentru întrebări de rating și NPS",
|
||||
"auto_progress_rating_and_nps_description": "Avansare automată în blocurile cu o singură întrebare. Întrebările obligatorii ascund butonul Următorul, cu excepția cazului în care este selectată opțiunea „Altele“.",
|
||||
"auto_progress_rating_and_nps_description": "Avansează automat când respondenții selectează un răspuns la întrebările de rating sau NPS. Aceasta se aplică doar blocurilor cu o singură întrebare. Întrebările obligatorii ascund butonul Următorul; întrebările opționale îl afișează în continuare pentru a permite omiterea.",
|
||||
"auto_save_disabled": "Salvare automată dezactivată",
|
||||
"auto_save_disabled_tooltip": "Chestionarul dvs. este salvat automat doar când este în ciornă. Acest lucru asigură că sondajele publice nu sunt actualizate neintenționat.",
|
||||
"auto_save_on": "Salvare automată activată",
|
||||
@@ -2298,12 +2298,12 @@
|
||||
"advanced_styling_field_track_bg_description": "Colorează partea necompletată a barei.",
|
||||
"advanced_styling_field_track_height": "Înălțime track",
|
||||
"advanced_styling_field_track_height_description": "Controlează grosimea barei de progres.",
|
||||
"advanced_styling_field_upper_label_color": "Culoare etichetă titlu",
|
||||
"advanced_styling_field_upper_label_color_description": "Colorează eticheta mică de deasupra câmpurilor.",
|
||||
"advanced_styling_field_upper_label_size": "Mărime font etichetă titlu",
|
||||
"advanced_styling_field_upper_label_size_description": "Redimensionează eticheta mică de deasupra câmpurilor.",
|
||||
"advanced_styling_field_upper_label_weight": "Grosime font etichetă titlu",
|
||||
"advanced_styling_field_upper_label_weight_description": "Face eticheta mai subțire sau mai îngroșată.",
|
||||
"advanced_styling_field_upper_label_color": "Culoare etichetă",
|
||||
"advanced_styling_field_upper_label_color_description": "Colorează etichetele mici de deasupra câmpurilor și etichetele de scală.",
|
||||
"advanced_styling_field_upper_label_size": "Mărime font etichetă",
|
||||
"advanced_styling_field_upper_label_size_description": "Redimensionează etichetele mici de deasupra câmpurilor și etichetele de scală.",
|
||||
"advanced_styling_field_upper_label_weight": "Grosime font etichetă",
|
||||
"advanced_styling_field_upper_label_weight_description": "Face etichetele mai subțiri sau mai îngroșate.",
|
||||
"advanced_styling_section_buttons": "Butoane",
|
||||
"advanced_styling_section_headlines": "Titluri și descrieri",
|
||||
"advanced_styling_section_inputs": "Inputuri",
|
||||
|
||||
@@ -1360,7 +1360,7 @@
|
||||
"audience": "Аудитория",
|
||||
"auto_close_on_inactivity": "Автоматически закрывать при бездействии",
|
||||
"auto_progress_rating_and_nps": "Автоматический переход для вопросов с оценкой и NPS",
|
||||
"auto_progress_rating_and_nps_description": "Автоматический переход в блоках с одним вопросом. Обязательные вопросы скрывают кнопку «Далее», за исключением случаев, когда выбран вариант «Другое».",
|
||||
"auto_progress_rating_and_nps_description": "Автоматически переходить к следующему шагу, когда респонденты выбирают ответ в вопросах с оценкой или NPS. Это применяется только к блокам с одним вопросом. В обязательных вопросах кнопка «Далее» скрыта; в необязательных вопросах она остается видимой для пропуска.",
|
||||
"auto_save_disabled": "Автосохранение отключено",
|
||||
"auto_save_disabled_tooltip": "Ваш опрос автоматически сохраняется только в режиме черновика. Это гарантирует, что публичные опросы не будут случайно обновлены.",
|
||||
"auto_save_on": "Автосохранение включено",
|
||||
@@ -2298,12 +2298,12 @@
|
||||
"advanced_styling_field_track_bg_description": "Задаёт цвет незаполненной части полосы.",
|
||||
"advanced_styling_field_track_height": "Высота трека",
|
||||
"advanced_styling_field_track_height_description": "Управляет толщиной индикатора прогресса.",
|
||||
"advanced_styling_field_upper_label_color": "Цвет метки заголовка",
|
||||
"advanced_styling_field_upper_label_color_description": "Задаёт цвет маленькой метки над полями ввода.",
|
||||
"advanced_styling_field_upper_label_size": "Размер шрифта метки заголовка",
|
||||
"advanced_styling_field_upper_label_size_description": "Изменяет размер маленькой метки над полями ввода.",
|
||||
"advanced_styling_field_upper_label_weight": "Толщина шрифта метки заголовка",
|
||||
"advanced_styling_field_upper_label_weight_description": "Делает метку тоньше или жирнее.",
|
||||
"advanced_styling_field_upper_label_color": "Цвет метки",
|
||||
"advanced_styling_field_upper_label_color_description": "Задаёт цвет маленьких меток над полями ввода и меток шкалы.",
|
||||
"advanced_styling_field_upper_label_size": "Размер шрифта метки",
|
||||
"advanced_styling_field_upper_label_size_description": "Изменяет размер маленьких меток над полями ввода и меток шкалы.",
|
||||
"advanced_styling_field_upper_label_weight": "Толщина шрифта метки",
|
||||
"advanced_styling_field_upper_label_weight_description": "Делает метки тоньше или жирнее.",
|
||||
"advanced_styling_section_buttons": "Кнопки",
|
||||
"advanced_styling_section_headlines": "Заголовки и описания",
|
||||
"advanced_styling_section_inputs": "Поля ввода",
|
||||
|
||||
@@ -1360,7 +1360,7 @@
|
||||
"audience": "Målgrupp",
|
||||
"auto_close_on_inactivity": "Stäng automatiskt vid inaktivitet",
|
||||
"auto_progress_rating_and_nps": "Gå vidare automatiskt vid betygs- och NPS-frågor",
|
||||
"auto_progress_rating_and_nps_description": "Gå automatiskt vidare i block med en enda fråga. Obligatoriska frågor döljer Nästa, utom när \"Annat\" är valt.",
|
||||
"auto_progress_rating_and_nps_description": "Gå automatiskt vidare när respondenter väljer ett svar på betygs- eller NPS-frågor. Detta gäller endast block med en enda fråga. Obligatoriska frågor döljer Nästa-knappen; valfria frågor visar den fortfarande för att kunna hoppas över.",
|
||||
"auto_save_disabled": "Automatisk sparning inaktiverad",
|
||||
"auto_save_disabled_tooltip": "Din enkät sparas endast automatiskt när den är ett utkast. Detta säkerställer att publika enkäter inte uppdateras oavsiktligt.",
|
||||
"auto_save_on": "Automatisk sparning på",
|
||||
@@ -2298,12 +2298,12 @@
|
||||
"advanced_styling_field_track_bg_description": "Färgar den ofyllda delen av stapeln.",
|
||||
"advanced_styling_field_track_height": "Spårets höjd",
|
||||
"advanced_styling_field_track_height_description": "Styr tjockleken på förloppsstapeln.",
|
||||
"advanced_styling_field_upper_label_color": "Rubriketikettens färg",
|
||||
"advanced_styling_field_upper_label_color_description": "Färgar den lilla etiketten ovanför fälten.",
|
||||
"advanced_styling_field_upper_label_size": "Rubriketikettens teckenstorlek",
|
||||
"advanced_styling_field_upper_label_size_description": "Skalar storleken på den lilla etiketten ovanför fälten.",
|
||||
"advanced_styling_field_upper_label_weight": "Rubriketikettens teckentjocklek",
|
||||
"advanced_styling_field_upper_label_weight_description": "Gör etiketten tunnare eller fetare.",
|
||||
"advanced_styling_field_upper_label_color": "Etikettfärg",
|
||||
"advanced_styling_field_upper_label_color_description": "Färgar de små etiketterna ovanför fälten och skaletiketter.",
|
||||
"advanced_styling_field_upper_label_size": "Etikettens teckenstorlek",
|
||||
"advanced_styling_field_upper_label_size_description": "Skalar storleken på de små etiketterna ovanför fälten och skaletiketter.",
|
||||
"advanced_styling_field_upper_label_weight": "Etikettens teckentjocklek",
|
||||
"advanced_styling_field_upper_label_weight_description": "Gör etiketterna tunnare eller fetare.",
|
||||
"advanced_styling_section_buttons": "Knappar",
|
||||
"advanced_styling_section_headlines": "Rubriker & beskrivningar",
|
||||
"advanced_styling_section_inputs": "Inmatningar",
|
||||
|
||||
@@ -1360,7 +1360,7 @@
|
||||
"audience": "受众",
|
||||
"auto_close_on_inactivity": "自动关闭 在 无活动时",
|
||||
"auto_progress_rating_and_nps": "自动推进评分和 NPS 问题",
|
||||
"auto_progress_rating_and_nps_description": "在单问题块中自动前进。必填问题会隐藏\"下一步\"按钮,除非选择了\"其他\"选项。",
|
||||
"auto_progress_rating_and_nps_description": "当受访者在评分或 NPS 问题上选择答案时自动前进。这仅适用于单问题区块。必填问题会隐藏\"下一步\"按钮;可选问题仍会显示该按钮以便跳过。",
|
||||
"auto_save_disabled": "自动保存已禁用",
|
||||
"auto_save_disabled_tooltip": "您的调查仅在草稿状态时自动保存。这确保公开的调查不会被意外更新。",
|
||||
"auto_save_on": "自动保存已启用",
|
||||
@@ -2298,11 +2298,11 @@
|
||||
"advanced_styling_field_track_bg_description": "设置进度条未填充部分的颜色。",
|
||||
"advanced_styling_field_track_height": "轨道高度",
|
||||
"advanced_styling_field_track_height_description": "控制进度条的粗细。",
|
||||
"advanced_styling_field_upper_label_color": "标题标签颜色",
|
||||
"advanced_styling_field_upper_label_color_description": "设置输入框上方小标签的颜色。",
|
||||
"advanced_styling_field_upper_label_size": "标题标签字体大小",
|
||||
"advanced_styling_field_upper_label_size_description": "调整输入框上方小标签的大小。",
|
||||
"advanced_styling_field_upper_label_weight": "标题标签字体粗细",
|
||||
"advanced_styling_field_upper_label_color": "标签颜色",
|
||||
"advanced_styling_field_upper_label_color_description": "设置输入框上方小标签和刻度标签的颜色。",
|
||||
"advanced_styling_field_upper_label_size": "标签字体大小",
|
||||
"advanced_styling_field_upper_label_size_description": "调整输入框上方小标签和刻度标签的大小。",
|
||||
"advanced_styling_field_upper_label_weight": "标签字体粗细",
|
||||
"advanced_styling_field_upper_label_weight_description": "设置标签文字的粗细。",
|
||||
"advanced_styling_section_buttons": "按钮",
|
||||
"advanced_styling_section_headlines": "标题和描述",
|
||||
|
||||
@@ -1360,7 +1360,7 @@
|
||||
"audience": "受眾",
|
||||
"auto_close_on_inactivity": "非活動時自動關閉",
|
||||
"auto_progress_rating_and_nps": "自動前進評分與 NPS 問題",
|
||||
"auto_progress_rating_and_nps_description": "在單一問題區塊中自動前進。必填問題會隱藏「下一步」按鈕,除非選擇了「其他」選項。",
|
||||
"auto_progress_rating_and_nps_description": "當受訪者在評分或 NPS 問題中選擇答案時自動前進。此設定僅適用於單一問題區塊。必填問題會隱藏「下一步」按鈕;選填問題仍會顯示該按鈕以便跳過。",
|
||||
"auto_save_disabled": "自動儲存已停用",
|
||||
"auto_save_disabled_tooltip": "您的問卷僅在草稿狀態時自動儲存。這確保公開的問卷不會被意外更新。",
|
||||
"auto_save_on": "自動儲存已啟用",
|
||||
@@ -2298,11 +2298,11 @@
|
||||
"advanced_styling_field_track_bg_description": "設定進度條未填滿部分的顏色。",
|
||||
"advanced_styling_field_track_height": "軌道高度",
|
||||
"advanced_styling_field_track_height_description": "調整進度條的厚度。",
|
||||
"advanced_styling_field_upper_label_color": "標題標籤顏色",
|
||||
"advanced_styling_field_upper_label_color_description": "設定輸入框上方小標籤的顏色。",
|
||||
"advanced_styling_field_upper_label_size": "標題標籤字體大小",
|
||||
"advanced_styling_field_upper_label_size_description": "調整輸入框上方小標籤的大小。",
|
||||
"advanced_styling_field_upper_label_weight": "標題標籤字體粗細",
|
||||
"advanced_styling_field_upper_label_color": "標籤顏色",
|
||||
"advanced_styling_field_upper_label_color_description": "設定輸入框上方小標籤和刻度標籤的顏色。",
|
||||
"advanced_styling_field_upper_label_size": "標籤字體大小",
|
||||
"advanced_styling_field_upper_label_size_description": "調整輸入框上方小標籤和刻度標籤的大小。",
|
||||
"advanced_styling_field_upper_label_weight": "標籤字體粗細",
|
||||
"advanced_styling_field_upper_label_weight_description": "讓標籤字體變細或變粗。",
|
||||
"advanced_styling_section_buttons": "按鈕",
|
||||
"advanced_styling_section_headlines": "標題與說明",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Skeleton } from "@/modules/ui/components/skeleton";
|
||||
|
||||
type SkeletonLoaderProps = {
|
||||
type: "response" | "summary";
|
||||
type: "response" | "responseTable" | "summary";
|
||||
};
|
||||
|
||||
export const SkeletonLoader = ({ type }: SkeletonLoaderProps) => {
|
||||
@@ -25,6 +25,43 @@ export const SkeletonLoader = ({ type }: SkeletonLoaderProps) => {
|
||||
);
|
||||
}
|
||||
|
||||
if (type === "responseTable") {
|
||||
const renderTableCells = () => (
|
||||
<>
|
||||
<Skeleton className="h-4 w-4 rounded-xl bg-slate-400" />
|
||||
<Skeleton className="h-4 w-24 rounded-xl bg-slate-200" />
|
||||
<Skeleton className="h-4 w-32 rounded-xl bg-slate-200" />
|
||||
<Skeleton className="h-4 w-40 rounded-xl bg-slate-200" />
|
||||
<Skeleton className="h-4 w-40 rounded-xl bg-slate-200" />
|
||||
<Skeleton className="h-4 w-32 rounded-xl bg-slate-200" />
|
||||
</>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="animate-pulse space-y-4" data-testid="skeleton-loader-response-table">
|
||||
<div className="flex items-center justify-between">
|
||||
<Skeleton className="h-8 w-48 rounded-md bg-slate-300" />
|
||||
<div className="flex gap-2">
|
||||
<Skeleton className="h-8 w-8 rounded-md bg-slate-300" />
|
||||
<Skeleton className="h-8 w-8 rounded-md bg-slate-300" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="overflow-hidden rounded-xl border border-slate-200">
|
||||
<div className="flex h-12 items-center gap-4 border-b border-slate-200 bg-slate-100 px-4">
|
||||
{renderTableCells()}
|
||||
</div>
|
||||
{Array.from({ length: 10 }, (_, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className="flex h-12 items-center gap-4 border-b border-slate-100 px-4 last:border-b-0">
|
||||
{renderTableCells()}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (type === "response") {
|
||||
return (
|
||||
<div className="group space-y-4 rounded-lg bg-white p-6" data-testid="skeleton-loader-response">
|
||||
|
||||
@@ -60,9 +60,9 @@ test.describe("Survey Styling", async () => {
|
||||
await setDimension(page, "Headline Font Size", "24");
|
||||
await setDimension(page, "Description Font Size", "18");
|
||||
await setDimension(page, "Headline Font Weight", "700");
|
||||
await setColor(page, "Headline Label Color", "0000aa"); // Blue-ish
|
||||
await setDimension(page, "Headline Label Font Size", "14");
|
||||
await setDimension(page, "Headline Label Font Weight", "600");
|
||||
await setColor(page, "Label Color", "0000aa"); // Blue-ish
|
||||
await setDimension(page, "Label Font Size", "14");
|
||||
await setDimension(page, "Label Font Weight", "600");
|
||||
|
||||
// Verify Typography Variables
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
@@ -182,12 +182,12 @@ function NPS({
|
||||
{(lowerLabel ?? upperLabel) ? (
|
||||
<div className="mt-2 flex justify-between gap-8 px-1.5">
|
||||
{lowerLabel ? (
|
||||
<Label variant="default" className="max-w-[50%] text-xs leading-6" dir={dir}>
|
||||
<Label variant="card" className="max-w-[50%] leading-6" dir={dir}>
|
||||
{lowerLabel}
|
||||
</Label>
|
||||
) : null}
|
||||
{upperLabel ? (
|
||||
<Label variant="default" className="max-w-[50%] text-right text-xs leading-6" dir={dir}>
|
||||
<Label variant="card" className="max-w-[50%] text-right leading-6" dir={dir}>
|
||||
{upperLabel}
|
||||
</Label>
|
||||
) : null}
|
||||
|
||||
@@ -426,12 +426,12 @@ function Rating({
|
||||
{(lowerLabel ?? upperLabel) ? (
|
||||
<div className="mt-4 flex justify-between gap-8 px-1.5">
|
||||
{lowerLabel ? (
|
||||
<Label variant="default" className="max-w-[50%] text-xs leading-6" dir={dir}>
|
||||
<Label variant="card" className="max-w-[50%] leading-6" dir={dir}>
|
||||
{lowerLabel}
|
||||
</Label>
|
||||
) : null}
|
||||
{upperLabel ? (
|
||||
<Label variant="default" className="max-w-[50%] text-right text-xs leading-6" dir={dir}>
|
||||
<Label variant="card" className="max-w-[50%] text-right leading-6" dir={dir}>
|
||||
{upperLabel}
|
||||
</Label>
|
||||
) : null}
|
||||
|
||||
@@ -78,58 +78,6 @@ interface SingleSelectProps {
|
||||
searchNoResultsText?: string;
|
||||
}
|
||||
|
||||
const useDropdownCommitState = ({
|
||||
variant,
|
||||
selectedValue,
|
||||
onChange,
|
||||
handleDropdownOpen,
|
||||
handleDropdownClose,
|
||||
}: {
|
||||
variant: "list" | "dropdown";
|
||||
selectedValue: string | undefined;
|
||||
onChange: (value: string) => void;
|
||||
handleDropdownOpen: () => void;
|
||||
handleDropdownClose: () => void;
|
||||
}) => {
|
||||
const [isDropdownOpen, setIsDropdownOpen] = React.useState(false);
|
||||
const [pendingDropdownValue, setPendingDropdownValue] = React.useState<string | undefined>(selectedValue);
|
||||
const [hasPendingDropdownChange, setHasPendingDropdownChange] = React.useState(false);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!isDropdownOpen) {
|
||||
setPendingDropdownValue(selectedValue);
|
||||
setHasPendingDropdownChange(false);
|
||||
}
|
||||
}, [selectedValue, isDropdownOpen]);
|
||||
|
||||
const handleDropdownOpenChange = (open: boolean) => {
|
||||
setIsDropdownOpen(open);
|
||||
if (open) {
|
||||
setPendingDropdownValue(selectedValue);
|
||||
setHasPendingDropdownChange(false);
|
||||
handleDropdownOpen();
|
||||
return;
|
||||
}
|
||||
|
||||
handleDropdownClose();
|
||||
if (hasPendingDropdownChange && pendingDropdownValue && pendingDropdownValue !== selectedValue) {
|
||||
onChange(pendingDropdownValue);
|
||||
}
|
||||
setHasPendingDropdownChange(false);
|
||||
};
|
||||
|
||||
const effectiveSelectedValue =
|
||||
variant === "dropdown" && isDropdownOpen ? pendingDropdownValue : selectedValue;
|
||||
|
||||
return {
|
||||
effectiveSelectedValue,
|
||||
handleDropdownOpenChange,
|
||||
setPendingDropdownValue,
|
||||
setHasPendingDropdownChange,
|
||||
};
|
||||
};
|
||||
|
||||
// NOSONAR - This component intentionally keeps list/dropdown rendering in one place for consistent a11y behavior.
|
||||
function SingleSelect({
|
||||
elementId,
|
||||
headline,
|
||||
@@ -180,19 +128,6 @@ function SingleSelect({
|
||||
handleDropdownClose,
|
||||
} = useDropdownSearch({ options, hasOtherOption, otherOptionLabel, isSearchEnabled: showSearch });
|
||||
|
||||
const {
|
||||
effectiveSelectedValue,
|
||||
handleDropdownOpenChange,
|
||||
setPendingDropdownValue,
|
||||
setHasPendingDropdownChange,
|
||||
} = useDropdownCommitState({
|
||||
variant,
|
||||
selectedValue,
|
||||
onChange,
|
||||
handleDropdownOpen,
|
||||
handleDropdownClose,
|
||||
});
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!isOtherSelected || disabled) return;
|
||||
|
||||
@@ -227,7 +162,7 @@ function SingleSelect({
|
||||
const optionLabelClassName = "font-option text-option font-option-weight text-option-label";
|
||||
|
||||
// Get selected option label for dropdown display
|
||||
const selectedOption = options.find((opt) => opt.id === effectiveSelectedValue);
|
||||
const selectedOption = options.find((opt) => opt.id === selectedValue);
|
||||
const displayText = isOtherSelected
|
||||
? otherValue || otherOptionLabel
|
||||
: (selectedOption?.label ?? placeholder);
|
||||
@@ -250,7 +185,11 @@ function SingleSelect({
|
||||
{variant === "dropdown" ? (
|
||||
<>
|
||||
<ElementError errorMessage={errorMessage} dir={dir} />
|
||||
<DropdownMenu onOpenChange={handleDropdownOpenChange}>
|
||||
<DropdownMenu
|
||||
onOpenChange={(open) => {
|
||||
if (open) handleDropdownOpen();
|
||||
else handleDropdownClose();
|
||||
}}>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button
|
||||
variant="outline"
|
||||
@@ -278,12 +217,7 @@ function SingleSelect({
|
||||
/>
|
||||
) : null}
|
||||
<div className="max-h-[260px] overflow-y-auto">
|
||||
<DropdownMenuRadioGroup
|
||||
value={effectiveSelectedValue}
|
||||
onValueChange={(newValue) => {
|
||||
setPendingDropdownValue(newValue);
|
||||
setHasPendingDropdownChange(newValue !== selectedValue);
|
||||
}}>
|
||||
<DropdownMenuRadioGroup value={selectedValue} onValueChange={onChange}>
|
||||
{filteredRegularOptions.map((option) => {
|
||||
const optionId = `${inputId}-${option.id}`;
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ function ElementHeader({
|
||||
|
||||
{/* Headline */}
|
||||
<div>
|
||||
<div>{required ? <span className="label-upper mb-[3px]">{requiredLabel}</span> : null}</div>
|
||||
<div>{required ? <span className="label-card mb-[3px]">{requiredLabel}</span> : null}</div>
|
||||
<div className="flex">
|
||||
{isHeadlineHtml && safeHeadlineHtml ? (
|
||||
<Label htmlFor={htmlFor} variant="headline">
|
||||
|
||||
@@ -4,7 +4,7 @@ import { cn, stripInlineStyles } from "@/lib/utils";
|
||||
|
||||
interface LabelProps extends React.ComponentProps<"label"> {
|
||||
/** Label variant for different styling contexts */
|
||||
variant?: "default" | "headline" | "description";
|
||||
variant?: "default" | "headline" | "description" | "card";
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -51,6 +51,8 @@ function Label({
|
||||
variantClass = "label-headline";
|
||||
} else if (variant === "description") {
|
||||
variantClass = "label-description";
|
||||
} else if (variant === "card") {
|
||||
variantClass = "label-card";
|
||||
}
|
||||
|
||||
// Base classes - use flex-col for HTML content to allow line breaks, flex items-center for non-HTML
|
||||
|
||||
@@ -197,8 +197,8 @@
|
||||
opacity: var(--fb-label-opacity);
|
||||
}
|
||||
|
||||
#fbjs .label-upper,
|
||||
#fbjs .label-upper * {
|
||||
#fbjs .label-card,
|
||||
#fbjs .label-card * {
|
||||
font-family: var(--fb-element-upper-label-font-family);
|
||||
font-weight: var(--fb-element-upper-label-font-weight);
|
||||
font-size: var(--fb-element-upper-label-font-size);
|
||||
|
||||
@@ -20,8 +20,6 @@ import { getLocalizedValue } from "@/lib/i18n";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { getFirstErrorMessage, validateBlockResponses } from "@/lib/validation/evaluator";
|
||||
|
||||
const AUTO_PROGRESS_SUBMIT_DELAY_MS = 350;
|
||||
|
||||
interface BlockConditionalProps {
|
||||
block: TSurveyBlock;
|
||||
value: TResponseData;
|
||||
@@ -84,8 +82,7 @@ export function BlockConditional({
|
||||
const autoProgressElement = getAutoProgressElement(block.elements, isAutoProgressingEnabled);
|
||||
const shouldHideSubmitButton = shouldHideSubmitButtonForAutoProgress(
|
||||
block.elements,
|
||||
isAutoProgressingEnabled,
|
||||
value
|
||||
isAutoProgressingEnabled
|
||||
);
|
||||
|
||||
// Handle change for an individual element
|
||||
@@ -131,7 +128,7 @@ export function BlockConditional({
|
||||
} finally {
|
||||
autoProgressingInFlightRef.current = false;
|
||||
}
|
||||
}, AUTO_PROGRESS_SUBMIT_DELAY_MS);
|
||||
}, 0);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ export function Headline({
|
||||
<label htmlFor={elementId} className="text-heading mb-[3px] flex flex-col">
|
||||
{hasRequiredRule && isQuestionCard && (
|
||||
<span
|
||||
className="label-upper mb-[3px] text-xs leading-6 font-normal opacity-60"
|
||||
className="label-card mb-[3px] text-xs leading-6 font-normal opacity-60"
|
||||
tabIndex={-1}
|
||||
data-testid="fb__surveys__headline-optional-text-test">
|
||||
{t("common.required")}
|
||||
|
||||
@@ -2,7 +2,6 @@ import { describe, expect, test } from "vitest";
|
||||
import { type TSurveyElement, TSurveyElementTypeEnum } from "@formbricks/types/surveys/elements";
|
||||
import {
|
||||
getAutoProgressElement,
|
||||
isSingleSelectOtherSelected,
|
||||
shouldHideSubmitButtonForAutoProgress,
|
||||
shouldTriggerAutoProgress,
|
||||
} from "./auto-progress";
|
||||
@@ -14,62 +13,26 @@ const createElement = (id: string, type: TSurveyElementTypeEnum, required: boole
|
||||
required,
|
||||
}) as unknown as TSurveyElement;
|
||||
|
||||
const createSingleSelectElement = (required: boolean): TSurveyElement =>
|
||||
({
|
||||
id: "single_select_1",
|
||||
type: TSurveyElementTypeEnum.MultipleChoiceSingle,
|
||||
required,
|
||||
choices: [
|
||||
{ id: "choice_1", label: { default: "Choice 1", de: "Auswahl 1" } },
|
||||
{ id: "choice_2", label: { default: "Choice 2" } },
|
||||
{ id: "other", label: { default: "Other" } },
|
||||
],
|
||||
}) as unknown as TSurveyElement;
|
||||
|
||||
const createPictureSelectionElement = (required: boolean, allowMulti: boolean): TSurveyElement =>
|
||||
({
|
||||
id: "picture_1",
|
||||
type: TSurveyElementTypeEnum.PictureSelection,
|
||||
required,
|
||||
allowMulti,
|
||||
choices: [
|
||||
{ id: "pic_1", imageUrl: "https://example.com/1.png" },
|
||||
{ id: "pic_2", imageUrl: "https://example.com/2.png" },
|
||||
],
|
||||
}) as unknown as TSurveyElement;
|
||||
|
||||
describe("auto-progress helpers", () => {
|
||||
test("returns auto-progress element for all supported single-question types only", () => {
|
||||
test("returns auto-progress element for single rating/nps blocks only", () => {
|
||||
const ratingElement = createElement("rating_1", TSurveyElementTypeEnum.Rating, true);
|
||||
const npsElement = createElement("nps_1", TSurveyElementTypeEnum.NPS, false);
|
||||
const singleSelectElement = createSingleSelectElement(false);
|
||||
const singlePictureElement = createPictureSelectionElement(false, false);
|
||||
const multiPictureElement = createPictureSelectionElement(false, true);
|
||||
const openTextElement = createElement("text_1", TSurveyElementTypeEnum.OpenText, false);
|
||||
|
||||
expect(getAutoProgressElement([ratingElement], true)).toEqual(ratingElement);
|
||||
expect(getAutoProgressElement([npsElement], true)).toEqual(npsElement);
|
||||
expect(getAutoProgressElement([singleSelectElement], true)).toEqual(singleSelectElement);
|
||||
expect(getAutoProgressElement([singlePictureElement], true)).toEqual(singlePictureElement);
|
||||
expect(getAutoProgressElement([multiPictureElement], true)).toBeNull();
|
||||
expect(getAutoProgressElement([openTextElement], true)).toBeNull();
|
||||
expect(getAutoProgressElement([ratingElement], false)).toBeNull();
|
||||
expect(getAutoProgressElement([ratingElement, npsElement], true)).toBeNull();
|
||||
});
|
||||
|
||||
test("hides submit button only for required auto-progress elements with no required+other exception", () => {
|
||||
test("hides submit button only for required auto-progress elements", () => {
|
||||
const requiredRating = createElement("rating_required", TSurveyElementTypeEnum.Rating, true);
|
||||
const optionalRating = createElement("rating_optional", TSurveyElementTypeEnum.Rating, false);
|
||||
const requiredSingleSelect = createSingleSelectElement(true);
|
||||
|
||||
expect(shouldHideSubmitButtonForAutoProgress([requiredRating], true)).toBe(true);
|
||||
expect(shouldHideSubmitButtonForAutoProgress([optionalRating], true)).toBe(false);
|
||||
expect(shouldHideSubmitButtonForAutoProgress([requiredRating], false)).toBe(false);
|
||||
expect(
|
||||
shouldHideSubmitButtonForAutoProgress([requiredSingleSelect], true, {
|
||||
[requiredSingleSelect.id]: "",
|
||||
})
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
test("triggers auto-progress only when an eligible response was changed", () => {
|
||||
@@ -110,76 +73,5 @@ describe("auto-progress helpers", () => {
|
||||
isAlreadyInFlight: true,
|
||||
})
|
||||
).toBe(false);
|
||||
|
||||
expect(
|
||||
shouldTriggerAutoProgress({
|
||||
changedElementId: "rating_1",
|
||||
mergedValue: { rating_1: 5 },
|
||||
autoProgressElement,
|
||||
isAlreadyInFlight: false,
|
||||
isCommittedSelection: false,
|
||||
})
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
test("detects single-select other selection from sentinel and custom values", () => {
|
||||
const autoProgressElement = createSingleSelectElement(true);
|
||||
|
||||
expect(
|
||||
isSingleSelectOtherSelected({
|
||||
autoProgressElement,
|
||||
mergedValue: { [autoProgressElement.id]: "" },
|
||||
})
|
||||
).toBe(true);
|
||||
|
||||
expect(
|
||||
isSingleSelectOtherSelected({
|
||||
autoProgressElement,
|
||||
mergedValue: { [autoProgressElement.id]: "Custom answer" },
|
||||
})
|
||||
).toBe(true);
|
||||
|
||||
expect(
|
||||
isSingleSelectOtherSelected({
|
||||
autoProgressElement,
|
||||
mergedValue: { [autoProgressElement.id]: "Choice 1" },
|
||||
})
|
||||
).toBe(false);
|
||||
|
||||
expect(
|
||||
isSingleSelectOtherSelected({
|
||||
autoProgressElement,
|
||||
mergedValue: { [autoProgressElement.id]: "Auswahl 1" },
|
||||
})
|
||||
).toBe(false);
|
||||
|
||||
expect(
|
||||
isSingleSelectOtherSelected({
|
||||
autoProgressElement,
|
||||
mergedValue: { [autoProgressElement.id]: "choice_1" },
|
||||
})
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
test("does not auto-progress when single-select other is selected", () => {
|
||||
const autoProgressElement = createSingleSelectElement(true);
|
||||
|
||||
expect(
|
||||
shouldTriggerAutoProgress({
|
||||
changedElementId: autoProgressElement.id,
|
||||
mergedValue: { [autoProgressElement.id]: "" },
|
||||
autoProgressElement,
|
||||
isAlreadyInFlight: false,
|
||||
})
|
||||
).toBe(false);
|
||||
|
||||
expect(
|
||||
shouldTriggerAutoProgress({
|
||||
changedElementId: autoProgressElement.id,
|
||||
mergedValue: { [autoProgressElement.id]: "Custom answer" },
|
||||
autoProgressElement,
|
||||
isAlreadyInFlight: false,
|
||||
})
|
||||
).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,65 +1,8 @@
|
||||
import { type TResponseData } from "@formbricks/types/responses";
|
||||
import { type TSurveyElement, TSurveyElementTypeEnum } from "@formbricks/types/surveys/elements";
|
||||
|
||||
const isAutoProgressElement = (element: TSurveyElement): boolean => {
|
||||
if (element.type === TSurveyElementTypeEnum.Rating || element.type === TSurveyElementTypeEnum.NPS) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (element.type === TSurveyElementTypeEnum.MultipleChoiceSingle) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (element.type === TSurveyElementTypeEnum.PictureSelection) {
|
||||
return !element.allowMulti;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
const getAllChoiceLabels = (
|
||||
element: Extract<TSurveyElement, { type: TSurveyElementTypeEnum.MultipleChoiceSingle }>
|
||||
) =>
|
||||
element.choices.filter((choice) => choice.id !== "other").flatMap((choice) => Object.values(choice.label));
|
||||
|
||||
export const isSingleSelectOtherSelected = ({
|
||||
autoProgressElement,
|
||||
mergedValue,
|
||||
}: {
|
||||
autoProgressElement: TSurveyElement | null;
|
||||
mergedValue: TResponseData;
|
||||
}): boolean => {
|
||||
if (!autoProgressElement || autoProgressElement.type !== TSurveyElementTypeEnum.MultipleChoiceSingle) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const hasOtherOption = autoProgressElement.choices.some((choice) => choice.id === "other");
|
||||
if (!hasOtherOption) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const currentValue = mergedValue[autoProgressElement.id];
|
||||
if (currentValue === undefined) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (currentValue === "") {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (typeof currentValue !== "string") {
|
||||
return false;
|
||||
}
|
||||
|
||||
const regularChoiceIds = autoProgressElement.choices
|
||||
.filter((choice) => choice.id !== "other")
|
||||
.map((choice) => choice.id);
|
||||
if (regularChoiceIds.includes(currentValue)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !getAllChoiceLabels(autoProgressElement).includes(currentValue);
|
||||
};
|
||||
const isAutoProgressElementType = (type: TSurveyElementTypeEnum): boolean =>
|
||||
type === TSurveyElementTypeEnum.Rating || type === TSurveyElementTypeEnum.NPS;
|
||||
|
||||
export const getAutoProgressElement = (
|
||||
elements: TSurveyElement[],
|
||||
@@ -70,24 +13,15 @@ export const getAutoProgressElement = (
|
||||
}
|
||||
|
||||
const [element] = elements;
|
||||
return isAutoProgressElement(element) ? element : null;
|
||||
return isAutoProgressElementType(element.type) ? element : null;
|
||||
};
|
||||
|
||||
export const shouldHideSubmitButtonForAutoProgress = (
|
||||
elements: TSurveyElement[],
|
||||
isAutoProgressingEnabled: boolean,
|
||||
mergedValue: TResponseData = {}
|
||||
isAutoProgressingEnabled: boolean
|
||||
): boolean => {
|
||||
const autoProgressElement = getAutoProgressElement(elements, isAutoProgressingEnabled);
|
||||
if (!autoProgressElement?.required) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isSingleSelectOtherSelected({ autoProgressElement, mergedValue })) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return Boolean(autoProgressElement?.required);
|
||||
};
|
||||
|
||||
export const shouldTriggerAutoProgress = ({
|
||||
@@ -95,24 +29,13 @@ export const shouldTriggerAutoProgress = ({
|
||||
mergedValue,
|
||||
autoProgressElement,
|
||||
isAlreadyInFlight,
|
||||
isCommittedSelection = true,
|
||||
}: {
|
||||
changedElementId: string;
|
||||
mergedValue: TResponseData;
|
||||
autoProgressElement: TSurveyElement | null;
|
||||
isAlreadyInFlight: boolean;
|
||||
isCommittedSelection?: boolean;
|
||||
}): boolean => {
|
||||
if (
|
||||
!autoProgressElement ||
|
||||
isAlreadyInFlight ||
|
||||
changedElementId !== autoProgressElement.id ||
|
||||
!isCommittedSelection
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isSingleSelectOtherSelected({ autoProgressElement, mergedValue })) {
|
||||
if (!autoProgressElement || isAlreadyInFlight || changedElementId !== autoProgressElement.id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -348,7 +348,7 @@ export const addCustomThemeToDom = ({ styling }: { styling: TProjectStyling | TS
|
||||
upperDecls += " color: var(--fb-element-upper-label-color) !important;\n";
|
||||
upperDecls += " opacity: var(--fb-element-upper-label-opacity, 1) !important;\n";
|
||||
}
|
||||
addRule("#fbjs .label-upper,\n#fbjs .label-upper *", upperDecls);
|
||||
addRule("#fbjs .label-card,\n#fbjs .label-card *", upperDecls);
|
||||
|
||||
// --- Buttons ---
|
||||
let buttonDecls = "";
|
||||
|
||||
Reference in New Issue
Block a user