+
);
@@ -110,6 +135,8 @@ const UsersFeedback = ({
UsersFeedback.propTypes = {
dispatch: PropTypes.func.isRequired,
fullWidth: PropTypes.bool,
+ isOpenUserFeedback: PropTypes.bool,
+ onOpenUserFeedback: PropTypes.func,
sendFeedback: PropTypes.func.isRequired,
state: PropTypes.object.isRequired,
};
diff --git a/src/client/src/components/UsersFeedback/usersFeedback.scss b/src/client/src/components/UsersFeedback/usersFeedback.scss
index 9e44973d4..ad6e515e5 100644
--- a/src/client/src/components/UsersFeedback/usersFeedback.scss
+++ b/src/client/src/components/UsersFeedback/usersFeedback.scss
@@ -16,7 +16,7 @@
&__panel {
background: $white;
- border: $border-grey-light;
+ border: 1px solid #dfdff1;
}
&__useful {
@@ -24,13 +24,17 @@
justify-content: space-between;
align-items: center;
padding: $spacing-2 $spacing-4;
- font-size: 1.2rem;
+ font-size: 1.75rem;
+ font-family: "Marianne", sans-serif;
+ font-style: normal;
font-weight: bold;
color: $white;
- background: $primary;
+ background: $dark-blue;
+ cursor: pointer;
- legend {
+ .legend-text {
font-size: $font-size-base;
+ cursor: pointer !important;
}
}
@@ -61,16 +65,59 @@
}
}
}
-
+ .icon {
+ background: transparent;
+ border: none;
+ width: 2rem;
+ height: 2rem;
+ cursor: pointer;
+ }
+ .question {
+ margin: $spacing-4 0;
+ padding: $spacing-2 0;
+ font-size: $font-size-base-small;
+ color: $dark-grey;
+ font-family: $marianne;
+ font-weight: bold;
+ line-height: 1.5rem;
+ }
+ .yes-no-btns {
+ display: flex;
+ align-items: center;
+ padding: $spacing-4 0;
+ gap: $spacing-2;
+ button {
+ color: $dark-blue;
+ padding: 4px 10px;
+ font-size: 1rem;
+ font-family: $marianne;
+ font-weight: 400;
+ background: #e5e5f4;
+ line-height: 1.5rem;
+ border-radius: 6px;
+ border: none;
+ cursor: pointer;
+ }
+ .active {
+ border: 2px solid $dark-blue;
+ }
+ button:hover {
+ border: 2px solid $dark-blue;
+ border-style: dashed;
+ }
+ }
&__comment {
padding: $spacing-4;
+ font-size: $font-size-base-small;
+ color: $dark-grey;
+ font-family: $marianne;
label {
font-weight: bold;
}
textarea {
- margin-bottom: $spacing-4;
+ margin: $spacing-4 0;
}
}
@@ -89,6 +136,8 @@
&__rates {
display: flex;
flex-wrap: wrap;
+ padding: 1rem 0;
+ gap: 0.5rem;
}
&__rate {
@@ -115,18 +164,20 @@
align-items: center;
width: 2.5rem;
height: 2.5rem;
+ color: $dark-blue !important;
border: $border-grey-light;
- border-radius: $border-radius-1;
- background-color: $grey-geyser;
+ border-radius: 6px;
+ background: #e5e5f4;
+ font-family: $marianne;
cursor: pointer;
transition: background-color $duration-2;
- // gradient colors for each rate from 0 to 10
- // SASS list index starts at 1, to start with 0 : index - 1
- @each $current-color in $rating-gradient {
- &--#{index($rating-gradient, $current-color) - 1} {
- background-color: $current-color;
- }
+ &.active {
+ border: 2px solid $dark-blue;
+ }
+ &:hover {
+ border: 2px solid $dark-blue;
+ border-style: dashed;
}
}
}
@@ -136,7 +187,19 @@
justify-content: flex-end;
.button {
- border: $border-grey-light;
+ font-size: 1rem;
+ line-height: 1.2rem;
+ color: white;
+ font-weight: 400;
+ background-color: $dark-blue;
+ }
+ .button:hover{
+ color: white;
+ font-weight: 500;
+ }
+ .button:disabled{
+ color: $dark-blue;
+ background-color: #dfdff1;
}
}
}
diff --git a/src/client/src/components/shared/Badge/Badge.scss b/src/client/src/components/shared/Badge/Badge.scss
new file mode 100644
index 000000000..b07b61513
--- /dev/null
+++ b/src/client/src/components/shared/Badge/Badge.scss
@@ -0,0 +1,38 @@
+@import "../../App/variables";
+
+.badge {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 0rem 0.5rem 0rem 0.25rem;
+ border-radius: 0.25rem;
+ gap: 0.25rem;
+ font-size: $font-size-base-small;
+ font-family: $marianne;
+ line-height: 1.5rem;
+ text-transform: uppercase;
+ font-weight: bold;
+ max-width: 100px;
+ &__small-text {
+ font-size: 0.75rem !important;
+ font-weight: 700 !important;
+ }
+ &__span {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
+ &__icon--success {
+ background: #b8fec9;
+ color: #18753c;
+ }
+ &__icon--danger {
+ color: #ce0500;
+ background: #ffe9e9;
+ }
+ .badge-icon {
+ display: inline-flex;
+ align-items: center;
+ margin-right: 0.5rem;
+ }
+}
diff --git a/src/client/src/components/shared/Badge/BadgeWithIcon.jsx b/src/client/src/components/shared/Badge/BadgeWithIcon.jsx
new file mode 100644
index 000000000..7fcac3098
--- /dev/null
+++ b/src/client/src/components/shared/Badge/BadgeWithIcon.jsx
@@ -0,0 +1,28 @@
+import "./Badge.scss";
+
+import PropTypes from "prop-types";
+import React from "react";
+
+import ClosedIcon from "../Icons/ClosedIcon.jsx";
+import OpenedIcon from "../Icons/OpenedIcon.jsx";
+
+const BadgeWithIcon = ({ text, state, isTableBadge = false }) => {
+ return (
+
+
+ {state === "icon--success" ? : }
+
+ {text && (
+
+ {text}
+
+ )}
+
+ );
+};
+BadgeWithIcon.propTypes = {
+ isTableBadge: PropTypes.bool,
+ state: PropTypes.string.isRequired,
+ text: PropTypes.string.isRequired,
+};
+export default BadgeWithIcon;
diff --git a/src/client/src/components/shared/Button/ButtonLink.js b/src/client/src/components/shared/Button/ButtonLink.js
index 733f09e6c..39f71ab36 100644
--- a/src/client/src/components/shared/Button/ButtonLink.js
+++ b/src/client/src/components/shared/Button/ButtonLink.js
@@ -4,9 +4,11 @@ import PropTypes from "prop-types";
import React from "react";
const ButtonLink = ({ children, onClick }) => (
-
+
+
+
);
ButtonLink.propTypes = {
diff --git a/src/client/src/components/shared/Button/button-link.scss b/src/client/src/components/shared/Button/button-link.scss
index ebed60999..421cf931d 100644
--- a/src/client/src/components/shared/Button/button-link.scss
+++ b/src/client/src/components/shared/Button/button-link.scss
@@ -1,12 +1,5 @@
@import "../../App/variables";
.button-link {
- color: $blue;
- background-color: transparent;
- border: none;
- cursor: pointer;
- text-decoration: none;
- font-size: 1em;
- font-weight: normal;
- padding: 0;
+ display: flex !important;
}
diff --git a/src/client/src/components/shared/Button/button.scss b/src/client/src/components/shared/Button/button.scss
index e1fe38b2d..a7e785e18 100644
--- a/src/client/src/components/shared/Button/button.scss
+++ b/src/client/src/components/shared/Button/button.scss
@@ -1,17 +1,22 @@
@import "../../App/variables";
.app .button {
- height: auto;
- min-height: 2.5rem;
- white-space: normal;
- font-weight: bold;
+ display: flex;
+ height: 2.5rem;
+ padding: 0.625rem;
+ justify-content: center;
+ align-items: center;
+ gap: 0.625rem;
&-icon {
+ display: flex;
+ align-items: center;
+ justify-content: center;
&--before-label {
margin-left: $spacing-2;
}
- &--after-label {
- margin-right: $spacing-2;
+ &--center-label {
+ text-align: center;
}
}
}
diff --git a/src/client/src/components/shared/Icons/ArrowDown.jsx b/src/client/src/components/shared/Icons/ArrowDown.jsx
new file mode 100644
index 000000000..2fb27f708
--- /dev/null
+++ b/src/client/src/components/shared/Icons/ArrowDown.jsx
@@ -0,0 +1,29 @@
+import Proptypes from "prop-types";
+import React from "react";
+
+const ArrowDown = ({ size = 24, color = "#000091" }) => (
+
+);
+
+ArrowDown.propTypes = {
+ color: Proptypes.string,
+ size: Proptypes.number,
+};
+
+export default ArrowDown;
diff --git a/src/client/src/components/shared/Icons/ArrowUp.jsx b/src/client/src/components/shared/Icons/ArrowUp.jsx
new file mode 100644
index 000000000..d7f24bc28
--- /dev/null
+++ b/src/client/src/components/shared/Icons/ArrowUp.jsx
@@ -0,0 +1,29 @@
+import Proptypes from "prop-types";
+import React from "react";
+
+const ArrowUp = ({ size = 22, color = "#000091" }) => (
+
+);
+
+ArrowUp.propTypes = {
+ color: Proptypes.string,
+ size: Proptypes.number,
+};
+
+export default ArrowUp;
diff --git a/src/client/src/components/shared/Icons/BuildingIcon.jsx b/src/client/src/components/shared/Icons/BuildingIcon.jsx
new file mode 100644
index 000000000..a0e2b842b
--- /dev/null
+++ b/src/client/src/components/shared/Icons/BuildingIcon.jsx
@@ -0,0 +1,30 @@
+import Proptypes from "prop-types";
+import React from "react";
+
+const BuildingIcon = ({ width = 24, height = 24, color = "#000091" }) => (
+
+);
+
+BuildingIcon.propTypes = {
+ color: Proptypes.string,
+ height: Proptypes.number,
+ width: Proptypes.number,
+};
+
+export default BuildingIcon;
diff --git a/src/client/src/components/shared/Icons/Calendar.jsx b/src/client/src/components/shared/Icons/Calendar.jsx
new file mode 100644
index 000000000..35790b969
--- /dev/null
+++ b/src/client/src/components/shared/Icons/Calendar.jsx
@@ -0,0 +1,83 @@
+import Proptypes from "prop-types";
+import React from "react";
+
+const Calendar = ({ size = 40 }) => (
+
+);
+
+Calendar.propTypes = {
+ size: Proptypes.number,
+};
+
+export default Calendar;
diff --git a/src/client/src/components/shared/Icons/ClosedIcon.jsx b/src/client/src/components/shared/Icons/ClosedIcon.jsx
new file mode 100644
index 000000000..b14ff82a6
--- /dev/null
+++ b/src/client/src/components/shared/Icons/ClosedIcon.jsx
@@ -0,0 +1,30 @@
+import Proptypes from "prop-types";
+import React from "react";
+
+const ClosedIcon = ({ width = 14, height = 12, color = "#CE0500" }) => (
+
+);
+
+ClosedIcon.propTypes = {
+ color: Proptypes.string,
+ height: Proptypes.number,
+ width: Proptypes.number,
+};
+
+export default ClosedIcon;
diff --git a/src/client/src/components/shared/Icons/Download.jsx b/src/client/src/components/shared/Icons/Download.jsx
new file mode 100644
index 000000000..fd8401996
--- /dev/null
+++ b/src/client/src/components/shared/Icons/Download.jsx
@@ -0,0 +1,30 @@
+import Proptypes from "prop-types";
+import React from "react";
+
+const Download = ({ width = 24, height = 24, color = "#000091" }) => (
+
+);
+
+Download.propTypes = {
+ color: Proptypes.string,
+ height: Proptypes.number,
+ width: Proptypes.number,
+};
+
+export default Download;
diff --git a/src/client/src/components/shared/Icons/EffectifIcon.jsx b/src/client/src/components/shared/Icons/EffectifIcon.jsx
new file mode 100644
index 000000000..68fd1d97e
--- /dev/null
+++ b/src/client/src/components/shared/Icons/EffectifIcon.jsx
@@ -0,0 +1,61 @@
+import Proptypes from "prop-types";
+import React from "react";
+
+const EffectifIcon = ({ size = 40 }) => (
+
+);
+
+EffectifIcon.propTypes = {
+ size: Proptypes.number,
+};
+
+export default EffectifIcon;
diff --git a/src/client/src/components/shared/Icons/EllipseIcon.jsx b/src/client/src/components/shared/Icons/EllipseIcon.jsx
new file mode 100644
index 000000000..244dbb2f2
--- /dev/null
+++ b/src/client/src/components/shared/Icons/EllipseIcon.jsx
@@ -0,0 +1,22 @@
+import Proptypes from "prop-types";
+import React from "react";
+
+const EllipseIcon = ({ width = 8, height = 8, color = "#000091" }) => (
+
+);
+
+EllipseIcon.propTypes = {
+ color: Proptypes.string,
+ height: Proptypes.number,
+ width: Proptypes.number,
+};
+
+export default EllipseIcon;
diff --git a/src/client/src/components/shared/Icons/EllipseIconAside.jsx b/src/client/src/components/shared/Icons/EllipseIconAside.jsx
new file mode 100644
index 000000000..7121e8052
--- /dev/null
+++ b/src/client/src/components/shared/Icons/EllipseIconAside.jsx
@@ -0,0 +1,22 @@
+import Proptypes from "prop-types";
+import React from "react";
+
+const EllipseIconAside = ({ width = 8, height = 7, color = "#000091" }) => (
+
+);
+
+EllipseIconAside.propTypes = {
+ color: Proptypes.string,
+ height: Proptypes.number,
+ width: Proptypes.number,
+};
+
+export default EllipseIconAside;
diff --git a/src/client/src/components/shared/Icons/HealthIcon.jsx b/src/client/src/components/shared/Icons/HealthIcon.jsx
new file mode 100644
index 000000000..4f36536a9
--- /dev/null
+++ b/src/client/src/components/shared/Icons/HealthIcon.jsx
@@ -0,0 +1,65 @@
+import Proptypes from "prop-types";
+import React from "react";
+
+const HealthIcon = ({ size = 40 }) => (
+
+);
+
+HealthIcon.propTypes = {
+ size: Proptypes.number,
+};
+
+export default HealthIcon;
diff --git a/src/client/src/components/shared/Icons/HospitalIcon.jsx b/src/client/src/components/shared/Icons/HospitalIcon.jsx
new file mode 100644
index 000000000..e12199bb0
--- /dev/null
+++ b/src/client/src/components/shared/Icons/HospitalIcon.jsx
@@ -0,0 +1,132 @@
+import Proptypes from "prop-types";
+import React from "react";
+
+const HospitalIcon = ({ width = 41, height = 40 }) => (
+
+);
+
+HospitalIcon.propTypes = {
+ height: Proptypes.number,
+ width: Proptypes.number,
+};
+
+export default HospitalIcon;
diff --git a/src/client/src/components/shared/Icons/LeftArrow.jsx b/src/client/src/components/shared/Icons/LeftArrow.jsx
new file mode 100644
index 000000000..22e3861d8
--- /dev/null
+++ b/src/client/src/components/shared/Icons/LeftArrow.jsx
@@ -0,0 +1,26 @@
+import Proptypes from "prop-types";
+import React from "react";
+
+const LeftArrow = ({ size = 17, color = "#000091" }) => (
+
+);
+
+LeftArrow.propTypes = {
+ color: Proptypes.string,
+ size: Proptypes.number,
+};
+
+export default LeftArrow;
diff --git a/src/client/src/components/shared/Icons/MessageIcon.jsx b/src/client/src/components/shared/Icons/MessageIcon.jsx
new file mode 100644
index 000000000..d563a81e1
--- /dev/null
+++ b/src/client/src/components/shared/Icons/MessageIcon.jsx
@@ -0,0 +1,26 @@
+import Proptypes from "prop-types";
+import React from "react";
+
+const MessageIcon = ({ size = 24, color = "#000091" }) => (
+
+);
+
+MessageIcon.propTypes = {
+ color: Proptypes.string,
+ size: Proptypes.number,
+};
+
+export default MessageIcon;
diff --git a/src/client/src/components/shared/Icons/Network.jsx b/src/client/src/components/shared/Icons/Network.jsx
new file mode 100644
index 000000000..46b77a464
--- /dev/null
+++ b/src/client/src/components/shared/Icons/Network.jsx
@@ -0,0 +1,85 @@
+import Proptypes from "prop-types";
+import React from "react";
+
+const Network = ({ size = 40 }) => (
+
+);
+
+Network.propTypes = {
+ size: Proptypes.number,
+};
+
+export default Network;
diff --git a/src/client/src/components/shared/Icons/OpenedIcon.jsx b/src/client/src/components/shared/Icons/OpenedIcon.jsx
new file mode 100644
index 000000000..539a2e8fc
--- /dev/null
+++ b/src/client/src/components/shared/Icons/OpenedIcon.jsx
@@ -0,0 +1,26 @@
+import Proptypes from "prop-types";
+import React from "react";
+
+const OpenedIcon = ({ size = 16, color = "#18753C" }) => (
+
+);
+
+OpenedIcon.propTypes = {
+ color: Proptypes.string,
+ size: Proptypes.number,
+};
+
+export default OpenedIcon;
diff --git a/src/client/src/components/shared/Icons/PrintIcon.jsx b/src/client/src/components/shared/Icons/PrintIcon.jsx
new file mode 100644
index 000000000..76fd5554b
--- /dev/null
+++ b/src/client/src/components/shared/Icons/PrintIcon.jsx
@@ -0,0 +1,26 @@
+import Proptypes from "prop-types";
+import React from "react";
+
+const PrintIcon = ({ size = 24, color = "#000091" }) => (
+
+);
+
+PrintIcon.propTypes = {
+ color: Proptypes.string,
+ size: Proptypes.number,
+};
+
+export default PrintIcon;
diff --git a/src/client/src/components/shared/Icons/RightArrow.jsx b/src/client/src/components/shared/Icons/RightArrow.jsx
new file mode 100644
index 000000000..149a4961c
--- /dev/null
+++ b/src/client/src/components/shared/Icons/RightArrow.jsx
@@ -0,0 +1,26 @@
+import Proptypes from "prop-types";
+import React from "react";
+
+const RightArrow = ({ size = 17, color = "#000091" }) => (
+
+);
+
+RightArrow.propTypes = {
+ color: Proptypes.string,
+ size: Proptypes.number,
+};
+
+export default RightArrow;
diff --git a/src/client/src/components/shared/Icons/SchoolIcon.jsx b/src/client/src/components/shared/Icons/SchoolIcon.jsx
new file mode 100644
index 000000000..56c2325d4
--- /dev/null
+++ b/src/client/src/components/shared/Icons/SchoolIcon.jsx
@@ -0,0 +1,140 @@
+import Proptypes from "prop-types";
+import React from "react";
+
+const SchoolIcon = ({ width = 41, height = 40 }) => (
+
+);
+
+SchoolIcon.propTypes = {
+ height: Proptypes.number,
+ width: Proptypes.number,
+};
+
+export default SchoolIcon;
diff --git a/src/client/src/components/shared/Icons/TopArrow.jsx b/src/client/src/components/shared/Icons/TopArrow.jsx
new file mode 100644
index 000000000..c56361f97
--- /dev/null
+++ b/src/client/src/components/shared/Icons/TopArrow.jsx
@@ -0,0 +1,24 @@
+import Proptypes from "prop-types";
+import React from "react";
+
+const TopArrow = ({ size = 16, color = "#000091" }) => (
+
+);
+
+TopArrow.propTypes = {
+ color: Proptypes.string,
+ size: Proptypes.number,
+};
+
+export default TopArrow;
diff --git a/src/client/src/components/shared/Icons/Warning.jsx b/src/client/src/components/shared/Icons/Warning.jsx
new file mode 100644
index 000000000..9332dd37f
--- /dev/null
+++ b/src/client/src/components/shared/Icons/Warning.jsx
@@ -0,0 +1,57 @@
+import Proptypes from "prop-types";
+import React from "react";
+
+const Warning = ({ size = 40 }) => (
+
+);
+
+Warning.propTypes = {
+ size: Proptypes.number,
+};
+
+export default Warning;
diff --git a/src/client/src/components/shared/InfoBox/InfoBox.js b/src/client/src/components/shared/InfoBox/InfoBox.js
index 86eb30a54..c7aadee78 100644
--- a/src/client/src/components/shared/InfoBox/InfoBox.js
+++ b/src/client/src/components/shared/InfoBox/InfoBox.js
@@ -14,7 +14,7 @@ const formatPostfix = (value) =>
const InfoBox = ({ value }) => {
return (
-
+
{formatPrefix(value)}
{formatPostfix(value)}
diff --git a/src/client/src/components/shared/InfoBox/infoBox.scss b/src/client/src/components/shared/InfoBox/infoBox.scss
index 9b7682a3b..76201b4eb 100644
--- a/src/client/src/components/shared/InfoBox/infoBox.scss
+++ b/src/client/src/components/shared/InfoBox/infoBox.scss
@@ -1,14 +1,21 @@
@import "../../App/variables";
.info-box {
- margin: 0 0 $spacing-4 -0.2rem; // -0.2rem = optical trick to align round shape
+ margin: 0 0 $spacing-4 -0.2rem;
&__pill {
padding: $spacing-2 $spacing-3;
- font-family: $roboto;
font-weight: bold;
- background-color: #f5f5f7;
+ background-color: #e3e3fd;
+ color: $dark-blue;
border-radius: 1rem;
+ font-family: $marianne;
+ font-size: $font-size-small;
+ cursor: pointer;
+
+ &:hover {
+ background-color: #c5c5e1;
+ }
}
&__print {
diff --git a/src/client/src/components/shared/LoadableContent/LoadableContent.js b/src/client/src/components/shared/LoadableContent/LoadableContent.js
index ba023c99e..fa0b5ed75 100644
--- a/src/client/src/components/shared/LoadableContent/LoadableContent.js
+++ b/src/client/src/components/shared/LoadableContent/LoadableContent.js
@@ -1,5 +1,5 @@
+import { PropTypes } from "prop-types";
import React from "react";
-import { propTypes } from "react-widgets/lib/util/Filter";
import LoadSpinner from "../LoadSpinner";
import Value from "../Value";
@@ -17,9 +17,9 @@ const LoadableContent = ({ loading, error, children }) => {
};
LoadableContent.propTypes = {
- children: propTypes.node,
- error: propTypes.any,
- loading: propTypes.bool,
+ children: PropTypes.node,
+ error: PropTypes.any,
+ loading: PropTypes.bool,
};
export default LoadableContent;
diff --git a/src/client/src/components/shared/Tooltip/Tooltip.jsx b/src/client/src/components/shared/Tooltip/Tooltip.jsx
new file mode 100644
index 000000000..79c471633
--- /dev/null
+++ b/src/client/src/components/shared/Tooltip/Tooltip.jsx
@@ -0,0 +1,40 @@
+import "./Tooltip.scss";
+
+import PropTypes from "prop-types";
+import React, { useState } from "react";
+
+function Tooltip({ content, children, position }) {
+ const [isTooltipVisible, setTooltipVisible] = useState(false);
+
+ const showTooltip = () => {
+ setTooltipVisible(true);
+ };
+
+ const hideTooltip = () => {
+ setTooltipVisible(false);
+ };
+
+ return (
+
+
+ {children}
+
+ {isTooltipVisible && (
+
+ )}
+
+ );
+}
+
+Tooltip.propTypes = {
+ children: PropTypes.node,
+ content: PropTypes.string,
+ position: PropTypes.string,
+};
+export default Tooltip;
diff --git a/src/client/src/components/shared/Tooltip/Tooltip.scss b/src/client/src/components/shared/Tooltip/Tooltip.scss
new file mode 100644
index 000000000..a1f1c152f
--- /dev/null
+++ b/src/client/src/components/shared/Tooltip/Tooltip.scss
@@ -0,0 +1,57 @@
+@import "../../App/variables";
+
+.tooltip-container {
+ position: relative;
+
+ .element-with-tooltip {
+ cursor: pointer;
+ }
+
+ .tooltip {
+ position: absolute;
+ color: #333;
+ padding: 5px;
+ border-radius: 4px;
+ display: none;
+ background-color: white !important;
+ box-shadow: 0 2px 6px rgba(0, 0, 18, 0.16);
+
+ .content {
+ display: flex;
+ flex-direction: row;
+ flex-wrap: nowrap;
+ color: #333 !important;
+ font-size: $font-size-small !important;
+ }
+ &.left {
+ top: 0%;
+ left: -170px;
+ transform: translateY(-50%);
+ }
+
+ &.top {
+ top: -5px;
+ left: 50%;
+ transform: translateX(-50%);
+ }
+
+ &.right {
+ top: 50%;
+ left: 100%;
+ transform: translateY(-50%);
+ }
+
+ &.bottom {
+ top: -5px;
+ left: -200px;
+ transform: translateY(10px);
+ z-index: 1;
+ }
+ }
+
+ &:hover {
+ .tooltip {
+ display: block;
+ }
+ }
+}
diff --git a/src/client/src/components/shared/Value/Value.js b/src/client/src/components/shared/Value/Value.js
index 07479b41a..5d4dd64a7 100644
--- a/src/client/src/components/shared/Value/Value.js
+++ b/src/client/src/components/shared/Value/Value.js
@@ -33,6 +33,9 @@ const Value = ({
if (value === false && empty === "0") {
return "0";
}
+ if (value === 0 && empty === "0") {
+ return "0";
+ }
if (value === false && no) {
return no;
@@ -79,13 +82,16 @@ const Value = ({
{" (DGFIP)"}
) : (
- formatNumber(value, numberFormatOptions)
+
+ {formatNumber(value, numberFormatOptions)}
+
);
}
return isApi ? (
- {value}
+
{value}
+
{" (DGFIP)"}
) : (
diff --git a/src/client/src/containers/AllEffectifsEtpButton/AllEffectifsEtpButton.js b/src/client/src/containers/AllEffectifsEtpButton/AllEffectifsEtpButton.js
index 2c2724931..63fb90899 100644
--- a/src/client/src/containers/AllEffectifsEtpButton/AllEffectifsEtpButton.js
+++ b/src/client/src/containers/AllEffectifsEtpButton/AllEffectifsEtpButton.js
@@ -1,14 +1,15 @@
import "./AllEffectifsEtpButton.scss";
-import { faCaretDown, faCaretUp } from "@fortawesome/free-solid-svg-icons";
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import classNames from "classnames";
import PropTypes from "prop-types";
import React from "react";
+import ArrowDown from "../../components/shared/Icons/ArrowDown.jsx";
+import ArrowUp from "../../components/shared/Icons/ArrowUp.jsx";
+
const AllEffectifsEtpButton = ({ onClick, loading, text, isUp = false }) => {
return (
-
+
);
diff --git a/src/client/src/containers/AllEffectifsEtpButton/AllEffectifsEtpButton.scss b/src/client/src/containers/AllEffectifsEtpButton/AllEffectifsEtpButton.scss
index cee36a670..72fe93e12 100644
--- a/src/client/src/containers/AllEffectifsEtpButton/AllEffectifsEtpButton.scss
+++ b/src/client/src/containers/AllEffectifsEtpButton/AllEffectifsEtpButton.scss
@@ -2,14 +2,31 @@
.all_effectifs_etp_button {
display: flex;
- margin: $spacing-2 0;
- align-items:center ;
- justify-content: center;
- button {
- border: none !important;
- background-color: transparent;
- text-decoration: underline ;
- color: $primary !important;
- cursor: pointer;
+
+ padding-bottom: $spacing-3;
+ button {
+ border: none !important;
+ padding: 0 1rem 0 0;
+ background-color: transparent;
+ color: $dark-blue !important;
+ font-family: $marianne;
+ font-size: $font-size-base;
+ font-weight: 400;
+ line-height: 1.5rem;
+ text-decoration: underline !important;
+ text-underline-offset: 4px;
+ text-decoration-thickness: 1px !important;
+ display: flex;
+ gap: $spacing-2;
+
+ cursor: pointer;
+ &:hover {
+ text-decoration-thickness: 2px !important;
+ }
+ > .icon {
+ width: 25px;
+ height: 25px;
+ margin-right: $spacing-4;
+ }
+ }
}
-}
\ No newline at end of file
diff --git a/src/client/src/containers/Association/Association.js b/src/client/src/containers/Association/Association.js
index 0e82149a1..2d575c171 100644
--- a/src/client/src/containers/Association/Association.js
+++ b/src/client/src/containers/Association/Association.js
@@ -18,9 +18,17 @@ const Association = ({ siret }) => {
const { association } = data;
return (
<>
-
+
{isAssociation(association) && (
-
+
)}
>
);
diff --git a/src/client/src/containers/Enterprise/ListEtablissements.jsx b/src/client/src/containers/Enterprise/ListEtablissements.jsx
new file mode 100644
index 000000000..967fc8198
--- /dev/null
+++ b/src/client/src/containers/Enterprise/ListEtablissements.jsx
@@ -0,0 +1,17 @@
+import PropTypes from "prop-types";
+import React from "react";
+import { withRouter } from "react-router";
+
+import ListEstablishmentsResult from "../../components/DataSheets/Sections/ListEstablishmentsResult/ListEstablishmentsResult.jsx";
+
+const ListEtablissements = ({ match, history }) => {
+ const siren = match.params.siren;
+ return
;
+};
+
+ListEtablissements.propTypes = {
+ history: PropTypes.object.isRequired,
+ match: PropTypes.object.isRequired,
+};
+
+export default withRouter(ListEtablissements);
diff --git a/src/client/src/containers/Search/Search.js b/src/client/src/containers/Search/Search.js
index e5f206808..a13dff64e 100644
--- a/src/client/src/containers/Search/Search.js
+++ b/src/client/src/containers/Search/Search.js
@@ -38,12 +38,12 @@ const Search = () => {
const [searchQuery, setSearchQuery] = useSearchTerms();
const [searchPage, setSearchPage] = useSearchPage();
- const { filters, addFilter, removeFilter } = useSearchFilters();
+ const { filters, addFilter, removeFilter, removeFilters } =
+ useSearchFilters();
const { sortField, sortDirection, toggleSortField } = useSort();
- const { data, loading, error, makeQuery } = useSearchQuery();
-
+ const { data, loading, error, makeQuery, query } = useSearchQuery();
const resetSearch = useResetSearch();
useEffect(() => {
@@ -103,6 +103,7 @@ const Search = () => {
results={data?.results}
page={searchPage}
pageSize={PAGE_SIZE}
+ query={query}
totalResults={data?.total || 0}
sendRequest={onSearch}
searchTerm={searchQuery || ""}
@@ -111,6 +112,7 @@ const Search = () => {
handlePageChange={handlePageChange}
addFilter={addFilter}
removeFilter={removeFilter}
+ removeFilters={removeFilters}
filters={filters}
sortField={sortField}
sortDirection={sortDirection}
diff --git a/src/client/src/containers/UsersFeedback/UsersFeedback.js b/src/client/src/containers/UsersFeedback/UsersFeedback.js
index 5846cd462..62729a74d 100644
--- a/src/client/src/containers/UsersFeedback/UsersFeedback.js
+++ b/src/client/src/containers/UsersFeedback/UsersFeedback.js
@@ -23,7 +23,11 @@ const reducer = (state, action) => {
}
};
-const UsersFeedback = ({ fullWidth }) => {
+const UsersFeedback = ({
+ fullWidth,
+ isOpenUserFeedback,
+ onOpenUserFeedback,
+}) => {
const [state, dispatch] = useReducer(reducer, initialState);
const sendFeedback = (e) => {
@@ -50,12 +54,16 @@ const UsersFeedback = ({ fullWidth }) => {
dispatch={dispatch}
sendFeedback={sendFeedback}
fullWidth={fullWidth}
+ isOpenUserFeedback={isOpenUserFeedback}
+ onOpenUserFeedback={onOpenUserFeedback}
/>
);
};
UsersFeedback.propTypes = {
fullWidth: PropTypes.bool,
+ isOpenUserFeedback: PropTypes.bool,
+ onOpenUserFeedback: PropTypes.func,
};
export default UsersFeedback;
diff --git a/src/client/src/helpers/Date/Date.js b/src/client/src/helpers/Date/Date.js
index a6804191f..3847229b1 100644
--- a/src/client/src/helpers/Date/Date.js
+++ b/src/client/src/helpers/Date/Date.js
@@ -65,6 +65,12 @@ export const setYearMonthFormat = (date) => {
}
return Moment(date).format("YYYY-MM");
};
+export const setYearFormat = (date) => {
+ if (!date) {
+ return "";
+ }
+ return Moment(date).format("YYYY");
+};
const START_DATE_LABEL = {
LAST_FIVE_YEARS: 60,
LAST_FOUR_YEARS: 48,
diff --git a/src/client/src/helpers/utils/utils.js b/src/client/src/helpers/utils/utils.js
index 58ae49d3f..c6e4b05e3 100644
--- a/src/client/src/helpers/utils/utils.js
+++ b/src/client/src/helpers/utils/utils.js
@@ -1,3 +1,5 @@
+import codesNaf from "@socialgouv/codes-naf";
+
export const joinNoFalsy = (arr, delimiter = "") =>
arr.filter((element) => !!element).join(delimiter);
@@ -9,6 +11,14 @@ export const capitalize = (str) =>
.map((str) => `${str.slice(0, 1).toUpperCase()}${str.slice(1)}`)
.join(" ");
+const getCodeNafLibelle = (code) =>
+ codesNafLabelIndex.get(code.padEnd(5, "0").slice(0, 5));
+const codesNafLabelIndex = codesNaf.reduce(
+ (map, { id, label }) => map.set(id, label),
+ new Map()
+);
+export const getLibelletFromCodeNaf = (code) => getCodeNafLibelle(code);
+
export const countValuesInArray = (array, fields) => {
if (!Array.isArray(fields) || !fields.length) {
return 0;
diff --git a/src/client/src/services/Elastic/elastic.js b/src/client/src/services/Elastic/elastic.js
index 6960f8502..1b53780eb 100644
--- a/src/client/src/services/Elastic/elastic.js
+++ b/src/client/src/services/Elastic/elastic.js
@@ -21,6 +21,7 @@ export const useElasticQuery = () => {
const [data, setData] = useState(defaultData);
const [loading, setIsLoading] = useState(false);
const [error, setError] = useState(null);
+ const [query, setQuery] = useState("");
const makeQuery = useCallback(
(query, { page: { size, current }, params }) => {
@@ -34,6 +35,7 @@ export const useElasticQuery = () => {
results: response.data.results,
total: response.data.total.value,
});
+ setQuery(sentQuery);
})
.catch((err) => {
setData(defaultData);
@@ -51,5 +53,6 @@ export const useElasticQuery = () => {
error,
loading,
makeQuery,
+ query,
};
};
diff --git a/src/client/src/services/Entreprise/hooks.js b/src/client/src/services/Entreprise/hooks.js
index 8c501bad1..c16764bc9 100644
--- a/src/client/src/services/Entreprise/hooks.js
+++ b/src/client/src/services/Entreprise/hooks.js
@@ -38,6 +38,7 @@ const entrepriseQuery = gql`
}
fce_organismes_formation(where: { siren: { _eq: $siren } }) {
siret
+ denomination
}
fce_psi_siren(where: { siren: { _eq: $siren } }) {
salaries_annee_courante
diff --git a/src/client/src/services/PrivateRoute/CustomLayout.jsx b/src/client/src/services/PrivateRoute/CustomLayout.jsx
new file mode 100644
index 000000000..7086f4092
--- /dev/null
+++ b/src/client/src/services/PrivateRoute/CustomLayout.jsx
@@ -0,0 +1,68 @@
+import PropTypes from "prop-types";
+import React from "react";
+
+import { EstablishmentProvider } from "../../components/DataSheets/Sections/SharedComponents/EstablishmentContext.jsx";
+import SubHeader from "../../components/DataSheets/Sections/SharedComponents/SubHeader/SubHeader.jsx";
+import Sidebar from "../../components/DataSheets/Sidebar/Sidebar";
+import UsersFeedback from "../../containers/UsersFeedback/UsersFeedback.js";
+
+const CustomLayout = ({
+ isEstablishmentDisplayed,
+ isEntrepriseDisplayed,
+ isEstablishmentsDisplayed,
+ siren,
+ siret,
+ children,
+}) => {
+ const [isOpenUserFeedback, setIsOpenUserFeedback] = React.useState(false);
+
+ const onOpenUserFeedback = (isOpen) => {
+ setIsOpenUserFeedback(isOpen);
+ };
+ const openUserFeedback = () => {
+ setIsOpenUserFeedback(true);
+ };
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+ {children}
+
+
+
+
+
+
+ >
+ );
+};
+
+CustomLayout.propTypes = {
+ children: PropTypes.node,
+ isEntrepriseDisplayed: PropTypes.bool.isRequired,
+ isEstablishmentDisplayed: PropTypes.bool.isRequired,
+ isEstablishmentsDisplayed: PropTypes.bool.isRequired,
+ siren: PropTypes.string.isRequired,
+ siret: PropTypes.string,
+};
+
+export default CustomLayout;
diff --git a/src/client/src/services/PrivateRoute/PrivateRoute.js b/src/client/src/services/PrivateRoute/PrivateRoute.js
index 305c8db23..fc9fb19e2 100644
--- a/src/client/src/services/PrivateRoute/PrivateRoute.js
+++ b/src/client/src/services/PrivateRoute/PrivateRoute.js
@@ -3,66 +3,75 @@ import React from "react";
import { Redirect, Route, useHistory } from "react-router-dom";
import Layout from "../../components/App/Layout";
+import { getSirenFromSiret } from "../../utils/establishment/establishment";
import Auth from "../Auth";
+import CustomLayout from "./CustomLayout.jsx";
const PrivateRoute = ({
component: Component,
- displayMessage,
+ isEstablishmentDisplayed = false,
+ isEntrepriseDisplayed = false,
+ isEstablishmentsDisplayed = false,
+ displayMessage = false,
location,
...rest
}) => {
const history = useHistory();
- async function getTempAuthAndRedirect(credential, location) {
- await Auth.tempLogin(credential)
- .then(() => {
- history.push(location.pathname);
- })
- .catch(() => {
- history.push("/login");
- });
- }
+ const getTempAuthAndRedirect = async (credential, location) => {
+ try {
+ await Auth.tempLogin(credential);
+ history.push(location.pathname);
+ } catch (error) {
+ history.push("/login");
+ }
+ };
const checkAuthorization = () => {
const credential = new URLSearchParams(location.search).get("credential");
if (Auth.isLogged()) {
- return {
- auth: true,
- };
+ return { auth: true };
} else if (credential) {
getTempAuthAndRedirect(credential, location);
- return {
- auth: false,
- redirect: location.pathname,
- };
+ return { auth: false, redirect: location.pathname };
} else {
- return {
- auth: false,
- redirect: "/home",
- };
+ return { auth: false, redirect: "/home" };
}
};
- const authorization = checkAuthorization();
+ const { auth, redirect } = checkAuthorization();
+ const siret = rest?.computedMatch?.params?.siret;
+ const siren = rest?.computedMatch?.params?.siren || getSirenFromSiret(siret);
return (
{
- return authorization.auth ? (
+ render={(props) =>
+ auth ? (
-
+ {isEstablishmentDisplayed ||
+ isEntrepriseDisplayed ||
+ isEstablishmentsDisplayed ? (
+
+
+
+ ) : (
+
+ )}
) : (
- );
- }}
+ )
+ }
/>
);
};
@@ -73,6 +82,9 @@ PrivateRoute.propTypes = {
history: PropTypes.shape({
push: PropTypes.func,
}),
+ isEntrepriseDisplayed: PropTypes.bool,
+ isEstablishmentDisplayed: PropTypes.bool,
+ isEstablishmentsDisplayed: PropTypes.bool,
location: PropTypes.object,
};
diff --git a/src/client/src/services/Store/hooks/search.js b/src/client/src/services/Store/hooks/search.js
index 23b3046fb..886581c47 100644
--- a/src/client/src/services/Store/hooks/search.js
+++ b/src/client/src/services/Store/hooks/search.js
@@ -38,7 +38,6 @@ export const useSearchPage = () => {
export const useSearchFilters = () => {
const dispatch = useDispatch();
const savedFilters = useSelector((state) => getSearchState(state).filters);
-
// cache busting mechanism
const validFilters = savedFilters.etats
? savedFilters
@@ -47,21 +46,43 @@ export const useSearchFilters = () => {
};
const addFilter = (key, value) => {
- dispatch(setSearchFilters({ ...validFilters, [key]: value }));
+ dispatch(setSearchFilters({ ...savedFilters, [key]: value }));
};
const removeFilter = (key) => {
- dispatch(setSearchFilters(omit(validFilters, key)));
+ dispatch(setSearchFilters(omit(savedFilters, key)));
};
+ const deleteKeys = (obj, keys) => {
+ if (!Array.isArray(keys)) {
+ throw new Error("Keys must be an array");
+ }
+
+ const newObj = {};
- return { addFilter, filters: savedFilters, removeFilter };
+ Object.keys(obj).forEach((key) => {
+ if (!keys.includes(key)) {
+ newObj[key] = obj[key];
+ }
+ });
+
+ return newObj;
+ };
+
+ const removeFilters = (keys) => {
+ const updatedFilters = keys.reduce(
+ (acc, key) => deleteKeys(acc, [key]),
+ validFilters
+ );
+ dispatch(setSearchFilters(updatedFilters));
+ };
+
+ return { addFilter, filters: savedFilters, removeFilter, removeFilters };
};
export const useSearchQuery = () => {
const dispatch = useDispatch();
const results = useSelector((state) => getSearchState(state).results);
-
- const { data, loading, error, makeQuery } = useElasticQuery();
+ const { data, loading, error, makeQuery, query } = useElasticQuery();
useEffect(() => {
if (data.results !== null) {
@@ -74,6 +95,7 @@ export const useSearchQuery = () => {
error,
loading,
makeQuery,
+ query,
};
};
diff --git a/src/client/src/utils/entreprise/entreprise.js b/src/client/src/utils/entreprise/entreprise.js
index 9cef339fc..6cbba69c5 100644
--- a/src/client/src/utils/entreprise/entreprise.js
+++ b/src/client/src/utils/entreprise/entreprise.js
@@ -26,7 +26,10 @@ import {
normalizeInteractionsT,
} from "../interactions/interactions";
-export const isActive = pipe(prop("etatadministratifunitelegale"), equals("A"));
+export const isActiveEntreprise = pipe(
+ prop("etatadministratifunitelegale"),
+ equals("A")
+);
export const getOrganismesFormations = prop("organismes_formation");
export const getRupco = prop("rupco");
diff --git a/src/client/src/utils/establishment/establishment.js b/src/client/src/utils/establishment/establishment.js
index c835b2957..330772b5b 100644
--- a/src/client/src/utils/establishment/establishment.js
+++ b/src/client/src/utils/establishment/establishment.js
@@ -10,7 +10,7 @@ import {
toLower,
} from "lodash/fp";
-export const getSirenFromSiret = (siret) => siret.substring(0, 9);
+export const getSirenFromSiret = (siret) => siret?.substring(0, 9);
export const getSiret = prop("siret");
@@ -21,7 +21,7 @@ export const isActive = pipe(getState, equals("A"));
export const isSiege = pipe(prop("etablissementsiege"), equals("true"));
export const getCategoryLabel = (etablissement) =>
- isSiege(etablissement) ? "Siège Social" : "Établissement";
+ isSiege(etablissement) ? "Siège Social" : "Établissement secondaire";
export const getCodePostal = (etablissement) =>
prop("codepostaletablissement", etablissement) ||
@@ -58,8 +58,13 @@ export const getAdresse = (etablissement) => {
]),
getTypeVoie(etablissement),
getNomVoie(etablissement),
- "-",
- getCodePostal(etablissement),
- getCity(etablissement),
].join(" ");
};
+export const getCodePostalAndCity = (etablissement) => {
+ if (etablissement)
+ return [getCodePostal(etablissement), getCity(etablissement)].join(" ");
+};
+
+export const getEtablissementsCount = prop("nb_eta");
+
+export const getEtablissementsFermesCount = prop("nb_eta_fermes");
diff --git a/src/client/yarn.lock b/src/client/yarn.lock
index c667a2d87..b82ae0e91 100644
--- a/src/client/yarn.lock
+++ b/src/client/yarn.lock
@@ -1976,6 +1976,11 @@
dependencies:
"@sinonjs/commons" "^1.7.0"
+"@socialgouv/codes-naf@^1.1.0":
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/@socialgouv/codes-naf/-/codes-naf-1.1.0.tgz#a84014b226d11afcf56bd581dc005b014730e56a"
+ integrity sha512-Evj6cI5yNw/tZOX9htx35lnK9O36rXnc787F40nE9+SDeReD8LTO4zXKKiB7G/dzCr4uHEDSRSPzapBDsdMceA==
+
"@socialgouv/eslint-config-react@^1.108.0":
version "1.108.0"
resolved "https://registry.yarnpkg.com/@socialgouv/eslint-config-react/-/eslint-config-react-1.108.0.tgz#4ed78951821ec20e4b8be4c3d5d77fbe320fea65"