Skip to content

Commit

Permalink
chore: add user profile drawer to CRM example (#4888)
Browse files Browse the repository at this point in the history
* fix: remove logout button on sider

* feat: add dropdown menu to user avatar

* feat: add user account drawer

* fix: performance issue
  • Loading branch information
salihozdemir authored Aug 31, 2023
1 parent c1ec8c9 commit e3b6ef0
Show file tree
Hide file tree
Showing 7 changed files with 390 additions and 64 deletions.
45 changes: 45 additions & 0 deletions examples/app-crm/src/components/account-settings/index.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
.header {
display: flex;
justify-content: space-between;
align-items: center;
background-color: #fff;
padding: 16px;
}

.container {
display: flex;
flex-direction: column;
gap: 32px;
padding: 24px;

.title {
display: block;
margin: 0 !important;

.titleEditIcon {
visibility: hidden;
opacity: 0;
transition: all 0.2s ease-in-out;
}

&:hover {
.titleEditIcon {
opacity: 1;
visibility: visible !important;
}
}
}

.name {
display: flex;
align-items: center;
justify-content: flex-start;
padding: 1rem;
}

.form {
background-color: #fff;
border-radius: 0.5rem;
margin-bottom: 1.75rem;
}
}
254 changes: 254 additions & 0 deletions examples/app-crm/src/components/account-settings/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
import { useState } from "react";
import { useOne, useUpdate } from "@refinedev/core";
import {
Button,
Card,
Drawer,
Input,
Select,
Space,
Spin,
Typography,
} from "antd";
import {
CloseOutlined,
EditOutlined,
GlobalOutlined,
IdcardOutlined,
MailOutlined,
PhoneOutlined,
SafetyCertificateOutlined,
UserOutlined,
} from "@ant-design/icons";

import { SingleElementForm } from "../single-element-form";
import { CustomAvatar } from "../custom-avatar";
import { Text } from "../text";
import { Timezone } from "../../enums/timezone";
import { User } from "../../interfaces/graphql";
import styles from "./index.module.css";

const timezoneOptions = Object.keys(Timezone).map((key) => ({
label: Timezone[key as keyof typeof Timezone],
value: Timezone[key as keyof typeof Timezone],
}));

type Props = {
opened: boolean;
setOpened: (opened: boolean) => void;
userId: string;
};

type FormKeys = "email" | "jobTitle" | "phone" | "timezone";

export const AccountSettings = ({ opened, setOpened, userId }: Props) => {
const [activeForm, setActiveForm] = useState<FormKeys>();

const { data, isLoading, isError } = useOne<User>({
resource: "users",
id: userId,
queryOptions: {
enabled: opened,
},
meta: {
fields: [
"id",
"name",
"email",
"avatarUrl",
"jobTitle",
"phone",
"timezone",
],
},
});
const { mutate: updateMutation } = useUpdate<User>();

const closeModal = () => {
setOpened(false);
};

if (isError) {
closeModal();
return null;
}

if (isLoading) {
return (
<Drawer
open={opened}
width={756}
bodyStyle={{
background: "#f5f5f5",
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
>
<Spin />
</Drawer>
);
}

const { id, name, email, jobTitle, phone, timezone, avatarUrl } =
data?.data ?? {};

const getActiveForm = (key: FormKeys) => {
if (activeForm === key) {
return "form";
}

if (!data?.data[key]) {
return "empty";
}

return "view";
};

return (
<Drawer
onClose={closeModal}
open={opened}
width={756}
bodyStyle={{ background: "#f5f5f5", padding: 0 }}
headerStyle={{ display: "none" }}
>
<div className={styles.header}>
<Text strong>Account Settings</Text>
<Button
type="text"
icon={<CloseOutlined />}
onClick={() => closeModal()}
/>
</div>
<div className={styles.container}>
<div className={styles.name}>
<CustomAvatar
style={{
marginRight: "1rem",
flexShrink: 0,
fontSize: "40px",
}}
size={96}
src={avatarUrl}
name={name}
/>
<Typography.Title
level={3}
style={{ padding: 0, margin: 0, width: "100%" }}
className={styles.title}
editable={{
onChange(value) {
updateMutation({
resource: "users",
id,
values: { name: value },
mutationMode: "optimistic",
successNotification: false,
});
},
triggerType: ["text", "icon"],
icon: (
<EditOutlined
className={styles.titleEditIcon}
/>
),
}}
>
{name}
</Typography.Title>
</div>
<Card
title={
<Space size={15}>
<UserOutlined />
<Text size="sm">User profile</Text>
</Space>
}
headStyle={{ padding: "0 12px" }}
bodyStyle={{ padding: "0" }}
>
<SingleElementForm
useFormProps={{ id, resource: "users" }}
formProps={{ initialValues: { jobTitle } }}
icon={<IdcardOutlined className="tertiary" />}
state={getActiveForm("jobTitle")}
itemProps={{
name: "jobTitle",
label: "Title",
}}
view={<Text>{jobTitle}</Text>}
onClick={() => setActiveForm("jobTitle")}
onUpdate={() => setActiveForm(undefined)}
onCancel={() => setActiveForm(undefined)}
>
<Input />
</SingleElementForm>
<SingleElementForm
useFormProps={{ id, resource: "users" }}
formProps={{ initialValues: { phone } }}
icon={<PhoneOutlined className="tertiary" />}
state={getActiveForm("phone")}
itemProps={{
name: "phone",
label: "Phone",
}}
view={<Text>{phone}</Text>}
onClick={() => setActiveForm("phone")}
onUpdate={() => setActiveForm(undefined)}
onCancel={() => setActiveForm(undefined)}
>
<Input />
</SingleElementForm>
<SingleElementForm
useFormProps={{ id, resource: "users" }}
formProps={{ initialValues: { timezone } }}
style={{ borderBottom: "none" }}
icon={<GlobalOutlined className="tertiary" />}
state={getActiveForm("timezone")}
itemProps={{
name: "timezone",
label: "Timezone",
}}
view={<Text>{timezone}</Text>}
onClick={() => setActiveForm("timezone")}
onUpdate={() => setActiveForm(undefined)}
onCancel={() => setActiveForm(undefined)}
>
<Select
style={{ width: "100%" }}
options={timezoneOptions}
/>
</SingleElementForm>
</Card>
<Card
title={
<Space size={15}>
<SafetyCertificateOutlined />
<Text size="sm">Security</Text>
</Space>
}
headStyle={{ padding: "0 12px" }}
bodyStyle={{ padding: "0" }}
>
<SingleElementForm
useFormProps={{ id, resource: "users" }}
formProps={{ initialValues: { email } }}
icon={<MailOutlined className="tertiary" />}
state={getActiveForm("email")}
itemProps={{
name: "email",
label: "Email",
}}
view={<Text>{email}</Text>}
onClick={() => setActiveForm("email")}
onUpdate={() => setActiveForm(undefined)}
onCancel={() => setActiveForm(undefined)}
>
<Input />
</SingleElementForm>
</Card>
</div>
</Drawer>
);
};
4 changes: 2 additions & 2 deletions examples/app-crm/src/components/company/info-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ export const CompanyInfoForm = () => {
return (
<Card
title={
<Space>
<ShopOutlined />
<Space size={15}>
<ShopOutlined className="sm" />
<Text>Company info</Text>
</Space>
}
Expand Down
Loading

0 comments on commit e3b6ef0

Please sign in to comment.