username-display-on-settings

Displays username on account settings tab,
This commit is contained in:
s.p.e.c.t.r.e 2025-03-04 18:53:25 -03:00 committed by GitHub
parent af2896efc3
commit e49e0c3e6e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1,255 +1,255 @@
import { Avatar, Button, SelectField } from "@renderer/components"; import { Avatar, Button, SelectField } from "@renderer/components";
import { Controller, useForm } from "react-hook-form"; import { Controller, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useDate, useToast, useUserDetails } from "@renderer/hooks"; import { useDate, useToast, useUserDetails } from "@renderer/hooks";
import { useCallback, useContext, useEffect, useState } from "react"; import { useCallback, useContext, useEffect, useState } from "react";
import { import {
CloudIcon, CloudIcon,
KeyIcon, KeyIcon,
MailIcon, MailIcon,
XCircleFillIcon, XCircleFillIcon,
} from "@primer/octicons-react"; } from "@primer/octicons-react";
import { settingsContext } from "@renderer/context"; import { settingsContext } from "@renderer/context";
import { AuthPage } from "@shared"; import { AuthPage } from "@shared";
import "./settings-account.scss"; import "./settings-account.scss";
interface FormValues { interface FormValues {
profileVisibility: "PUBLIC" | "FRIENDS" | "PRIVATE"; profileVisibility: "PUBLIC" | "FRIENDS" | "PRIVATE";
} }
export function SettingsAccount() { export function SettingsAccount() {
const { t } = useTranslation("settings"); const { t } = useTranslation("settings");
const [isUnblocking, setIsUnblocking] = useState(false); const [isUnblocking, setIsUnblocking] = useState(false);
const { showSuccessToast } = useToast(); const { showSuccessToast } = useToast();
const { blockedUsers, fetchBlockedUsers } = useContext(settingsContext); const { blockedUsers, fetchBlockedUsers } = useContext(settingsContext);
const { formatDate } = useDate(); const { formatDate } = useDate();
const { const {
control, control,
formState: { isSubmitting }, formState: { isSubmitting },
setValue, setValue,
handleSubmit, handleSubmit,
} = useForm<FormValues>(); } = useForm<FormValues>();
const { const {
userDetails, userDetails,
hasActiveSubscription, hasActiveSubscription,
patchUser, patchUser,
fetchUserDetails, fetchUserDetails,
updateUserDetails, updateUserDetails,
unblockUser, unblockUser,
} = useUserDetails(); } = useUserDetails();
useEffect(() => { useEffect(() => {
if (userDetails?.profileVisibility) { if (userDetails?.profileVisibility) {
setValue("profileVisibility", userDetails.profileVisibility); setValue("profileVisibility", userDetails.profileVisibility);
} }
}, [userDetails, setValue]); }, [userDetails, setValue]);
useEffect(() => { useEffect(() => {
const unsubscribe = window.electron.onAccountUpdated(() => { const unsubscribe = window.electron.onAccountUpdated(() => {
fetchUserDetails().then((response) => { fetchUserDetails().then((response) => {
if (response) { if (response) {
updateUserDetails(response); updateUserDetails(response);
} }
}); });
showSuccessToast(t("account_data_updated_successfully")); showSuccessToast(t("account_data_updated_successfully"));
}); });
return () => { return () => {
unsubscribe(); unsubscribe();
}; };
}, [fetchUserDetails, updateUserDetails, t, showSuccessToast]); }, [fetchUserDetails, updateUserDetails, t, showSuccessToast]);
const visibilityOptions = [ const visibilityOptions = [
{ value: "PUBLIC", label: t("public") }, { value: "PUBLIC", label: t("public") },
{ value: "FRIENDS", label: t("friends_only") }, { value: "FRIENDS", label: t("friends_only") },
{ value: "PRIVATE", label: t("private") }, { value: "PRIVATE", label: t("private") },
]; ];
const onSubmit = async (values: FormValues) => { const onSubmit = async (values: FormValues) => {
await patchUser(values); await patchUser(values);
showSuccessToast(t("changes_saved")); showSuccessToast(t("changes_saved"));
}; };
const handleUnblockClick = useCallback( const handleUnblockClick = useCallback(
(id: string) => { (id: string) => {
setIsUnblocking(true); setIsUnblocking(true);
unblockUser(id) unblockUser(id)
.then(() => { .then(() => {
fetchBlockedUsers(); fetchBlockedUsers();
showSuccessToast(t("user_unblocked")); showSuccessToast(t("user_unblocked"));
}) })
.finally(() => { .finally(() => {
setIsUnblocking(false); setIsUnblocking(false);
}); });
}, },
[unblockUser, fetchBlockedUsers, t, showSuccessToast] [unblockUser, fetchBlockedUsers, t, showSuccessToast]
); );
const getHydraCloudSectionContent = () => { const getHydraCloudSectionContent = () => {
const hasSubscribedBefore = Boolean(userDetails?.subscription?.expiresAt); const hasSubscribedBefore = Boolean(userDetails?.subscription?.expiresAt);
const isRenewalActive = userDetails?.subscription?.status === "active"; const isRenewalActive = userDetails?.subscription?.status === "active";
if (!hasSubscribedBefore) { if (!hasSubscribedBefore) {
return { return {
description: <small>{t("no_subscription")}</small>, description: <small>{t("no_subscription")}</small>,
callToAction: t("become_subscriber"), callToAction: t("become_subscriber"),
}; };
} }
if (hasActiveSubscription) { if (hasActiveSubscription) {
return { return {
description: isRenewalActive ? ( description: isRenewalActive ? (
<> <>
<small> <small>
{t("subscription_renews_on", { {t("subscription_renews_on", {
date: formatDate(userDetails.subscription!.expiresAt!), date: formatDate(userDetails.subscription!.expiresAt!),
})} })}
</small> </small>
<small>{t("bill_sent_until")}</small> <small>{t("bill_sent_until")}</small>
</> </>
) : ( ) : (
<> <>
<small>{t("subscription_renew_cancelled")}</small> <small>{t("subscription_renew_cancelled")}</small>
<small> <small>
{t("subscription_active_until", { {t("subscription_active_until", {
date: formatDate(userDetails!.subscription!.expiresAt!), date: formatDate(userDetails!.subscription!.expiresAt!),
})} })}
</small> </small>
</> </>
), ),
callToAction: t("manage_subscription"), callToAction: t("manage_subscription"),
}; };
} }
return { return {
description: ( description: (
<small> <small>
{t("subscription_expired_at", { {t("subscription_expired_at", {
date: formatDate(userDetails!.subscription!.expiresAt!), date: formatDate(userDetails!.subscription!.expiresAt!),
})} })}
</small> </small>
), ),
callToAction: t("renew_subscription"), callToAction: t("renew_subscription"),
}; };
}; };
if (!userDetails) return null; if (!userDetails) return null;
return ( return (
<form className="settings-account__form" onSubmit={handleSubmit(onSubmit)}> <form className="settings-account__form" onSubmit={handleSubmit(onSubmit)}>
<Controller <Controller
control={control} control={control}
name="profileVisibility" name="profileVisibility"
render={({ field }) => { render={({ field }) => {
const handleChange = ( const handleChange = (
event: React.ChangeEvent<HTMLSelectElement> event: React.ChangeEvent<HTMLSelectElement>
) => { ) => {
field.onChange(event); field.onChange(event);
handleSubmit(onSubmit)(); handleSubmit(onSubmit)();
}; };
return ( return (
<section className="settings-account__section"> <section className="settings-account__section">
<SelectField <SelectField
label={t("profile_visibility")} label={t("profile_visibility")}
value={field.value} value={field.value}
onChange={handleChange} onChange={handleChange}
options={visibilityOptions.map((visiblity) => ({ options={visibilityOptions.map((visiblity) => ({
key: visiblity.value, key: visiblity.value,
value: visiblity.value, value: visiblity.value,
label: visiblity.label, label: visiblity.label,
}))} }))}
disabled={isSubmitting} disabled={isSubmitting}
/> />
<small>{t("profile_visibility_description")}</small> <small>{t("profile_visibility_description")}</small>
</section> </section>
); );
}} }}
/> />
<section className="settings-account__section"> <section className="settings-account__section">
<h4>{t("current_email")}</h4> <h4>{t("current_email")}</h4>
<p>{userDetails?.email ?? t("no_email_account")}</p> <p>{userDetails?.email ?? t("no_email_account")}</p>
<h4>Nome de usuário:</h4>
<div className="settings-account__actions"> <p>{userDetails?.username}</p>
<Button <div className="settings-account__actions">
theme="outline" <Button
onClick={() => window.electron.openAuthWindow(AuthPage.UpdateEmail)} theme="outline"
> onClick={() => window.electron.openAuthWindow(AuthPage.UpdateEmail)}
<MailIcon /> >
{t("update_email")} <MailIcon />
</Button> {t("update_email")}
</Button>
<Button
theme="outline" <Button
onClick={() => theme="outline"
window.electron.openAuthWindow(AuthPage.UpdatePassword) onClick={() =>
} window.electron.openAuthWindow(AuthPage.UpdatePassword)
> }
<KeyIcon /> >
{t("update_password")} <KeyIcon />
</Button> {t("update_password")}
</div> </Button>
</section> </div>
</section>
<section className="settings-account__section"> <section className="settings-account__section">
<h3>Hydra Cloud</h3> <h3>Hydra Cloud</h3>
<div className="settings-account__subscription-info"> <div className="settings-account__subscription-info">
{getHydraCloudSectionContent().description} {getHydraCloudSectionContent().description}
</div> </div>
<Button <Button
className="settings-account__subscription-button" className="settings-account__subscription-button"
theme="outline" theme="outline"
onClick={() => window.electron.openCheckout()} onClick={() => window.electron.openCheckout()}
> >
<CloudIcon /> <CloudIcon />
{getHydraCloudSectionContent().callToAction} {getHydraCloudSectionContent().callToAction}
</Button> </Button>
</section> </section>
<section className="settings-account__section"> <section className="settings-account__section">
<h3>{t("blocked_users")}</h3> <h3>{t("blocked_users")}</h3>
{blockedUsers.length > 0 ? ( {blockedUsers.length > 0 ? (
<ul className="settings-account__blocked-users"> <ul className="settings-account__blocked-users">
{blockedUsers.map((user) => { {blockedUsers.map((user) => {
return ( return (
<li key={user.id} className="settings-account__blocked-user"> <li key={user.id} className="settings-account__blocked-user">
<div className="settings-account__user-info"> <div className="settings-account__user-info">
<Avatar <Avatar
className="settings-account__user-avatar" className="settings-account__user-avatar"
size={32} size={32}
src={user.profileImageUrl} src={user.profileImageUrl}
alt={user.displayName} alt={user.displayName}
/> />
<span>{user.displayName}</span> <span>{user.displayName}</span>
</div> </div>
<button <button
type="button" type="button"
className="settings-account__unblock-button" className="settings-account__unblock-button"
onClick={() => handleUnblockClick(user.id)} onClick={() => handleUnblockClick(user.id)}
disabled={isUnblocking} disabled={isUnblocking}
> >
<XCircleFillIcon /> <XCircleFillIcon />
</button> </button>
</li> </li>
); );
})} })}
</ul> </ul>
) : ( ) : (
<small>{t("no_users_blocked")}</small> <small>{t("no_users_blocked")}</small>
)} )}
</section> </section>
</form> </form>
); );
} }