mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-05-31 04:04:21 -04:00
Add password reset button
This commit is contained in:
parent
6407579dd6
commit
ab6e8962e4
@ -29,7 +29,6 @@ import { percent, px, useYoshiki } from "yoshiki/native";
|
|||||||
import { DefaultLayout } from "../layout";
|
import { DefaultLayout } from "../layout";
|
||||||
import { FormPage } from "./form";
|
import { FormPage } from "./form";
|
||||||
import { PasswordInput } from "./password-input";
|
import { PasswordInput } from "./password-input";
|
||||||
import { useQueryClient } from "@tanstack/react-query";
|
|
||||||
import { cleanApiUrl } from "./login";
|
import { cleanApiUrl } from "./login";
|
||||||
|
|
||||||
export const RegisterPage: QueryPage = () => {
|
export const RegisterPage: QueryPage = () => {
|
||||||
@ -41,7 +40,6 @@ export const RegisterPage: QueryPage = () => {
|
|||||||
const [error, setError] = useState<string | undefined>(undefined);
|
const [error, setError] = useState<string | undefined>(undefined);
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const queryClient = useQueryClient();
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { css } = useYoshiki();
|
const { css } = useYoshiki();
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
Account,
|
Account,
|
||||||
|
KyooErrors,
|
||||||
QueryIdentifier,
|
QueryIdentifier,
|
||||||
QueryPage,
|
QueryPage,
|
||||||
User,
|
User,
|
||||||
@ -45,17 +46,17 @@ import {
|
|||||||
ts,
|
ts,
|
||||||
} from "@kyoo/primitives";
|
} from "@kyoo/primitives";
|
||||||
import { DefaultLayout } from "../layout";
|
import { DefaultLayout } from "../layout";
|
||||||
import { Children, ReactElement, ReactNode, useState, useTransition } from "react";
|
import { Children, ComponentProps, ReactElement, ReactNode, useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { ScrollView, View } from "react-native";
|
import { ScrollView, View } from "react-native";
|
||||||
import { Portal } from "@gorhom/portal";
|
import { px, rem, useYoshiki } from "yoshiki/native";
|
||||||
import { percent, px, rem, useYoshiki } from "yoshiki/native";
|
|
||||||
|
|
||||||
import Theme from "@material-symbols/svg-400/outlined/dark_mode.svg";
|
import Theme from "@material-symbols/svg-400/outlined/dark_mode.svg";
|
||||||
import Username from "@material-symbols/svg-400/outlined/badge.svg";
|
import Username from "@material-symbols/svg-400/outlined/badge.svg";
|
||||||
import Mail from "@material-symbols/svg-400/outlined/mail.svg";
|
import Mail from "@material-symbols/svg-400/outlined/mail.svg";
|
||||||
import Password from "@material-symbols/svg-400/outlined/password.svg";
|
import Password from "@material-symbols/svg-400/outlined/password.svg";
|
||||||
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||||
|
import { PasswordInput } from "../login/password-input";
|
||||||
|
|
||||||
const Preference = ({
|
const Preference = ({
|
||||||
icon,
|
icon,
|
||||||
@ -132,12 +133,14 @@ const ChangePopup = ({
|
|||||||
label,
|
label,
|
||||||
icon,
|
icon,
|
||||||
inital,
|
inital,
|
||||||
|
autoComplete,
|
||||||
apply,
|
apply,
|
||||||
close,
|
close,
|
||||||
}: {
|
}: {
|
||||||
label: string;
|
label: string;
|
||||||
icon: Icon;
|
icon: Icon;
|
||||||
inital: string;
|
inital: string;
|
||||||
|
autoComplete: ComponentProps<typeof Input>["autoComplete"];
|
||||||
apply: (v: string) => Promise<unknown>;
|
apply: (v: string) => Promise<unknown>;
|
||||||
close: () => void;
|
close: () => void;
|
||||||
}) => {
|
}) => {
|
||||||
@ -152,7 +155,12 @@ const ChangePopup = ({
|
|||||||
<Icon icon={icon} />
|
<Icon icon={icon} />
|
||||||
<H1 {...css({ fontSize: rem(2) })}>{label}</H1>
|
<H1 {...css({ fontSize: rem(2) })}>{label}</H1>
|
||||||
</View>
|
</View>
|
||||||
<Input variant="big" value={value} onChangeText={(v) => setValue(v)} />
|
<Input
|
||||||
|
autoComplete={autoComplete}
|
||||||
|
variant="big"
|
||||||
|
value={value}
|
||||||
|
onChangeText={(v) => setValue(v)}
|
||||||
|
/>
|
||||||
<View {...css({ flexDirection: "row", alignSelf: "flex-end", gap: ts(1) })}>
|
<View {...css({ flexDirection: "row", alignSelf: "flex-end", gap: ts(1) })}>
|
||||||
<Button
|
<Button
|
||||||
text={t("misc.cancel")}
|
text={t("misc.cancel")}
|
||||||
@ -174,9 +182,72 @@ const ChangePopup = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const ChangePasswordPopup = ({
|
||||||
|
label,
|
||||||
|
icon,
|
||||||
|
apply,
|
||||||
|
close,
|
||||||
|
}: {
|
||||||
|
label: string;
|
||||||
|
icon: Icon;
|
||||||
|
apply: (oldPassword: string, newPassword: string) => Promise<unknown>;
|
||||||
|
close: () => void;
|
||||||
|
}) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const [oldValue, setOldValue] = useState("");
|
||||||
|
const [newValue, setNewValue] = useState("");
|
||||||
|
const [error, setError] = useState<string | null>(null);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Popup>
|
||||||
|
{({ css }) => (
|
||||||
|
<>
|
||||||
|
<View {...css({ flexDirection: "row", alignItems: "center", gap: ts(2) })}>
|
||||||
|
<Icon icon={icon} />
|
||||||
|
<H1 {...css({ fontSize: rem(2) })}>{label}</H1>
|
||||||
|
</View>
|
||||||
|
<PasswordInput
|
||||||
|
autoComplete="current-password"
|
||||||
|
variant="big"
|
||||||
|
value={oldValue}
|
||||||
|
onChangeText={(v) => setOldValue(v)}
|
||||||
|
placeholder={t("settings.account.password.oldPassword")}
|
||||||
|
/>
|
||||||
|
<PasswordInput
|
||||||
|
autoComplete="password-new"
|
||||||
|
variant="big"
|
||||||
|
value={newValue}
|
||||||
|
onChangeText={(v) => setNewValue(v)}
|
||||||
|
placeholder={t("settings.account.password.newPassword")}
|
||||||
|
/>
|
||||||
|
{error && <P {...css({ color: (theme) => theme.colors.red })}>{error}</P>}
|
||||||
|
<View {...css({ flexDirection: "row", alignSelf: "flex-end", gap: ts(1) })}>
|
||||||
|
<Button
|
||||||
|
text={t("misc.cancel")}
|
||||||
|
onPress={() => close()}
|
||||||
|
{...css({ minWidth: rem(6) })}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
text={t("misc.edit")}
|
||||||
|
onPress={async () => {
|
||||||
|
try {
|
||||||
|
await apply(oldValue, newValue);
|
||||||
|
close();
|
||||||
|
} catch (e) {
|
||||||
|
setError((e as KyooErrors).errors[0]);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
{...css({ minWidth: rem(6) })}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Popup>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const AccountSettings = ({ setPopup }: { setPopup: (e?: ReactElement) => void }) => {
|
const AccountSettings = ({ setPopup }: { setPopup: (e?: ReactElement) => void }) => {
|
||||||
const account = useAccount();
|
const account = useAccount();
|
||||||
const { css } = useYoshiki();
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
@ -189,6 +260,14 @@ const AccountSettings = ({ setPopup }: { setPopup: (e?: ReactElement) => void })
|
|||||||
}),
|
}),
|
||||||
onSettled: async () => await queryClient.invalidateQueries({ queryKey: ["auth", "me"] }),
|
onSettled: async () => await queryClient.invalidateQueries({ queryKey: ["auth", "me"] }),
|
||||||
});
|
});
|
||||||
|
const { mutateAsync: editPassword } = useMutation({
|
||||||
|
mutationFn: async (request: { newPassword: string; oldPassword: string }) =>
|
||||||
|
await queryFn({
|
||||||
|
path: ["auth", "password-reset"],
|
||||||
|
method: "POST",
|
||||||
|
body: request,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
account && (
|
account && (
|
||||||
@ -204,6 +283,7 @@ const AccountSettings = ({ setPopup }: { setPopup: (e?: ReactElement) => void })
|
|||||||
setPopup(
|
setPopup(
|
||||||
<ChangePopup
|
<ChangePopup
|
||||||
icon={Username}
|
icon={Username}
|
||||||
|
autoComplete="username-new"
|
||||||
label={t("settings.account.username.label")}
|
label={t("settings.account.username.label")}
|
||||||
inital={account.username}
|
inital={account.username}
|
||||||
apply={async (v) => await mutateAsync({ username: v })}
|
apply={async (v) => await mutateAsync({ username: v })}
|
||||||
@ -224,6 +304,7 @@ const AccountSettings = ({ setPopup }: { setPopup: (e?: ReactElement) => void })
|
|||||||
setPopup(
|
setPopup(
|
||||||
<ChangePopup
|
<ChangePopup
|
||||||
icon={Mail}
|
icon={Mail}
|
||||||
|
autoComplete="email"
|
||||||
label={t("settings.account.email.label")}
|
label={t("settings.account.email.label")}
|
||||||
inital={account.email}
|
inital={account.email}
|
||||||
apply={async (v) => await mutateAsync({ email: v })}
|
apply={async (v) => await mutateAsync({ email: v })}
|
||||||
@ -237,7 +318,21 @@ const AccountSettings = ({ setPopup }: { setPopup: (e?: ReactElement) => void })
|
|||||||
icon={Password}
|
icon={Password}
|
||||||
label={t("settings.account.password.label")}
|
label={t("settings.account.password.label")}
|
||||||
description={t("settings.account.password.description")}
|
description={t("settings.account.password.description")}
|
||||||
></Preference>
|
>
|
||||||
|
<Button
|
||||||
|
text={t("misc.edit")}
|
||||||
|
onPress={() =>
|
||||||
|
setPopup(
|
||||||
|
<ChangePasswordPopup
|
||||||
|
icon={Password}
|
||||||
|
label={t("settings.account.password.label")}
|
||||||
|
apply={async (op, np) => await editPassword({ oldPassword: op, newPassword: np })}
|
||||||
|
close={() => setPopup(undefined)}
|
||||||
|
/>,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Preference>
|
||||||
</SettingsContainer>
|
</SettingsContainer>
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@ -96,7 +96,9 @@
|
|||||||
},
|
},
|
||||||
"password": {
|
"password": {
|
||||||
"label": "Password",
|
"label": "Password",
|
||||||
"description": "Change your password"
|
"description": "Change your password",
|
||||||
|
"oldPassword": "Old password",
|
||||||
|
"newPassword": "New password"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -96,7 +96,9 @@
|
|||||||
},
|
},
|
||||||
"password": {
|
"password": {
|
||||||
"label": "Mot de passe",
|
"label": "Mot de passe",
|
||||||
"description": "Changer de mot de passe"
|
"description": "Changer de mot de passe",
|
||||||
|
"oldPassword": "Ancien mot de passe",
|
||||||
|
"newPassword": "Nouveau mot de passe"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user