Skip to content

Commit

Permalink
feat(web): workspace setting page (#1174)
Browse files Browse the repository at this point in the history
Co-authored-by: tcsola <[email protected]>
Co-authored-by: tcsola <[email protected]>
Co-authored-by: airslice <[email protected]>
  • Loading branch information
4 people authored Oct 18, 2024
1 parent b96d9f3 commit 967eb7c
Show file tree
Hide file tree
Showing 28 changed files with 1,216 additions and 226 deletions.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ type Props = {
isVisible: boolean;
onClose?: () => void;
passwordPolicy?: PasswordPolicy;
onPasswordUpdate?: ({
handleUpdateUserPassword?: ({
password,
passwordConfirmation
}: {
Expand All @@ -38,7 +38,7 @@ const PasswordModal: React.FC<Props> = ({
isVisible,
onClose,
passwordPolicy,
onPasswordUpdate
handleUpdateUserPassword
}) => {
const t = useT();
const theme = useTheme();
Expand Down Expand Up @@ -95,10 +95,10 @@ const PasswordModal: React.FC<Props> = ({

const handleSave = useCallback(() => {
if (password === passwordConfirmation) {
onPasswordUpdate?.({ password, passwordConfirmation });
handleUpdateUserPassword?.({ password, passwordConfirmation });
handleClose();
}
}, [onPasswordUpdate, handleClose, password, passwordConfirmation]);
}, [handleUpdateUserPassword, handleClose, password, passwordConfirmation]);

useEffect(() => {
if (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import { useMeFetcher } from "@reearth/services/api";
import { useCallback } from "react";

export type UpdatePasswordType = {
type UpdatePasswordType = {
password: string;
passwordConfirmation: string;
};

export default () => {
const { useMeQuery, useUpdatePassword, useDeleteUser } = useMeFetcher();
const { useMeQuery, useUpdatePassword, useDeleteUser, updateLanguage } =
useMeFetcher();
const { me: data } = useMeQuery();

const passwordPolicy = window.REEARTH_CONFIG?.passwordPolicy;

const { me: data } = useMeQuery();

const handleUpdateUserPassword = useCallback(
async ({ password, passwordConfirmation }: UpdatePasswordType) => {
try {
Expand All @@ -33,10 +33,22 @@ export default () => {
}
}, [data.id, useDeleteUser]);

const handleUpdateUserLanguage = useCallback(
async ({ lang }: { lang: string }) => {
try {
await updateLanguage(lang);
} catch (error) {
console.error("Failed to update language:", error);
}
},
[updateLanguage]
);

return {
meData: data,
passwordPolicy,
handleUpdateUserPassword,
handleDeleteUser
handleDeleteUser,
handleUpdateUserLanguage
};
};
158 changes: 158 additions & 0 deletions web/src/beta/features/AccountSetting/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
import useAccountSettingsTabs from "@reearth/beta/hooks/useAccountSettingsTabs";
import {
Collapse,
TextInput,
Typography,
IconButton
} from "@reearth/beta/lib/reearth-ui";
import SettingBase from "@reearth/beta/ui/components/SettingBase";
import { InputField, SelectField } from "@reearth/beta/ui/fields";
import { useT } from "@reearth/services/i18n";
import { useWorkspace } from "@reearth/services/state";
import { styled } from "@reearth/services/theme";
import { FC, useState } from "react";

import useHook from "./hooks";
import PasswordModal from "./PasswordModal";

const AccountSetting: FC = () => {
const t = useT();
const [changePasswordModal, setChangePasswordModal] =
useState<boolean>(false);

const {
meData,
passwordPolicy,
handleUpdateUserPassword,
handleUpdateUserLanguage
} = useHook();
const { name, email } = meData;

const [currentWorkspace] = useWorkspace();

const { tabs } = useAccountSettingsTabs({
workspaceId: currentWorkspace?.id ?? ""
});

const options = [
{
label: t("Auto"),
value: "und"
},
{
label: "English",
value: "en"
},
{
label: "日本語",
value: "ja"
}
];
type LanguageOption = (typeof options)[number]["value"];
const [languageLabel, setLanguageLabel] = useState<LanguageOption>("und");

return (
<SettingBase tabs={tabs} tab={"account"}>
<InnerPage>
<SettingsWrapper>
<Collapse size="large" title={t("Account")}>
<SettingsFields>
<InputField
title={t("Name")}
value={name ? t(name) : ""}
appearance="readonly"
disabled
/>
<InputField
title={t("Email address")}
value={email ? t(email) : ""}
appearance="readonly"
disabled
/>

<PasswordWrapper>
<Typography size="body">{t("Password")}</Typography>
<PasswordInputWrapper>
<TextInput
value={"**********"}
appearance="readonly"
disabled
extendWidth
/>
<IconButton
appearance="secondary"
icon="pencilSimple"
onClick={() => {
setChangePasswordModal(true);
}}
size="medium"
hasBorder={true}
/>
</PasswordInputWrapper>
</PasswordWrapper>
<SelectField
title={t("Language")}
value={languageLabel}
options={options}
onChange={(value) => {
if (typeof value === "string") {
setLanguageLabel(value);
handleUpdateUserLanguage({ lang: value });
}
}}
/>
</SettingsFields>
</Collapse>
</SettingsWrapper>

<PasswordModal
isVisible={changePasswordModal}
passwordPolicy={passwordPolicy}
onClose={() => setChangePasswordModal(false)}
handleUpdateUserPassword={handleUpdateUserPassword}
/>
</InnerPage>
</SettingBase>
);
};
export default AccountSetting;

const PasswordWrapper = styled("div")(() => ({
display: "flex",
flexDirection: "column",
width: "100%"
}));

const PasswordInputWrapper = styled("div")(({ theme }) => ({
display: "flex",
gap: theme.spacing.smallest,
alignItems: "center"
}));

const InnerPage = styled("div")<{
wide?: boolean;
transparent?: boolean;
}>(({ wide, transparent, theme }) => ({
boxSizing: "border-box",
display: "flex",
width: "100%",
maxWidth: wide ? 950 : 750,
backgroundColor: transparent ? "none" : theme.bg[1],
borderRadius: theme.radius.normal
}));

const SettingsWrapper = styled("div")(({ theme }) => ({
display: "flex",
flexDirection: "column",
width: "100%",
flex: 1,
["> div:not(:last-child)"]: {
borderBottom: `1px solid ${theme.outline.weaker}`
}
}));

const SettingsFields = styled("div")(({ theme }) => ({
display: "flex",
flexDirection: "column",
gap: theme.spacing.largest
}));
Loading

0 comments on commit 967eb7c

Please sign in to comment.