Web: Components: filling-status-line

This commit is contained in:
Elyor Djalilov 2023-05-25 14:44:37 +05:00
parent 840ddd80c5
commit b5f0b25515
6 changed files with 326 additions and 246 deletions

View File

@ -1,211 +0,0 @@
import React, { useState } from "react";
import styled from "styled-components";
import ArrowReactSvgUrl from "PUBLIC_DIR/images/arrow.react.svg?url";
import IconButton from "../icon-button";
import Text from "../text";
import Box from "../box";
import Avatar from "../avatar";
const AccordionItem = styled.div`
width: 100%;
`;
const AccordionItemInfo = styled.div`
display: flex;
align-items: center;
justify-content: space-between;
cursor: pointer;
height: 38px;
padding: 18px 0;
.user-avatar {
padding 1px;
border: 2px solid ${(props) => (props.finished ? "#4781D1" : "#A3A9AE")};
border-radius: 50%;
}
.icon-button {
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transform: rotate(90deg);
}
.icon-button-rotate {
path {
fill: #4781d1;
}
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transform: rotate(270deg);
}
`;
const AccordionItemHistory = styled.div`
display: flex;
align-items: center;
justify-content: space-between;
padding-left: 15px;
`;
const AccordionItemDetailHistory = styled.div`
display: flex;
align-items: center;
justify-content: space-between;
padding-left: 15px;
`;
const ItemWrapper = styled.div`
display: flex;
align-items: center;
border-left: 2px ${(props) => (props.finished ? "solid" : "dashed")};
border-color: ${(props) => (props.finished ? "#4781D1" : "#A3A9AE")};
min-height: 40px;
margin: ${(props) => (props.finished ? "0" : "2px 0")};
.filled-status-text {
color: ${(props) => (props.finished ? "#4781D1" : "#657077")};
}
`;
const Accordion = ({
avatar,
displayName,
role,
startFillingStatus,
startFillingDate,
filledAndSignedStatus,
filledAndSignedDate,
returnedByUser,
returnedByUserDate,
comment,
finished,
}) => {
const [isOpen, setIsOpen] = useState(false);
return (
<AccordionItem>
<AccordionItemInfo finished={finished} onClick={() => setIsOpen(!isOpen)}>
<Box displayProp="flex" alignItems="center">
<Avatar
className="user-avatar"
size="min"
role="user"
source={avatar}
userName={displayName}
/>
<Box
displayProp="flex"
flexDirection="column"
marginProp="0 0 0 10px"
>
<Text
className="accordion-displayname"
fontSize="14px"
color="#333333"
lineHeight="16px"
fontWeight="bold"
>
{displayName}
</Text>
<Text
as="span"
className="accordion-role"
fontSize="12px"
color="#657077"
lineHeight="16px"
>
{role}
</Text>
</Box>
</Box>
<IconButton
className={isOpen ? "icon-button-rotate" : "icon-button"}
size={16}
iconName={ArrowReactSvgUrl}
/>
</AccordionItemInfo>
<AccordionItemHistory>
<ItemWrapper finished={finished}>
<Text
fontSize="12px"
lineHeight="16px"
className="filled-status-text"
style={{ marginLeft: "15px" }}
>
{filledAndSignedStatus}
</Text>
</ItemWrapper>
<Text fontSize="12px" lineHeight="16px" color="#657077">
{filledAndSignedDate}
</Text>
</AccordionItemHistory>
{isOpen && (
<>
<AccordionItemDetailHistory>
<ItemWrapper finished={finished}>
<Text
fontSize="12px"
lineHeight="16px"
color="#657077"
className="status-text"
style={{ marginLeft: "15px" }}
>
{startFillingStatus}
</Text>
</ItemWrapper>
<Text fontSize="12px" lineHeight="16px" color="#657077">
{startFillingDate}
</Text>
</AccordionItemDetailHistory>
{returnedByUser && (
<AccordionItemDetailHistory>
<ItemWrapper finished={finished}>
<Text
fontSize="12px"
lineHeight="16px"
color="#657077"
className="status-text"
style={{ marginLeft: "15px" }}
>
{returnedByUser}
</Text>
</ItemWrapper>
<Text fontSize="12px" lineHeight="16px" color="#657077">
{returnedByUserDate}
</Text>
</AccordionItemDetailHistory>
)}
{comment && (
<AccordionItemDetailHistory>
<ItemWrapper finished={finished}>
<Text
fontSize="12px"
lineHeight="16px"
color="#657077"
className="status-text"
style={{ marginLeft: "15px" }}
>
{comment}
</Text>
</ItemWrapper>
</AccordionItemDetailHistory>
)}
</>
)}
</AccordionItem>
);
};
export default Accordion;

View File

@ -0,0 +1,148 @@
import React, { useState } from "react";
import { ReactSVG } from "react-svg";
import { AccordionItem } from "./styled-filling-status-line";
import ArrowReactSvgUrl from "PUBLIC_DIR/images/arrow.react.svg?url";
import Text from "../text";
import Box from "../box";
import Avatar from "../avatar";
const FillingStatusAccordion = ({
avatar,
displayName,
role,
startFilling,
startFillingDate,
filledAndSigned,
filledAndSignedDate,
returnedByUser,
returnedDate,
comment,
isDone,
isInterrupted,
}) => {
const [isOpen, setIsOpen] = useState(false);
const onClickHandler = () => {
setIsOpen((prev) => !prev);
};
return (
<AccordionItem
isOpen={isOpen}
isDone={isDone}
isInterrupted={isInterrupted}
>
<div className="accordion-item-info" onClick={onClickHandler}>
<Box displayProp="flex" alignItems="center">
<Avatar
className="user-avatar"
size="min"
role="user"
source={avatar}
userName={displayName}
/>
<Box
displayProp="flex"
flexDirection="column"
marginProp="0 0 0 10px"
>
<Text
className="accordion-displayname"
fontSize="14px"
lineHeight="16px"
fontWeight="bold"
>
{displayName}
</Text>
<Text
as="span"
className="accordion-role"
fontSize="12px"
lineHeight="16px"
>
{role}
</Text>
</Box>
</Box>
<ReactSVG src={ArrowReactSvgUrl} className="arrow-icon" />
</div>
{isOpen ? (
<>
<div className="accordion-item-history">
<div className="accordion-item-wrapper">
<Text fontSize="12px" lineHeight="16px" className="status-text">
{startFilling}
</Text>
</div>
<Text fontSize="12px" lineHeight="16px" className="status-date">
{startFillingDate}
</Text>
</div>
{returnedByUser && (
<div className="accordion-item-history">
<div className="accordion-item-wrapper">
<Text fontSize="12px" lineHeight="16px" className="status-text">
{returnedByUser}
</Text>
</div>
<Text fontSize="12px" lineHeight="16px" className="status-date">
{returnedDate}
</Text>
</div>
)}
{comment && (
<div className="accordion-item-history">
<div className="accordion-item-wrapper">
<Text fontSize="12px" lineHeight="16px" className="status-text">
{comment}
</Text>
</div>
</div>
)}
{isDone && (
<div className="accordion-item-history">
<div className="accordion-item-wrapper">
<Text
fontSize="12px"
lineHeight="16px"
className="filled-status-text"
>
{filledAndSigned}
</Text>
</div>
<Text fontSize="12px" lineHeight="16px" className="status-date">
{filledAndSignedDate}
</Text>
</div>
)}
</>
) : (
<div className="accordion-item-history">
<div className="accordion-item-wrapper">
<Text
fontSize="12px"
lineHeight="16px"
className="filled-status-text"
>
{filledAndSigned}
</Text>
</div>
<Text fontSize="12px" lineHeight="16px" className="status-date">
{filledAndSignedDate}
</Text>
</div>
)}
</AccordionItem>
);
};
export default FillingStatusAccordion;

View File

@ -1,46 +1,97 @@
import React from "react";
import Accordion from "./accordion.js";
import PropTypes from "prop-types";
import { ReactSVG } from "react-svg";
import { mockData } from "./mockData.js";
import { FillingStatusContainer } from "./styled-filling-status-line.js";
import FillingStatusAccordion from "./filling-status-accordion.js";
import StatusDoneReactSvgUrl from "PUBLIC_DIR/images/done.react.svg?url";
import StatusInterruptedSvgUrl from "PUBLIC_DIR/images/interrupted.react.svg?url";
import DoneReactSvg from "PUBLIC_DIR/images/done.react.svg";
import { StyledFillingStatusContainer } from "./styled-filling-status-line.js";
import Text from "../text";
import Box from "../box";
import { Data } from "./data.js";
const FillingStatusLine = () => {
const FillingStatusLine = ({
statusDoneText,
statusInterruptedText,
statusDone,
statusInterrupted,
}) => {
return (
<StyledFillingStatusContainer>
{Data.map((data) => {
<FillingStatusContainer
isDone={statusDone}
isInterrupted={statusInterrupted}
>
{mockData.map((data) => {
return (
<Accordion
<FillingStatusAccordion
key={data.id}
displayName={data.displayName}
avatar={data.avatar}
role={data.role}
startFillingStatus={data.startFillingStatus}
startFilling={data.startFillingStatus}
startFillingDate={data.startFillingDate}
filledAndSignedStatus={data.filledAndSignedStatus}
filledAndSigned={data.filledAndSignedStatus}
filledAndSignedDate={data.filledAndSignedDate}
returnedByUser={data.returnedByUser}
returnedByUserDate={data.returnedByUserDate}
returnedDate={data.returnedByUserDate}
comment={data.comment}
avatar={data.avatar}
finished={data.finished}
isDone={statusDone}
isInterrupted={statusInterrupted}
/>
);
})}
<Box displayProp="flex" alignItems="center" marginProp="15px 0 0">
<DoneReactSvg className="done-icon" />
<Text
fontSize="14px"
lineHeight="16px"
color="#A3A9AE"
fontWeight="bold"
>
Done
</Text>
</Box>
</StyledFillingStatusContainer>
{statusInterrupted ? (
<Box displayProp="flex" alignItems="center" marginProp="15px 0 0">
<ReactSVG
src={StatusInterruptedSvgUrl}
className="status-interrupted-icon"
/>
<Text
fontSize="14px"
lineHeight="16px"
fontWeight="bold"
className="status-interrupted-text"
>
{statusInterruptedText}
</Text>
</Box>
) : (
<Box displayProp="flex" alignItems="center" marginProp="15px 0 0">
<ReactSVG src={StatusDoneReactSvgUrl} className="status-done-icon" />
<Text
fontSize="14px"
lineHeight="16px"
fontWeight="bold"
className="status-done-text"
>
{statusDoneText}
</Text>
</Box>
)}
</FillingStatusContainer>
);
};
FillingStatusLine.propTypes = {
/** Accepts id */
id: PropTypes.string,
/** Accepts class */
className: PropTypes.string,
/** Filling status done text*/
statusDoneText: PropTypes.string,
/** Filling status interrupted text*/
statusInterruptedText: PropTypes.string,
/** Filling status done*/
statusDone: PropTypes.bool,
/** Filling status interrupted*/
statusInterrupted: PropTypes.bool,
};
FillingStatusLine.defaultProps = {
statusDoneText: "Done",
statusInterruptedText: "Interrupted",
statusDone: true,
statusInterrupted: false,
};
export default FillingStatusLine;

View File

@ -1,4 +1,4 @@
export const Data = [
export const mockData = [
{
id: 0,
displayName: "Lydia Calzoni",
@ -9,10 +9,8 @@ export const Data = [
filledAndSignedDate: "26.01.2023 13:56",
returnedByUser: "Returned by Teacher",
returnedByUserDate: "25.01.2023 13:56",
comment:
"The registration block is filled in incorrectly. It is necessary to specify the user ID, and the email is specified. The user ID can be viewed on the profile page.",
comment: "The registration block is filled in incorrectly. It is necessary to specify the user ID, and the email is specified. The user ID can be viewed on the profile page.",
avatar: null,
finished: true,
},
{
id: 1,
@ -26,7 +24,6 @@ export const Data = [
returnedByUserDate: "22.01.2023 13:56",
comment: null,
avatar: null,
finished: true,
},
{
id: 2,
@ -40,6 +37,5 @@ export const Data = [
returnedByUserDate: null,
comment: null,
avatar: null,
finished: false,
},
];

View File

@ -1,13 +1,105 @@
import styled from "styled-components";
export const StyledFillingStatusContainer = styled.div`
const FillingStatusContainer = styled.div`
width: 100%;
max-width: 425px;
padding: 10px;
.done-icon {
width: 32px;
height: 32px;
.status-done-text {
color: ${(props) => (props.isDone ? "#4781D1" : "#A3A9AE")};
}
.status-done-icon {
circle,
path {
stroke: ${(props) => (props.isDone ? "#4781D1" : "#A3A9AE")};
}
}
.status-interrupted-text {
color: ${(props) => props.isInterrupted && "#F2675A"};
}
.status-interrupted-icon {
circle,
path {
stroke: ${(props) => props.isInterrupted && "#F2675A"};
}
}
.status-done-icon,
.status-interrupted-icon {
margin-right: 10px;
}
`;
const AccordionItem = styled.div`
width: 100%;
.accordion-item-info {
display: flex;
align-items: center;
justify-content: space-between;
cursor: pointer;
height: 38px;
padding: 18px 0;
.user-avatar {
padding 1px;
border: 2px solid #A3A9AE;
border-color: ${(props) => (props.isDone && "#4781D1") || (props.isInterrupted && "#F2675A")};
border-radius: 50%;
}
.accordion-displayname {
color: #333333;
}
.accordion-role {
color: #657077;
}
.arrow-icon {
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transform: ${(props) => props.isOpen ? "rotate(270deg)" : "rotate(90deg)"};
path {
fill: ${(props) => (props.isOpen ? "#4781d1" : "#A3A9AE")};
}
}
}
.accordion-item-history {
display: flex;
align-items: center;
justify-content: space-between;
padding-left: 15px;
}
.accordion-item-wrapper {
display: flex;
align-items: center;
min-height: 40px;
margin: ${(props) => (props.isDone || props.isInterrupted ? "0" : "2px 0")};
border-left: 2px ${(props) => props.isDone || props.isInterrupted ? "solid" : "dashed"} #A3A9AE;
border-color: ${(props) => (props.isDone && "#4781D1") || (props.isInterrupted && "#F2675A")};
.status-text {
margin-left: 15px;
color: #657077;
}
.status-date {
color: #657077;
}
.filled-status-text {
margin-left: 15px;
color: ${(props) => (props.isDone ? "#4781D1" : "#657077")};
}
}
`;
export { FillingStatusContainer, AccordionItem };

View File

@ -0,0 +1,4 @@
<svg width="38" height="38" viewBox="0 0 38 38" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="19" cy="19" r="18" stroke="#F2675A" stroke-width="2"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M23.2929 13.2929C23.6834 12.9024 24.3166 12.9024 24.7071 13.2929C25.0976 13.6834 25.0976 14.3166 24.7071 14.7071L20.4142 19L24.7071 23.2929C25.0976 23.6834 25.0976 24.3166 24.7071 24.7071C24.3166 25.0976 23.6834 25.0976 23.2929 24.7071L19 20.4142L14.7071 24.7071C14.3166 25.0976 13.6834 25.0976 13.2929 24.7071C12.9024 24.3166 12.9024 23.6834 13.2929 23.2929L17.5858 19L13.2929 14.7071C12.9024 14.3166 12.9024 13.6834 13.2929 13.2929C13.6834 12.9024 14.3166 12.9024 14.7071 13.2929L19 17.5858L23.2929 13.2929Z" fill="#F2675A"/>
</svg>

After

Width:  |  Height:  |  Size: 747 B