diff --git a/apps/client/src/scenes/Settings/DateFormat/DateFormat.tsx b/apps/client/src/scenes/Settings/DateFormat/DateFormat.tsx
new file mode 100644
index 00000000..95d7866c
--- /dev/null
+++ b/apps/client/src/scenes/Settings/DateFormat/DateFormat.tsx
@@ -0,0 +1,49 @@
+import { Select, MenuItem } from "@mui/material";
+import { useCallback } from "react";
+import { useSelector } from "react-redux";
+import Text from "../../../components/Text";
+import TitleCard from "../../../components/TitleCard";
+import { changeDateFormat } from "../../../services/redux/modules/settings/thunk";
+import { selectDateFormat } from "../../../services/redux/modules/user/selector";
+import { useAppDispatch } from "../../../services/redux/tools";
+import SettingLine from "../SettingLine";
+import { dateFormats } from "./dateFormats";
+import s from "./index.module.css";
+
+export default function DateFormat() {
+ const dispatch = useAppDispatch();
+ const currentDateFormat = useSelector(selectDateFormat);
+
+ const handleChangeDateFormat = useCallback(
+ (newDateFormat: string | null | undefined) => {
+ dispatch(changeDateFormat(newDateFormat ?? "default")).catch(
+ console.error,
+ );
+ },
+ [dispatch],
+ );
+
+ return (
+
+
+ Format of dates throughout the application for this user.
+
+ handleChangeDateFormat(ev.target.value)}>
+ Follow browser
+ {dateFormats.map(dateFormat => (
+
+ {dateFormat.name}
+
+ ))}
+
+ }
+ />
+
+ );
+}
diff --git a/apps/client/src/scenes/Settings/DateFormat/dateFormats.ts b/apps/client/src/scenes/Settings/DateFormat/dateFormats.ts
new file mode 100644
index 00000000..9b86cc63
--- /dev/null
+++ b/apps/client/src/scenes/Settings/DateFormat/dateFormats.ts
@@ -0,0 +1,144 @@
+export const dateFormats = [
+ { name: "Afrikaans", code: "af" },
+ { name: "Albanian - shqip", code: "sq" },
+ { name: "Amharic - አማርኛ", code: "am" },
+ { name: "Arabic - العربية", code: "ar" },
+ { name: "Aragonese - aragonés", code: "an" },
+ { name: "Armenian - հայերեն", code: "hy" },
+ { name: "Asturian - asturianu", code: "ast" },
+ { name: "Azerbaijani - azərbaycan dili", code: "az" },
+ { name: "Basque - euskara", code: "eu" },
+ { name: "Belarusian - беларуская", code: "be" },
+ { name: "Bengali - বাংলা", code: "bn" },
+ { name: "Bosnian - bosanski", code: "bs" },
+ { name: "Breton - brezhoneg", code: "br" },
+ { name: "Bulgarian - български", code: "bg" },
+ { name: "Catalan - català", code: "ca" },
+ { name: "Central Kurdish - کوردی (دەستنوسی عەرەبی)", code: "ckb" },
+ { name: "Chinese - 中文", code: "zh" },
+ { name: "Chinese (Hong Kong) - 中文(香港)", code: "zh-HK" },
+ { name: "Chinese (Simplified) - 中文(简体)", code: "zh-CN" },
+ { name: "Chinese (Traditional) - 中文(繁體)", code: "zh-TW" },
+ { name: "Corsican", code: "co" },
+ { name: "Croatian - hrvatski", code: "hr" },
+ { name: "Czech - čeština", code: "cs" },
+ { name: "Danish - dansk", code: "da" },
+ { name: "Dutch - Nederlands", code: "nl" },
+ { name: "English", code: "en" },
+ { name: "English (Australia)", code: "en-AU" },
+ { name: "English (Canada)", code: "en-CA" },
+ { name: "English (India)", code: "en-IN" },
+ { name: "English (New Zealand)", code: "en-NZ" },
+ { name: "English (South Africa)", code: "en-ZA" },
+ { name: "English (United Kingdom)", code: "en-GB" },
+ { name: "English (United States)", code: "en-US" },
+ { name: "Esperanto - esperanto", code: "eo" },
+ { name: "Estonian - eesti", code: "et" },
+ { name: "Faroese - føroyskt", code: "fo" },
+ { name: "Filipino", code: "fil" },
+ { name: "Finnish - suomi", code: "fi" },
+ { name: "French - français", code: "fr" },
+ { name: "French (Canada) - français (Canada)", code: "fr-CA" },
+ { name: "French (France) - français (France)", code: "fr-FR" },
+ { name: "French (Switzerland) - français (Suisse)", code: "fr-CH" },
+ { name: "Galician - galego", code: "gl" },
+ { name: "Georgian - ქართული", code: "ka" },
+ { name: "German - Deutsch", code: "de" },
+ { name: "German (Austria) - Deutsch (Österreich)", code: "de-AT" },
+ { name: "German (Germany) - Deutsch (Deutschland)", code: "de-DE" },
+ { name: "German (Liechtenstein) - Deutsch (Liechtenstein)", code: "de-LI" },
+ { name: "German (Switzerland) - Deutsch (Schweiz)", code: "de-CH" },
+ { name: "Greek - Ελληνικά", code: "el" },
+ { name: "Guarani", code: "gn" },
+ { name: "Gujarati - ગુજરાતી", code: "gu" },
+ { name: "Hausa", code: "ha" },
+ { name: "Hawaiian - ʻŌlelo Hawaiʻi", code: "haw" },
+ { name: "Hebrew - עברית", code: "he" },
+ { name: "Hindi - हिन्दी", code: "hi" },
+ { name: "Hungarian - magyar", code: "hu" },
+ { name: "Icelandic - íslenska", code: "is" },
+ { name: "Indonesian - Indonesia", code: "id" },
+ { name: "Interlingua", code: "ia" },
+ { name: "Irish - Gaeilge", code: "ga" },
+ { name: "Italian - italiano", code: "it" },
+ { name: "Italian (Italy) - italiano (Italia)", code: "it-IT" },
+ { name: "Italian (Switzerland) - italiano (Svizzera)", code: "it-CH" },
+ { name: "Japanese - 日本語", code: "ja" },
+ { name: "Kannada - ಕನ್ನಡ", code: "kn" },
+ { name: "Kazakh - қазақ тілі", code: "kk" },
+ { name: "Khmer - ខ្មែរ", code: "km" },
+ { name: "Korean - 한국어", code: "ko" },
+ { name: "Kurdish - Kurdî", code: "ku" },
+ { name: "Kyrgyz - кыргызча", code: "ky" },
+ { name: "Lao - ລາວ", code: "lo" },
+ { name: "Latin", code: "la" },
+ { name: "Latvian - latviešu", code: "lv" },
+ { name: "Lingala - lingála", code: "ln" },
+ { name: "Lithuanian - lietuvių", code: "lt" },
+ { name: "Macedonian - македонски", code: "mk" },
+ { name: "Malay - Bahasa Melayu", code: "ms" },
+ { name: "Malayalam - മലയാളം", code: "ml" },
+ { name: "Maltese - Malti", code: "mt" },
+ { name: "Marathi - मराठी", code: "mr" },
+ { name: "Mongolian - монгол", code: "mn" },
+ { name: "Nepali - नेपाली", code: "ne" },
+ { name: "Norwegian - norsk", code: "no" },
+ { name: "Norwegian Bokmål - norsk bokmål", code: "nb" },
+ { name: "Norwegian Nynorsk - nynorsk", code: "nn" },
+ { name: "Occitan", code: "oc" },
+ { name: "Oriya - ଓଡ଼ିଆ", code: "or" },
+ { name: "Oromo - Oromoo", code: "om" },
+ { name: "Pashto - پښتو", code: "ps" },
+ { name: "Persian - فارسی", code: "fa" },
+ { name: "Polish - polski", code: "pl" },
+ { name: "Portuguese - português", code: "pt" },
+ { name: "Portuguese (Brazil) - português (Brasil)", code: "pt-BR" },
+ { name: "Portuguese (Portugal) - português (Portugal)", code: "pt-PT" },
+ { name: "Punjabi - ਪੰਜਾਬੀ", code: "pa" },
+ { name: "Quechua", code: "qu" },
+ { name: "Romanian - română", code: "ro" },
+ { name: "Romanian (Moldova) - română (Moldova)", code: "mo" },
+ { name: "Romansh - rumantsch", code: "rm" },
+ { name: "Russian - русский", code: "ru" },
+ { name: "Scottish Gaelic", code: "gd" },
+ { name: "Serbian - српски", code: "sr" },
+ { name: "Serbo - Croatian", code: "sh" },
+ { name: "Shona - chiShona", code: "sn" },
+ { name: "Sindhi", code: "sd" },
+ { name: "Sinhala - සිංහල", code: "si" },
+ { name: "Slovak - slovenčina", code: "sk" },
+ { name: "Slovenian - slovenščina", code: "sl" },
+ { name: "Somali - Soomaali", code: "so" },
+ { name: "Southern Sotho", code: "st" },
+ { name: "Spanish - español", code: "es" },
+ { name: "Spanish (Argentina) - español (Argentina)", code: "es-AR" },
+ { name: "Spanish (Latin America) - español (Latinoamérica)", code: "es-419" },
+ { name: "Spanish (Mexico) - español (México)", code: "es-MX" },
+ { name: "Spanish (Spain) - español (España)", code: "es-ES" },
+ { name: "Spanish (United States) - español (Estados Unidos)", code: "es-US" },
+ { name: "Sundanese", code: "su" },
+ { name: "Swahili - Kiswahili", code: "sw" },
+ { name: "Swedish - svenska", code: "sv" },
+ { name: "Tajik - тоҷикӣ", code: "tg" },
+ { name: "Tamil - தமிழ்", code: "ta" },
+ { name: "Tatar", code: "tt" },
+ { name: "Telugu - తెలుగు", code: "te" },
+ { name: "Thai - ไทย", code: "th" },
+ { name: "Tigrinya - ትግርኛ", code: "ti" },
+ { name: "Tongan - lea fakatonga", code: "to" },
+ { name: "Turkish - Türkçe", code: "tr" },
+ { name: "Turkmen", code: "tk" },
+ { name: "Twi", code: "tw" },
+ { name: "Ukrainian - українська", code: "uk" },
+ { name: "Urdu - اردو", code: "ur" },
+ { name: "Uyghur", code: "ug" },
+ { name: "Uzbek - o‘zbek", code: "uz" },
+ { name: "Vietnamese - Tiếng Việt", code: "vi" },
+ { name: "Walloon - wa", code: "wa" },
+ { name: "Welsh - Cymraeg", code: "cy" },
+ { name: "Western Frisian", code: "fy" },
+ { name: "Xhosa", code: "xh" },
+ { name: "Yiddish", code: "yi" },
+ { name: "Yoruba - Èdè Yorùbá", code: "yo" },
+ { name: "Zulu - isiZulu", code: "zu" },
+];
diff --git a/apps/client/src/scenes/Settings/DateFormat/index.module.css b/apps/client/src/scenes/Settings/DateFormat/index.module.css
new file mode 100644
index 00000000..9c929669
--- /dev/null
+++ b/apps/client/src/scenes/Settings/DateFormat/index.module.css
@@ -0,0 +1,4 @@
+.marginbottom {
+ display: block;
+ margin-bottom: 8px;
+}
\ No newline at end of file
diff --git a/apps/client/src/scenes/Settings/DateFormat/index.ts b/apps/client/src/scenes/Settings/DateFormat/index.ts
new file mode 100644
index 00000000..ad137ece
--- /dev/null
+++ b/apps/client/src/scenes/Settings/DateFormat/index.ts
@@ -0,0 +1 @@
+export { default } from "./DateFormat";
diff --git a/apps/client/src/scenes/Settings/Importer/ImportHistory/ImportHistory.tsx b/apps/client/src/scenes/Settings/Importer/ImportHistory/ImportHistory.tsx
index 63a090c6..78d8fb11 100644
--- a/apps/client/src/scenes/Settings/Importer/ImportHistory/ImportHistory.tsx
+++ b/apps/client/src/scenes/Settings/Importer/ImportHistory/ImportHistory.tsx
@@ -1,7 +1,6 @@
import { useCallback } from "react";
import { useSelector } from "react-redux";
import { CircularProgress } from "@mui/material";
-import { dateToListenedAt } from "../../../../services/stats";
import SettingLine from "../../SettingLine";
import { selectImportStates } from "../../../../services/redux/modules/import/selector";
import {
@@ -13,6 +12,7 @@ import { compact } from "../../../../services/tools";
import { ImporterStateStatus } from "../../../../services/redux/modules/import/types";
import Text from "../../../../components/Text";
import { useAppDispatch } from "../../../../services/redux/tools";
+import { DateFormatter } from "../../../../services/date";
import s from "./index.module.css";
const statusToString: Record
= {
@@ -28,7 +28,7 @@ export default function ImportHistory() {
const cleanImport = useCallback(
async (id: string) => {
- dispatch(cleanupImport(id));
+ dispatch(cleanupImport(id)).catch(console.error);
},
[dispatch],
);
@@ -52,7 +52,7 @@ export default function ImportHistory() {
key={st._id}
left={
- Import of {dateToListenedAt(new Date(st.createdAt))}
+ Import of {DateFormatter.listenedAt(new Date(st.createdAt))}
from {st.type}
}
diff --git a/apps/client/src/scenes/Settings/Settings.tsx b/apps/client/src/scenes/Settings/Settings.tsx
index a0e5a749..c55f9df1 100644
--- a/apps/client/src/scenes/Settings/Settings.tsx
+++ b/apps/client/src/scenes/Settings/Settings.tsx
@@ -26,6 +26,7 @@ import RelogToSpotify from "./RelogToSpotify";
import SetAdmin from "./SetAdmin";
import SpotifyAccountInfos from "./SpotifyAccountInfos";
import Timezone from "./Timezone";
+import DateFormat from "./DateFormat";
export default function Settings() {
const settings = useSelector(selectSettings);
@@ -107,6 +108,7 @@ export default function Settings() {
{!isPublic && }
{!isPublic && }
+ {!isPublic && }
}
/>
diff --git a/apps/client/src/scenes/Settings/Timezone/Timezone.tsx b/apps/client/src/scenes/Settings/Timezone/Timezone.tsx
index 797ce865..e1ce04c5 100644
--- a/apps/client/src/scenes/Settings/Timezone/Timezone.tsx
+++ b/apps/client/src/scenes/Settings/Timezone/Timezone.tsx
@@ -12,14 +12,14 @@ import s from "./index.module.css";
export default function Timezone() {
const dispatch = useAppDispatch();
- const dark = useSelector(selectTimezone);
+ const currentTimezone = useSelector(selectTimezone);
const handleChangeTimezone = useCallback(
(newTimezone: string | null | undefined) => {
if (newTimezone === "follow") {
newTimezone = null;
}
- dispatch(changeTimezone(newTimezone));
+ dispatch(changeTimezone(newTimezone)).catch(console.error);
},
[dispatch],
);
@@ -35,7 +35,7 @@ export default function Timezone() {
right={
handleChangeTimezone(ev.target.value)}>
Default timezone
{timezones.map(timezone => (
diff --git a/apps/client/src/scenes/TrackStats/FirstAndLast/FirstAndLast.tsx b/apps/client/src/scenes/TrackStats/FirstAndLast/FirstAndLast.tsx
index eec4a6a8..eac22988 100644
--- a/apps/client/src/scenes/TrackStats/FirstAndLast/FirstAndLast.tsx
+++ b/apps/client/src/scenes/TrackStats/FirstAndLast/FirstAndLast.tsx
@@ -1,6 +1,6 @@
-import { dateToListenedAt } from "../../../services/stats";
import Text from "../../../components/Text";
import TitleCard from "../../../components/TitleCard";
+import { DateFormatter } from "../../../services/date";
import s from "./index.module.css";
interface FirstAndLastProps {
@@ -19,7 +19,7 @@ export default function FirstAndLast({
Last listened on{" "}
- {dateToListenedAt(lastDate)}
+ {DateFormatter.listenedAt(lastDate)}
@@ -28,7 +28,7 @@ export default function FirstAndLast({