Skip to content

Commit

Permalink
feat(flat-components): add InviteModal and RemoveDetailModal (#618)
Browse files Browse the repository at this point in the history
  • Loading branch information
Cheerego7 committed May 10, 2021
1 parent 7dda7ef commit a7f2b4f
Show file tree
Hide file tree
Showing 5 changed files with 319 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React from "react";
import { Meta, Story } from "@storybook/react";
import { InviteModal, InviteModalProps } from ".";
import { RoomStatus, RoomType } from "../../types/room";
import { message } from "antd";

const storyMeta: Meta = {
title: "Components/InviteModal",
component: InviteModal,
};

export default storyMeta;

export const Overview: Story<InviteModalProps> = args => (
<div className="vh-75 mw8-ns">
<InviteModal {...args} />
</div>
);
Overview.args = {
visible: true,
room: {
roomUUID: "roomUUID",
ownerUUID: "ownerUUID",
title: "RoomDetailTitle",
roomType: RoomType.BigClass,
roomStatus: RoomStatus.Started,
beginTime: 1619771930756,
endTime: 1619775530756,
},
userName: "Flat",
onCopy: () => {
message.success("复制成功");
},
onCancel: () => {},
};
69 changes: 69 additions & 0 deletions packages/flat-components/src/components/InviteModal/index.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
.invite-modal {
.ant-modal-content {
border-radius: 8px;
}

.ant-modal-footer {
button {
border-radius: 4px;
}
}
}

.invite-modal-header {
margin-top: -5px;
width: 100%;

span {
display: block;
font-size: 14px;
font-family: PingFangSC-Medium, PingFang SC, serif;

&:first-of-type {
margin-bottom: 8px;
color: #444e60;
font-weight: 500;
font-size: 16px;
}

&:last-of-type {
color: #7a7b7c;
padding-bottom: 16px;
border-bottom: 1px solid #dbe1ea;
}
}
}

.invite-modal-content {
margin-top: 23px;
}

.invite-modal-content-item {
display: flex;

span {
display: inline-block;

&:first-of-type {
flex: 1;
min-width: 25%;
color: #7a7b7c;
}

&:last-of-type {
flex: auto;
text-align: right;
}
}

&:not(:last-of-type) {
margin-bottom: 8px;
}
}

.invite-modal-content-title {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
word-break: keep-all;
}
98 changes: 98 additions & 0 deletions packages/flat-components/src/components/InviteModal/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import "./index.less";

import React, { useMemo } from "react";
import { Modal } from "antd";
import { differenceInCalendarDays, format } from "date-fns/fp";
import { RoomInfo, Week } from "../../types/room";
import { getWeekNames } from "../../utils/room";

const completeTimeFormat = format("yyyy-MM-dd HH:mm");
const onlySuffixTimeFormat = format("HH:mm");

export interface InviteModalProps {
visible: boolean;
room: RoomInfo;
weeks?: Week[];
userName: string;
onCopy: (text: string) => void;
onCancel: () => void;
}

export const InviteModal: React.FC<InviteModalProps> = ({
visible,
room,
weeks,
userName,
onCopy,
onCancel,
}) => {
const { beginTime, endTime, periodicUUID, roomUUID, title } = room;
const uuid = periodicUUID || roomUUID;

const formattedTimeRange = useMemo<string>(() => {
if (!beginTime || !endTime) {
return "";
}

const formatBeginTime = completeTimeFormat(beginTime!);
const formatEndTime =
differenceInCalendarDays(beginTime!, endTime!) !== 0
? completeTimeFormat(endTime!)
: onlySuffixTimeFormat(endTime!);

return `${formatBeginTime}~${formatEndTime}`;
}, [beginTime, endTime]);

const onCopyClicked = (): void => {
const basePrefixText =
`${userName} 邀请你加入 Flat 房间\n` +
`房间主题:${title}\n` +
(formattedTimeRange ? `开始时间:${formattedTimeRange}\n` : "");
const baseSuffixText =
`\n房间号:${uuid}\n\n` +
`打开(没有安装的话请先下载并安装)并登录 Flat,点击加入房间,输入房间号即可加入和预约`;

if (periodicUUID) {
const content = weeks ? `重复周期:${getWeekNames(weeks || [])}` : "";

onCopy(`${basePrefixText}${content}${baseSuffixText}`);
} else {
onCopy(`${basePrefixText}${baseSuffixText}`);
}
};

return (
<Modal
width={460}
visible={visible}
onOk={onCopyClicked}
onCancel={onCancel}
okText="复制"
cancelText="取消"
className="invite-modal"
>
<div className="invite-modal-header">
<span>{userName} 邀请加入 FLAT 房间</span>
<span>可通过房间号加入和预约</span>
</div>
<div className="invite-modal-content">
<div className="invite-modal-content-item">
<span>房间主题</span>
<span className="invite-modal-content-title">{title}</span>
</div>
<div className="invite-modal-content-item">
<span>房间号</span>
<span style={{ userSelect: "text" }}>{uuid}</span>
</div>
{formattedTimeRange && (
<div className="invite-modal-content-item">
<span>开始时间</span>
<span>{formattedTimeRange}</span>
</div>
)}
</div>
{/* @TODO Add invite URL */}
{/*<Input type="text" placeholder="https://netless.link/url/5f2259d5069bc052d2" />*/}
</Modal>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React from "react";
import { Meta, Story } from "@storybook/react";
import { RemoveRoomModal, RemoveRoomModalProps } from ".";

const storyMeta: Meta = {
title: "Components/RemoveRoomModal",
component: RemoveRoomModal,
};

export default storyMeta;

export const Overview: Story<RemoveRoomModalProps> = args => (
<div className="vh-75 mw8-ns">
<RemoveRoomModal {...args} />
</div>
);
Overview.args = {
cancelModalVisible: true,
isCreator: true,
roomUUID: "roomUUID",
periodicUUID: "periodicUUID",
isPeriodicDetailsPage: true,
onCancel: () => {},
onCancelRoom: () => {},
};
92 changes: 92 additions & 0 deletions packages/flat-components/src/components/RemoveRoomModal/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { Button, Checkbox, Modal } from "antd";
import React, { useState } from "react";

export interface RemoveRoomModalProps {
cancelModalVisible: boolean;
isCreator: boolean;
roomUUID?: string;
periodicUUID?: string;
isPeriodicDetailsPage: boolean;
onCancel: () => void;
onCancelRoom: () => void;
}

export const RemoveRoomModal: React.FC<RemoveRoomModalProps> = ({
cancelModalVisible,
isCreator,
roomUUID,
periodicUUID,
isPeriodicDetailsPage,
onCancel,
onCancelRoom,
}) => {
const [isCancelAll, setIsCancelAll] = useState(false);
const isPeriodicRoom = !!periodicUUID && !roomUUID;
const isSubPeriodicRoom = periodicUUID && roomUUID;

const title = (() => {
if (!isCreator) {
return "移除房间";
}

if (isPeriodicRoom && isPeriodicDetailsPage) {
return "取消周期性房间";
}

return "取消房间";
})();

const content = (): React.ReactElement => {
if (!periodicUUID) {
if (isCreator) {
return <span>确定取消该房间?取消后其他成员将无法加入。</span>;
}

return <span>确定从房间列表移除该房间?移除后可通过房间号再次加入。</span>;
}

if (!isCreator) {
return <span>确定从房间列表中移除该系列周期性房间?移除后可通过房间号再次加入。</span>;
}

if (!isPeriodicDetailsPage) {
return (
<>
<span>确定取消该房间?</span>
<br />
<br />
<Checkbox
checked={isCancelAll}
onChange={e => setIsCancelAll(e.target.checked)}
>
同时取消该系列周期性房间
</Checkbox>
</>
);
}

if (isSubPeriodicRoom) {
return <span>确定将此房间从该周期性房间中取消?取消后其他成员将无法加入。</span>;
}

return <span>确定取消该周期性房间?取消后其他成员将无法加入。</span>;
};

return (
<Modal
visible={cancelModalVisible}
title={title}
onCancel={onCancel}
footer={[
<Button key="Cancel" onClick={onCancel}>
{isCreator ? "再想想" : "取消"}
</Button>,
<Button key="Ok" type="primary" onClick={onCancelRoom}>
确定
</Button>,
]}
>
{content()}
</Modal>
);
};

0 comments on commit a7f2b4f

Please sign in to comment.