Skip to content

Commit

Permalink
feat(app-crm): add users table to settings page (#4886)
Browse files Browse the repository at this point in the history
* feat(app-crm): add users table to settings page

* feat(app-crm): add company info to settings page
  • Loading branch information
alicanerdurmaz authored Aug 31, 2023
1 parent 73a9226 commit c1ec8c9
Show file tree
Hide file tree
Showing 6 changed files with 345 additions and 6 deletions.
3 changes: 1 addition & 2 deletions examples/app-crm/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,7 @@ import {
QuotesEditPage,
QuotesShowPage,
} from "./routes/quotes";
import { SettingsPage } from "./routes/administration/settings";
import { AuditLogPage } from "./routes/administration/audit-log";
import { SettingsPage, AuditLogPage } from "./routes/administration";

import "./utilities/init-dayjs";

Expand Down
1 change: 1 addition & 0 deletions examples/app-crm/src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ export * from "./participants";
export * from "./single-element-form";
export * from "./select-option-with-avatar";
export * from "./algolia-search";
export * from "./role-tag";
49 changes: 49 additions & 0 deletions examples/app-crm/src/components/role-tag/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import React, { FC } from "react";
import { User } from "../../interfaces/graphql";
import { Tag } from "antd";
import { TagProps } from "antd/lib";
import { CrownOutlined, StarOutlined, UserOutlined } from "@ant-design/icons";

type Props = {
role: User["role"];
};

export const RoleTag: FC<Props> = ({ role }) => {
const variants: {
[key in User["role"]]: {
color: TagProps["color"];
icon: React.ReactNode;
};
} = {
ADMIN: {
color: "red",
icon: <CrownOutlined />,
},
SALES_INTERN: {
color: "blue",
icon: <UserOutlined />,
},
SALES_PERSON: {
color: "geekblue",
icon: <UserOutlined />,
},
SALES_MANAGER: {
color: "cyan",
icon: <StarOutlined />,
},
};

const text = role.replace("_", " ").toLowerCase();

return (
<Tag
style={{
textTransform: "capitalize",
}}
color={variants[role].color}
icon={variants[role].icon}
>
{text}
</Tag>
);
};
2 changes: 2 additions & 0 deletions examples/app-crm/src/routes/administration/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./settings";
export * from "./audit-log";
23 changes: 23 additions & 0 deletions examples/app-crm/src/routes/administration/settings.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
.list {
display: flex;
flex-direction: column;
}

.listItem {
padding: 8px 16px;
display: flex;
align-items: flex-start;
gap: 12px;

border-bottom: 1px solid var(--gray-5, #d9d9d9);
&:last-child {
border-bottom: none;
}
}

.listItemContent {
flex: 1;
display: flex;
flex-direction: column;
align-items: flex-start;
}
273 changes: 269 additions & 4 deletions examples/app-crm/src/routes/administration/settings.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,274 @@
import React from "react";
import { getDefaultFilter } from "@refinedev/core";
import { FilterDropdown, useTable } from "@refinedev/antd";
import { Card, Col, Input, Row, Select, Space, Table } from "antd";
import {
EnvironmentOutlined,
GlobalOutlined,
MailOutlined,
PhoneOutlined,
SearchOutlined,
ShopOutlined,
TeamOutlined,
} from "@ant-design/icons";
import cn from "classnames";
import { CustomAvatar, RoleTag, Text } from "../../components";
import { User } from "../../interfaces/graphql";
import { Logo } from "../../components/logo";

import styles from "./settings.module.css";

export const SettingsPage = () => {
return (
<div>
<div>settings page</div>
</div>
<>
<Space
size={16}
style={{
width: "100%",
paddingBottom: "24px",
borderBottom: "1px solid #D9D9D9",
}}
>
<Logo width={96} height={96} />
<Text style={{ fontSize: "32px", fontWeight: 700 }}>
Globex Corporation
</Text>
</Space>
<Row
gutter={[32, 32]}
style={{
marginTop: 32,
}}
>
<Col span={16}>
<UsersTable />
</Col>
<Col span={8}>
<CompanyInfo />
</Col>
</Row>
</>
);
};

const roleOptions: {
label: string;
value: User["role"];
}[] = [
{
label: "Admin",
value: "ADMIN",
},
{
label: "Sales Intern",
value: "SALES_INTERN",
},
{
label: "Sales Person",
value: "SALES_PERSON",
},
{
label: "Sales Manager",
value: "SALES_MANAGER",
},
];

const UsersTable = () => {
const { tableProps, filters } = useTable<User>({
resource: "users",
sorters: {
initial: [
{
field: "createdAt",
order: "desc",
},
],
},
filters: {
initial: [
{
field: "jobTitle",
value: "",
operator: "contains",
},
{
field: "name",
value: "",
operator: "contains",
},
{
field: "status",
value: undefined,
operator: "in",
},
],
},
meta: {
fields: ["id", "name", "jobTitle", "role", "avatarUrl"],
},
});

return (
<Card
bodyStyle={{ padding: 0 }}
headStyle={{
borderBottom: "1px solid #D9D9D9",
marginBottom: "1px",
}}
title={
<Space size="middle">
<TeamOutlined />
<Text>Contacts</Text>
</Space>
}
extra={
<>
<Text className="tertiary">Total users: </Text>
<Text strong>
{tableProps?.pagination !== false &&
tableProps.pagination?.total}
</Text>
</>
}
>
<Table {...tableProps}>
<Table.Column<User>
dataIndex="name"
title="Name"
defaultFilteredValue={getDefaultFilter(
"name",
filters,
"contains",
)}
filterIcon={<SearchOutlined />}
filterDropdown={(props) => (
<FilterDropdown {...props}>
<Input placeholder="Search Name" />
</FilterDropdown>
)}
render={(_, record) => {
return (
<div
style={{
display: "flex",
alignItems: "center",
gap: "8px",
}}
>
<CustomAvatar
src={record.avatarUrl}
name={record.name}
/>
<Text>{record.name}</Text>
</div>
);
}}
/>
<Table.Column
dataIndex="jobTitle"
title="Title"
defaultFilteredValue={getDefaultFilter(
"jobTitle",
filters,
"contains",
)}
filterIcon={<SearchOutlined />}
filterDropdown={(props) => (
<FilterDropdown {...props}>
<Input placeholder="Search title" />
</FilterDropdown>
)}
/>
<Table.Column<User>
dataIndex="role"
title="Role"
defaultFilteredValue={getDefaultFilter(
"role",
filters,
"in",
)}
filterDropdown={(props) => (
<FilterDropdown {...props}>
<Select
style={{ width: "200px" }}
mode="multiple"
placeholder="Select Stage"
options={roleOptions}
/>
</FilterDropdown>
)}
render={(_, record) => {
return <RoleTag role={record.role} />;
}}
/>
</Table>
</Card>
);
};

const companyInfo = [
{
label: "Address",
value: "2158 Mount Tabor, Westbury, New York, USA 11590",
icon: <EnvironmentOutlined className="tertiary" />,
},
{
label: "Phone",
value: "+123 456 789 01 23",
icon: <PhoneOutlined className="tertiary" />,
},
{
label: "Email",
value: "[email protected]",
icon: <MailOutlined className="tertiary" />,
},
{
label: "Website",
value: "https://globexcorp.com",
icon: <GlobalOutlined className="tertiary" />,
},
];

export const CompanyInfo = () => {
return (
<Card
title={
<Space>
<ShopOutlined />
<Text>Company info</Text>
</Space>
}
headStyle={{
padding: "1rem",
}}
bodyStyle={{
padding: "0",
}}
style={{
maxWidth: "500px",
}}
>
<div className={styles.list}>
{companyInfo.map((item) => {
return (
<div key={item.label} className={styles.listItem}>
<div>{item.icon}</div>
<div className={styles.listItemContent}>
<Text size="xs" className="tertiary">
{item.label}
</Text>
<Text
className={cn(
styles.listItemContent,
"primary",
)}
>
{item.value}
</Text>
</div>
</div>
);
})}
</div>
</Card>
);
};

0 comments on commit c1ec8c9

Please sign in to comment.