feat: lots of updates
This commit is contained in:
@@ -0,0 +1,168 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import toast from "react-hot-toast";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useSelector } from "react-redux";
|
||||
import Modal from "../Modal";
|
||||
import ChannelIcon from "../ChannelIcon";
|
||||
import Contact from "../Contact";
|
||||
import StyledWrapper from "./styled";
|
||||
import useFilteredUsers from "../../hook/useFilteredUsers";
|
||||
import { useGetChannelsQuery } from "../../../app/services/channel";
|
||||
import { useCreateChannelMutation } from "../../../app/services/channel";
|
||||
|
||||
export default function ChannelModal({ personal = false, closeModal }) {
|
||||
const navigateTo = useNavigate();
|
||||
const [data, setData] = useState({
|
||||
name: "",
|
||||
dsecription: "",
|
||||
members: [],
|
||||
is_public: !personal,
|
||||
});
|
||||
const { contacts, input, updateInput } = useFilteredUsers();
|
||||
const { refetch: refetchChannels } = useGetChannelsQuery();
|
||||
const [
|
||||
createChannel,
|
||||
{ isSuccess, isError, isLoading, data: newChannel },
|
||||
] = useCreateChannelMutation();
|
||||
const currentUser = useSelector((state) => {
|
||||
return state.authData.user;
|
||||
});
|
||||
const handleToggle = () => {
|
||||
const { is_public } = data;
|
||||
setData((prev) => {
|
||||
return { ...prev, is_public: !is_public };
|
||||
});
|
||||
};
|
||||
const handleCreate = () => {
|
||||
if (!data.name) {
|
||||
toast("please input channel name");
|
||||
return;
|
||||
}
|
||||
createChannel(data);
|
||||
};
|
||||
useEffect(() => {
|
||||
if (isError) {
|
||||
toast.error("create new channel failed");
|
||||
}
|
||||
}, [isError]);
|
||||
useEffect(() => {
|
||||
if (isSuccess) {
|
||||
toast.success("create new channel success");
|
||||
closeModal();
|
||||
refetchChannels();
|
||||
navigateTo(`/chat/channel/${newChannel.gid}`);
|
||||
}
|
||||
}, [isSuccess, newChannel]);
|
||||
|
||||
const handleNameInput = (evt) => {
|
||||
setData((prev) => {
|
||||
return { ...prev, name: evt.target.value };
|
||||
});
|
||||
};
|
||||
const handleInputChange = (evt) => {
|
||||
updateInput(evt.target.value);
|
||||
};
|
||||
const toggleCheckMember = ({ currentTarget }) => {
|
||||
const { members } = data;
|
||||
const { uid } = currentTarget.dataset;
|
||||
let tmp = members.includes(+uid)
|
||||
? members.filter((m) => m != uid)
|
||||
: [...members, +uid];
|
||||
console.log(uid, currentTarget);
|
||||
setData((prev) => {
|
||||
return { ...prev, members: tmp };
|
||||
});
|
||||
console.log({ data });
|
||||
};
|
||||
console.log("contacts", contacts);
|
||||
if (!currentUser) return null;
|
||||
const { name, members, is_public } = data;
|
||||
return (
|
||||
<Modal>
|
||||
<StyledWrapper>
|
||||
{!is_public && (
|
||||
<div className="left">
|
||||
<div className="search">
|
||||
<input
|
||||
value={input}
|
||||
onChange={handleInputChange}
|
||||
placeholder="Type username to search"
|
||||
/>
|
||||
</div>
|
||||
{contacts && (
|
||||
<ul className="users">
|
||||
{contacts.map((u) => {
|
||||
const { uid } = u;
|
||||
const checked = members.includes(uid);
|
||||
console.log({ checked });
|
||||
return (
|
||||
<li
|
||||
key={uid}
|
||||
data-uid={uid}
|
||||
className="user"
|
||||
onClick={toggleCheckMember}
|
||||
>
|
||||
<input
|
||||
readOnly
|
||||
checked={checked}
|
||||
type="checkbox"
|
||||
name="cb"
|
||||
id="cb"
|
||||
/>
|
||||
<Contact uid={uid} interactive={false} />
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<div className={`right ${!is_public ? "private" : ""}`}>
|
||||
<h3 className="title">Create New Channel</h3>
|
||||
<p className="desc normal">
|
||||
{!is_public
|
||||
? "This is a private channel, only select members will bee able to join."
|
||||
: "This is a public channel, everyone in this team can see it."}
|
||||
</p>
|
||||
<div className="name">
|
||||
<span className="label normal">Channel Name</span>
|
||||
<div className="input">
|
||||
<input
|
||||
onChange={handleNameInput}
|
||||
value={name}
|
||||
placeholder="new channel"
|
||||
/>
|
||||
<ChannelIcon personal={!is_public} className="icon" />
|
||||
</div>
|
||||
</div>
|
||||
{/* admin or */}
|
||||
{
|
||||
<div className="private">
|
||||
<span className="txt normal">Private Channel</span>
|
||||
<input
|
||||
disabled={!currentUser?.is_admin}
|
||||
onChange={handleToggle}
|
||||
checked={!is_public}
|
||||
type="checkbox"
|
||||
name="private"
|
||||
id="private"
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
<div className="btns">
|
||||
<button onClick={closeModal} className="btn normal cancel">
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
disabled={isLoading}
|
||||
onClick={handleCreate}
|
||||
className="btn normal create"
|
||||
>
|
||||
Create
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</StyledWrapper>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
import styled from "styled-components";
|
||||
|
||||
const StyledWrapper = styled.div`
|
||||
display: flex;
|
||||
/* max-width: 604px; */
|
||||
max-height: 402px;
|
||||
background: #fff;
|
||||
box-shadow: 0px 25px 50px rgba(31, 41, 55, 0.25);
|
||||
border-radius: 8px;
|
||||
transition: all 0.5s ease;
|
||||
.left {
|
||||
width: 260px;
|
||||
height: 100%;
|
||||
box-shadow: inset -1px 0px 0px rgba(0, 0, 0, 0.1);
|
||||
overflow-y: scroll;
|
||||
.search {
|
||||
box-shadow: 0px 1px 0px rgba(0, 0, 0, 0.1);
|
||||
padding: 8px;
|
||||
width: -webkit-fill-available;
|
||||
input {
|
||||
outline: none;
|
||||
width: -webkit-fill-available;
|
||||
padding: 8px;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
.users {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 260px;
|
||||
padding-bottom: 20px;
|
||||
overflow-y: scroll;
|
||||
.user {
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 16px;
|
||||
width: -webkit-fill-available;
|
||||
> div {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.right {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 32px;
|
||||
box-sizing: border-box;
|
||||
&.private {
|
||||
width: 344px;
|
||||
.desc {
|
||||
text-align: center;
|
||||
/* padding: 0 20px; */
|
||||
}
|
||||
}
|
||||
> .title {
|
||||
font-weight: 600;
|
||||
font-size: 20px;
|
||||
line-height: 30px;
|
||||
color: #374151;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.desc {
|
||||
font-weight: normal;
|
||||
color: #6b7280;
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
.name {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
gap: 8px;
|
||||
margin-bottom: 34px;
|
||||
.label {
|
||||
font-weight: 600;
|
||||
color: #6b7280;
|
||||
}
|
||||
.input {
|
||||
position: relative;
|
||||
input {
|
||||
width: -webkit-fill-available;
|
||||
border: 1px solid #e5e7eb;
|
||||
box-shadow: 0px 1px 2px rgba(31, 41, 55, 0.08);
|
||||
border-radius: 4px;
|
||||
padding: 8px;
|
||||
color: #78787c;
|
||||
padding-left: 36px;
|
||||
}
|
||||
.icon {
|
||||
position: absolute;
|
||||
left: 8px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
}
|
||||
}
|
||||
.private {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 50px;
|
||||
.txt {
|
||||
font-weight: 600;
|
||||
color: #6b7280;
|
||||
}
|
||||
input {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.btns {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
gap: 16px;
|
||||
.btn {
|
||||
cursor: pointer;
|
||||
padding: 8px 16px;
|
||||
background: none;
|
||||
border: 1px solid #e5e7eb;
|
||||
box-shadow: 0px 1px 2px rgba(31, 41, 55, 0.08);
|
||||
border-radius: 4px;
|
||||
font-weight: 500;
|
||||
color: #374151;
|
||||
&.create {
|
||||
border: none;
|
||||
background: #1fe1f9;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
.normal {
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
}
|
||||
}
|
||||
`;
|
||||
export default StyledWrapper;
|
||||
Reference in New Issue
Block a user