diff --git a/.gitignore b/.gitignore
index 304f809..6d8036d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -49,4 +49,6 @@ node_modules/
/playwright/.auth/
# eslint
-.eslintcache
\ No newline at end of file
+.eslintcache
+.pytest_cache/
+__pycache__/
diff --git a/package-lock.json b/package-lock.json
index 3944405..232a843 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "granda-front",
- "version": "0.3.16",
+ "version": "0.3.17",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "granda-front",
- "version": "0.3.16",
+ "version": "0.3.17",
"dependencies": {
"@radix-ui/react-dropdown-menu": "^2.1.6",
"@radix-ui/react-select": "^2.2.6",
diff --git a/package.json b/package.json
index 0fdcebf..c767d80 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "granda-front",
- "version": "0.3.16",
+ "version": "0.3.17",
"private": true,
"scripts": {
"dev": "next dev --turbopack",
diff --git a/scripts/i18ndiffer/.python-version b/scripts/i18ndiffer/.python-version
new file mode 100644
index 0000000..24ee5b1
--- /dev/null
+++ b/scripts/i18ndiffer/.python-version
@@ -0,0 +1 @@
+3.13
diff --git a/scripts/i18ndiffer/README.md b/scripts/i18ndiffer/README.md
new file mode 100644
index 0000000..c2f41e3
--- /dev/null
+++ b/scripts/i18ndiffer/README.md
@@ -0,0 +1,6 @@
+This utility can be used to add missing lines to i18n files while preserving their line-by-line structure.
+
+Usage:
+```bash
+diff -y [file1] [file2] | uv run src/main.py [file1] [file2]
+```
diff --git a/scripts/i18ndiffer/pyproject.toml b/scripts/i18ndiffer/pyproject.toml
new file mode 100644
index 0000000..40e4acf
--- /dev/null
+++ b/scripts/i18ndiffer/pyproject.toml
@@ -0,0 +1,9 @@
+[project]
+name = "i18ndiffer"
+version = "0.1.0"
+description = "Add your description here"
+readme = "README.md"
+requires-python = ">=3.13"
+dependencies = [
+ "pytest>=9.0.3",
+]
diff --git a/scripts/i18ndiffer/src/__init__.py b/scripts/i18ndiffer/src/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/scripts/i18ndiffer/src/main.py b/scripts/i18ndiffer/src/main.py
new file mode 100644
index 0000000..c169e2c
--- /dev/null
+++ b/scripts/i18ndiffer/src/main.py
@@ -0,0 +1,47 @@
+import re
+import sys
+
+
+def main():
+ path1, path2 = sys.argv[1], sys.argv[2]
+ diff_file: str = sys.stdin.read()
+ diff_lines = diff_file.split("\n")
+ lines1, lines2 = read_lines_from_files(path1, path2)
+ file1, file2 = insert_missing_lines(lines1, lines2, diff_lines)
+
+ with open(path1, "w") as f:
+ f.writelines(file1)
+ with open(path2, "w") as f:
+ f.writelines(file2)
+
+
+def insert_missing_lines(lines1: list[str], lines2: list[str], diff_lines: list[str]):
+ for i in range(len(diff_lines)):
+ if diff_lines[i].endswith("<"):
+ lines2.insert(i, prepare_placeholder_from(lines1[i]))
+ elif diff_lines[i].lstrip().startswith(">"):
+ lines1.insert(i, prepare_placeholder_from(lines2[i]))
+
+ return lines1, lines2
+
+
+def read_lines_from_files(path1, path2):
+ lines1 = []
+ lines2 = []
+
+ with open(path1, "r") as f1:
+ lines1 = f1.readlines()
+ f1.close()
+ with open(path2, "r") as f2:
+ lines2 = f2.readlines()
+ f2.close()
+ return lines1, lines2
+
+
+def prepare_placeholder_from(line: str) -> str:
+ capture_key_without_value_pattern = r'(\s*".+":\s*")(.+".*)'
+ return re.sub(capture_key_without_value_pattern, r"\1[CHANGE ME!] \2", line)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/i18ndiffer/test/__init__.py b/scripts/i18ndiffer/test/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/scripts/i18ndiffer/test/test_diffing.py b/scripts/i18ndiffer/test/test_diffing.py
new file mode 100644
index 0000000..85ef95e
--- /dev/null
+++ b/scripts/i18ndiffer/test/test_diffing.py
@@ -0,0 +1,98 @@
+import re
+
+from src.main import insert_missing_lines, prepare_placeholder_from
+
+
+def test_preparing_placeholders_basic():
+ assert (
+ prepare_placeholder_from(' "msg_handle_empty": "Handle must not be empty.",')
+ == ' "msg_handle_empty": "[CHANGE ME!] Handle must not be empty.",'
+ )
+
+
+def test_preparing_placeholders_with_curly_braces():
+ assert (
+ prepare_placeholder_from(' "error_message": "Details: {message}"')
+ == ' "error_message": "[CHANGE ME!] Details: {message}"'
+ )
+
+
+def test_instert_lines_right_to_left():
+ diff_file = [
+ ' "debate_details": { "debate_details": {',
+ ' "unconfigured_debate": "Debata bez tezy" | "unconfigured_debate": "Debate without a motion",',
+ ' > "proceed_to_debate": "Proceed to Debate!",',
+ ' > "marshal_panel": "Marshal Panel"',
+ " > },",
+ ' > "create_tournament": {',
+ ' > "title": "Create Tournament",',
+ ' > "full_name": "Full name",',
+ ]
+
+ file1 = [
+ ' "debate_details": {',
+ ' "unconfigured_debate": "Debata bez tezy"',
+ " }",
+ "}",
+ ]
+ file2 = [
+ ' "debate_details": {',
+ ' "unconfigured_debate": "Debate without a motion",',
+ ' "proceed_to_debate": "Proceed to Debate!",',
+ ' "marshal_panel": "Marshal Panel"',
+ " },",
+ ' "create_tournament": {',
+ ' "title": "Create Tournament",',
+ ' "full_name": "Full name",',
+ ' "short_name": "Short name",',
+ ' "close": "Close",',
+ ' "full_name_placeholder": "(Required)"',
+ " },",
+ ]
+
+ file1, file2 = insert_missing_lines(file1, file2, diff_file)
+
+ empty_value_pattern = r'(\s*".+":\s*"".*)'
+
+ value_to_change_pattern = r'(\s*".+":\s*"\[CHANGE ME!\].+".*)'
+ for line in file1:
+ if not re.findall(r"debate|{|}", line):
+ assert re.match(value_to_change_pattern, line)
+
+
+def test_insert_lines_left_to_right():
+ diff_file = [
+ ' "metadata": { "metadata": {',
+ ' "title": "granda: Debate Tournament Planner", | "title": "granda: Zaplanuj swój turniej debat",',
+ ' "description": "Computer aided debate tournament organizi | "description": "Komputerowo wspomagane planowanie turniej',
+ " }, <",
+ ' "generic": { <',
+ ' "error": "Error", <',
+ ' "error_loading_content": "An error occurred while loading <',
+ ' "error_message": "Details: {message}" <',
+ " }, },",
+ ]
+ file1 = [
+ ' "metadata": {',
+ ' "title": "granda: Debate Tournament Planner",',
+ ' "description": "Computer aided debate tournament organizing experience enrichment."',
+ " },",
+ ' "generic": {',
+ ' "error": "Error",',
+ ' "error_loading_content": "An error occurred while loading the content.",',
+ ' "error_message": "Details: {message}"',
+ " },",
+ ]
+ file2 = [
+ ' "metadata": {',
+ ' "title": "granda: Zaplanuj swój turniej debat",',
+ ' "description": "Komputerowo wspomagane planowanie turniejów debat."',
+ " },",
+ ]
+
+ file1, file2 = insert_missing_lines(file1, file2, diff_file)
+
+ value_to_change_pattern = r'(\s*".+":\s*"\[CHANGE ME!\].+".*)'
+ for line in file2:
+ if line.__contains__("error"):
+ assert re.match(value_to_change_pattern, line)
diff --git a/scripts/i18ndiffer/uv.lock b/scripts/i18ndiffer/uv.lock
new file mode 100644
index 0000000..cb6098e
--- /dev/null
+++ b/scripts/i18ndiffer/uv.lock
@@ -0,0 +1,75 @@
+version = 1
+revision = 3
+requires-python = ">=3.13"
+
+[[package]]
+name = "colorama"
+version = "0.4.6"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
+]
+
+[[package]]
+name = "i18ndiffer"
+version = "0.1.0"
+source = { virtual = "." }
+dependencies = [
+ { name = "pytest" },
+]
+
+[package.metadata]
+requires-dist = [{ name = "pytest", specifier = ">=9.0.3" }]
+
+[[package]]
+name = "iniconfig"
+version = "2.3.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" },
+]
+
+[[package]]
+name = "packaging"
+version = "26.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d7/f1/e7a6dd94a8d4a5626c03e4e99c87f241ba9e350cd9e6d75123f992427270/packaging-26.2.tar.gz", hash = "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661", size = 228134, upload-time = "2026-04-24T20:15:23.917Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/df/b2/87e62e8c3e2f4b32e5fe99e0b86d576da1312593b39f47d8ceef365e95ed/packaging-26.2-py3-none-any.whl", hash = "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e", size = 100195, upload-time = "2026-04-24T20:15:22.081Z" },
+]
+
+[[package]]
+name = "pluggy"
+version = "1.6.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" },
+]
+
+[[package]]
+name = "pygments"
+version = "2.20.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" },
+]
+
+[[package]]
+name = "pytest"
+version = "9.0.3"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "colorama", marker = "sys_platform == 'win32'" },
+ { name = "iniconfig" },
+ { name = "packaging" },
+ { name = "pluggy" },
+ { name = "pygments" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/7d/0d/549bd94f1a0a402dc8cf64563a117c0f3765662e2e668477624baeec44d5/pytest-9.0.3.tar.gz", hash = "sha256:b86ada508af81d19edeb213c681b1d48246c1a91d304c6c81a427674c17eb91c", size = 1572165, upload-time = "2026-04-07T17:16:18.027Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-py3-none-any.whl", hash = "sha256:2c5efc453d45394fdd706ade797c0a81091eccd1d6e4bccfcd476e2b8e0ab5d9", size = 375249, upload-time = "2026-04-07T17:16:16.13Z" },
+]
diff --git a/src/app/[locale]/t/[path]/debates/[debate_id]/page.tsx b/src/app/[locale]/t/[path]/debates/[debate_id]/page.tsx
index 419b4a8..c85e2c3 100644
--- a/src/app/[locale]/t/[path]/debates/[debate_id]/page.tsx
+++ b/src/app/[locale]/t/[path]/debates/[debate_id]/page.tsx
@@ -118,41 +118,29 @@ export default async function DebateDetailsPage({
- {" "}
- {motion}{" "}
+ {motion}
ret
-
-
- {" "}
- {/*{phaseName} | {roundName}{" "}*/}
-
-
+
-
-
- {" "}
- Information about assigned Marshal will be presented here.{" "}
-
+
+ {t("time_and_place_info.placeholder_text")}
+
+
+
+ {t("teams_info.placeholder_text")}
-
-
- {" "}
- Information about assigned Judges will be presented here.{" "}
-
+
+ {t("marshal_info.placeholder_text")}
-
-
- {" "}
- Information about time and place of the debate will be presented
- here.{" "}
-
+
+ {t("judges_info.placeholder_text")}
diff --git a/src/components/tournament/MarshalPanel.tsx b/src/components/tournament/MarshalPanel.tsx
index e80c2f0..41e5674 100644
--- a/src/components/tournament/MarshalPanel.tsx
+++ b/src/components/tournament/MarshalPanel.tsx
@@ -15,7 +15,6 @@ export function MarshalPanel({ motion }: MarshalPanelProps) {
return (
= ({
tournamentId,
debateId,
}) => {
- const [isJudge, setIsJudge] = useState(null);
+ const [canSubmitVerdict, setCanSubmitVerdict] = useState(
+ null,
+ );
const [verdicts, setVerdicts] = useState([]);
const [selectedVote, setSelectedVote] = useState(null);
const [submitting, setSubmitting] = useState(false);
@@ -50,9 +52,9 @@ const VerdictPanel: React.FC = ({
return null;
}
- if (counts.proposition > counts.opposition) return "Proposition";
- if (counts.opposition > counts.proposition) return "Opposition";
- return "Tie";
+ if (counts.proposition > counts.opposition) return "proposition";
+ if (counts.opposition > counts.proposition) return "opposition";
+ return "no_verdict";
}, [verdicts]);
useEffect(() => {
@@ -74,7 +76,7 @@ const VerdictPanel: React.FC = ({
}),
])
.then(([permissionData, verdictsData]) => {
- setIsJudge(Boolean(permissionData));
+ setCanSubmitVerdict(Boolean(permissionData));
const loadedVerdicts: VerdictRecord[] = Array.isArray(verdictsData)
? verdictsData
: [];
@@ -184,9 +186,37 @@ const VerdictPanel: React.FC = ({
);
}
+ const VerdictInformation = () => {
+ return (
+
+
+ <>
+
+ {t.rich(`majority.${majorityVerdict ?? "no_verdict"}`, {
+ highlight: (chunks) => (
+
+ {chunks}
+
+ ),
+ })}
+
+ >
+
+
+ );
+ };
+
return (
-
- {isJudge ? (
+
+ {canSubmitVerdict ? (
-
-
-
- {majorityVerdict === "Proposition" ? (
- <>
-
- {t("majority.proposition.prefix")}
-
-
-
- {t("majority.proposition.highlight")}
-
-
-
- {t("majority.proposition.suffix")}
-
- >
- ) : majorityVerdict === "Opposition" ? (
- <>
-
- {t("majority.opposition.prefix")}
-
-
-
- {t("majority.opposition.highlight")}
-
-
-
- {t("majority.opposition.suffix")}
-
- >
- ) : (
- <>
-
- {t("majority.no_verdict.prefix")}
-
-
-
- {t("majority.no_verdict.highlight")}
-
-
-
- {t("majority.no_verdict.suffix")}
-
- >
- )}
-
-
+
) : (
-
+
)}
);
diff --git a/src/i18n/translations/en.json b/src/i18n/translations/en.json
index ca00678..22a6f1c 100644
--- a/src/i18n/translations/en.json
+++ b/src/i18n/translations/en.json
@@ -96,8 +96,6 @@
"advancing_teams": "Advancing teams",
"submit": "Plan tournament",
"submitting": "Planning...",
- "placeholder_title": "Tournament ladder",
- "placeholder_description": "Tournament ladder placeholder.",
"no_phases_error": "Failed to load tournament phases.",
"validation_positive_integer": "This value must be a positive integer.",
"validation_power_of_two": "Advancing teams must be a power of 2.",
@@ -111,7 +109,7 @@
"total_teams_hint": "The total number of teams taking part in the tournament.",
"advancing_teams_hint": "Defines how many teams advance from the group phase to the finals phase. Must be a power of 2.",
"hint_title": "Tournament Ladder",
- "hint_content": "Each box represents a debate. You can click on a specific box to see the debate details. The ladder shows the structure and flow of the tournament, including the rounds and how debates are organised."
+ "hint_content": "Each box represents a debate. You can click on a specific box to see the debate details. The ladder visualizes the flow of the tournament."
},
"debates": {
"title": "Debates"
@@ -128,7 +126,23 @@
"debate_details": {
"unconfigured_debate": "Debate without a motion",
"proceed_to_debate": "Proceed to Debate!",
- "marshal_panel": "Marshal Panel"
+ "marshal_panel": "Marshal Panel",
+ "marshal_info": {
+ "title": "Marshal",
+ "placeholder_text": "Information about assigned Marshal will be presented here."
+ },
+ "judges_info": {
+ "title": "Judges",
+ "placeholder_text": "Information about assigned Judges will be presented here."
+ },
+ "time_and_place_info": {
+ "title": "Time and place",
+ "placeholder_text": "Information about time and place of the debate will be presented here"
+ },
+ "teams_info": {
+ "title": "Teams",
+ "placeholder_text": "Information about competing teams will be presented here"
+ }
},
"create_tournament": {
"title": "Create Tournament",
@@ -138,6 +152,7 @@
"full_name_placeholder": "(Required)"
},
"verdict_panel": {
+ "title": "Verdict",
"proposition": "Proposition",
"opposition": "Opposition",
"submit": "Submit",
@@ -151,21 +166,9 @@
"load_verdicts_error": "Unable to load verdict information",
"panel_error_title": "Verdict panel got an error, oops:",
"majority": {
- "proposition": {
- "prefix": "The",
- "highlight": "Proposition",
- "suffix": "is the winning team!"
- },
- "opposition": {
- "prefix": "The",
- "highlight": "Opposition",
- "suffix": "is the winning team!"
- },
- "no_verdict": {
- "prefix": "There is",
- "highlight": "no verdict",
- "suffix": "yet."
- }
+ "proposition": "The Proposition is the winning team!",
+ "opposition": "The Opposition is the winning team!",
+ "no_verdict": "There is no verdict available yet."
}
}
}
diff --git a/src/i18n/translations/pl.json b/src/i18n/translations/pl.json
index 6be9052..9b9faeb 100644
--- a/src/i18n/translations/pl.json
+++ b/src/i18n/translations/pl.json
@@ -65,30 +65,110 @@
"footer_text": "Komputerowe wspomaganie debat dostarcza ."
},
"overview": {
- "title": "Panel główny"
+ "title": "Panel główny",
+ "welcome": "Witaj w turnieju {tournamentName}!",
+ "get_started": "Aby rozpocząć, przejdź do Drabinki Turniejowej, aby zaplanować przebieg turnieju.",
+ "leaderboard_placeholder": "Wyniki drużyn (już wkrótce!)",
+ "leaderboard_desc": "Tutaj znajdzie się tabela z wynikami drużyn biorących udział w turnieju.",
+ "debates_placeholder": "Nadchodzące debaty (już wkrótce!)",
+ "debates_desc": "Tutaj znajdą się informacje o najbliższych zaplanowanych debatach.",
+ "event_log_placeholder": "Dziennik zdarzeń (już wkrótce!)",
+ "event_log_desc": "Tutaj zapisywane będą działania wykonywane przez użytkowników biorących udział w turnieju.",
+ "rules_placeholder": "Zasady turnieju (już wkrótce!)",
+ "rules_desc": "Tutaj pojawią się skrócone zasady turnieju."
},
"metadata": {
"title": "granda: Zaplanuj swój turniej debat",
"description": "Komputerowo wspomagane planowanie turniejów debat."
},
+ "generic": {
+ "error": "Błąd",
+ "error_loading_content": "Wystąpił błąd.",
+ "error_message": "Szczegóły: {message}"
+ },
"ladder": {
"title": "Drabinka turniejowa",
"planning_title": "Planowanie turnieju",
"planning_description": "Ustaw podstawowe parametry, aby wygenerować drabinkę turniejową.",
"group_phase_rounds": "Liczba rund fazy grupowej",
"groups_count": "Liczba grup",
+ "total_teams": "Łączna liczba drużyn",
"advancing_teams": "Liczba awansujących drużyn",
"submit": "Zaplanuj turniej",
"submitting": "Planowanie...",
- "placeholder_title": "Drabinka turniejowa",
- "placeholder_description": "Placeholder drabinki turniejowej.",
"no_phases_error": "Nie udało się pobrać faz turnieju.",
- "validation_positive_integer": "Ta wartość musi być dodatnią liczbą całkowitą.",
+ "validation_positive_integer": "Parametry muszą być dodatnimi liczbami całkowitymi.",
"validation_power_of_two": "Liczba awansujących drużyn musi być potęgą 2.",
+ "validation_groups_and_teams": "Liczba grup nie może być mniejsza niż łączna liczba drużyn.",
"request_failed": "Nie udało się zaplanować turnieju.",
- "success": "Planowanie turnieju zakończone powodzeniem."
+ "success": "Planowanie turnieju zakończone powodzeniem.",
+ "unconfigured_debate": "Nieskonfigurowana debata",
+ "advancing_teams_placeholder": "2, 4, 8, 16…",
+ "group_rounds_hint": "Określa, ile rund nastąpi po sobie w fazie grupowej.",
+ "groups_count_hint": "Podczas każdej rundy w każdej grupie odbywa się osobna debata. Ta liczba określa, ile debat odbędzie się jednocześnie. Musi być mniejsza niż łączna liczba drużyn.",
+ "total_teams_hint": "Łączna liczba drużyn biorących udział w turnieju.",
+ "advancing_teams_hint": "Liczba drużyn, które awansują do fazy pucharowej. Musi być potęgą 2.",
+ "hint_title": "Drabinka turniejowa",
+ "hint_content": "Każdy kafelek reprezentuje debatę. Możesz kliknąć na kafelek, by zobaczyć szczegóły debaty. Drabinka przedstawia przebieg turnieju."
+ },
+ "debates": {
+ "title": "Debaty"
+ },
+ "round_config": {
+ "title": "Konfiguracja rundy {name}",
+ "motion_title": "Teza",
+ "motion_description": "O czym będzie ta debata?",
+ "motion_placeholder": "(Wymagane)",
+ "infoslide_title": "Infoslajd",
+ "infoslide_description": "Dodatkowe informacje na temat tezy",
+ "apply": "Zastosuj"
},
"debate_details": {
- "unconfigured_debate": "Debata bez tezy"
+ "unconfigured_debate": "Debata bez tezy",
+ "proceed_to_debate": "Przejdź do debaty!",
+ "marshal_panel": "Panel marszałka",
+ "marshal_info": {
+ "title": "Marszałek",
+ "placeholder_text": "Informacja o marszałku przypisanym do debaty pojawi się tutaj."
+ },
+ "judges_info": {
+ "title": "Sędziowie",
+ "placeholder_text": "Informacje o panelu sędziowskim przypisanym do tej debaty pojawią się tutaj."
+ },
+ "time_and_place_info": {
+ "title": "Czas i miejsce",
+ "placeholder_text": "Informacje o czasie oraz miejscu debaty pojawią się tutaj."
+ },
+ "teams_info": {
+ "title": "Teams",
+ "placeholder_text": "Informacje o drużynach biorących udział w debacie pojawią się tutaj."
+ }
+ },
+ "create_tournament": {
+ "title": "Utwórz turniej",
+ "full_name": "Pełna nazwa",
+ "short_name": "Skrócona nazwa",
+ "close": "Zamknij",
+ "full_name_placeholder": "(Wymagane)"
+ },
+ "verdict_panel": {
+ "title": "Werdykt",
+ "proposition": "Propozycja",
+ "opposition": "Opozycja",
+ "submit": "Wyślij",
+ "select_verdict_error": "Wybierz stronę przed wysłaniem werdyktu.",
+ "submit_error": "Nie udało się wysłać werdyktu",
+ "failed_submit": "Nie udało się utworzyć werdyktu",
+ "failed_update": "Nie udało się zaktualizować werdyktu",
+ "no_existing_verdict": "Aktualizowany werdykt nie istnieje",
+ "failed_load_permissions": "Nie udało się wczytać uprawnień",
+ "failed_load_verdicts": "Nie udało się wczytać werdyktów",
+ "load_verdicts_error": "Nie udało się wczytać informacji o werdykcie",
+ "panel_error_title": "Błąd w panelu werdyktu",
+ "majority": {
+ "proposition": "Wygrała drużyna Propozycji!",
+ "opposition": "Wygrała drużyna Opozycji!",
+ "no_verdict": "Jeszcze nie opublikowano werdyktu"
+ }
}
}
diff --git a/test/e2e/tournament-ladder-rendering.test.ts b/test/e2e/tournament-ladder-rendering.test.ts
index 732c6db..e40f47d 100644
--- a/test/e2e/tournament-ladder-rendering.test.ts
+++ b/test/e2e/tournament-ladder-rendering.test.ts
@@ -60,7 +60,7 @@ testInTournamentAsAdmin(
page.getByText("You can click on a specific box"),
).toBeVisible();
await expect(
- page.getByText("The ladder shows the structure and flow"),
+ page.getByText("The ladder visualizes the flow of the tournament"),
).toBeVisible();
// WHEN
diff --git a/test/e2e/verdictPanel.test.ts b/test/e2e/verdictPanel.test.ts
index d2bf75b..71fd262 100644
--- a/test/e2e/verdictPanel.test.ts
+++ b/test/e2e/verdictPanel.test.ts
@@ -7,6 +7,9 @@ import {
createUserAndCastVote,
} from "./e2eUtils";
+const PROPOSITION_WINNING_TEXT = "The Proposition is the";
+const OPPOSITION_WINNING_TEXT = "The Opposition is the";
+
test.describe("verdict panel", () => {
testInTournamentAsAdmin(
"judge permission renders verdict submission options",
@@ -49,8 +52,9 @@ test.describe("verdict panel", () => {
.first()
.click();
- await expect(page.getByText("Verdict panel")).toBeVisible();
+ await expect(page.getByText("Verdict", { exact: true })).toBeVisible();
await expect(page.getByText("Opposition")).not.toBeVisible();
+ await expect(page.getByText("no verdict")).toBeVisible();
},
);
@@ -86,8 +90,7 @@ test.describe("verdict panel", () => {
.click();
await page.waitForURL(/debates/);
- const winningText = page.getByText("ThePropositionis the winning");
- await expect(winningText).toBeVisible();
+ await expect(page.getByText(PROPOSITION_WINNING_TEXT)).toBeVisible();
},
);
@@ -120,8 +123,7 @@ test.describe("verdict panel", () => {
await page.getByRole("button", { name: "Proposition" }).click();
await page.getByRole("button", { name: "Submit" }).click();
- const winningText = page.getByText("ThePropositionis the winning");
- await expect(winningText).toBeVisible();
+ await expect(page.getByText(PROPOSITION_WINNING_TEXT)).toBeVisible();
},
);
@@ -154,14 +156,12 @@ test.describe("verdict panel", () => {
await page.getByRole("button", { name: "Proposition" }).click();
await page.getByRole("button", { name: "Submit" }).click();
- const winningText = page.getByText("ThePropositionis the winning");
- await expect(winningText).toBeVisible();
+ await expect(page.getByText(PROPOSITION_WINNING_TEXT)).toBeVisible();
await page.getByRole("button", { name: "Opposition" }).click();
await page.getByRole("button", { name: "Submit" }).click();
- const otherWinningText = page.getByText("TheOppositionis the winning");
- await expect(otherWinningText).toBeVisible();
+ await expect(page.getByText(OPPOSITION_WINNING_TEXT)).toBeVisible();
},
);
});