= ({ visibleModal, setVisibleModal, onAdd }) => {
12 | const handleCancel = () => setVisibleModal(false);
13 |
14 | return (
15 |
24 |
25 |
26 | );
27 | };
28 |
29 | export default AddDocumentsModal;
30 |
--------------------------------------------------------------------------------
/src/pages/Distinction/DistinctionTable/Form.module.css:
--------------------------------------------------------------------------------
1 | .cardButton {
2 | display: flex;
3 | width: 100%;
4 | justify-content:flex-end;
5 | float: right;
6 | }
7 | .cardButton>* {
8 | margin-right: 8px;
9 | }
10 | .formField {
11 | max-width: 370px;
12 | min-width: 370px;
13 | }
14 |
15 | .selectField {
16 | max-width: 370px;
17 | min-width: 370px;
18 | }
19 |
20 | .selectTypeDistField {
21 | max-width: 320px;
22 | min-width: 320px;
23 | }
24 |
25 | .editTypeDistPosition{
26 | padding: 35px 0 0 25%;
27 | }
28 |
29 | .buttons{
30 | margin-right: 0px !important;
31 | margin-left: 7px;
32 | }
33 |
34 | @media(max-width: 400px) {
35 | .formField{
36 | max-width: 100%;
37 | min-width: 100%;
38 | }
39 | .selectField {
40 | max-width: 100%;
41 | min-width: 100%;
42 | }
43 | .selectTypeDistField {
44 | max-width: 100%;
45 | min-width: 100%;
46 | }
47 | }
--------------------------------------------------------------------------------
/src/pages/userPage/ActiveMembership/UserDates/columnsFormerUser.tsx:
--------------------------------------------------------------------------------
1 | import moment from "moment";
2 |
3 | const minDate = "0001-01-01T00:00:00";
4 |
5 |
6 | const columns = [
7 | {
8 | title: "№",
9 | width: 60,
10 | key: "index",
11 | render: (text: string, record: any, index: number) => index + 1
12 | },
13 | {
14 | title: "Дата початку",
15 | dataIndex: "entry",
16 | width: 120,
17 | render: (entry: string) => {
18 | return entry == minDate ?
19 | "Немає"
20 | : moment.utc(entry).local().format("DD.MM.YYYY");
21 | },
22 | },
23 | {
24 | title: "Дата відновлення",
25 | dataIndex: "end",
26 | width: 120,
27 | render: (end: string) => {
28 | return end == minDate ?
29 | "Все ще не відновився"
30 | : moment.utc(end).local().format("DD.MM.YYYY");
31 | },
32 | }
33 | ];
34 |
35 | export default columns;
36 |
--------------------------------------------------------------------------------
/src/pages/Precaution/Interfaces/DropDownPrecautionTableProps.ts:
--------------------------------------------------------------------------------
1 | import Precaution from "./Precaution";
2 | import PrecautionUser from "./PrecautionUser";
3 | import UserPrecautionStatus from "./UserPrecautionStatus";
4 | import UserPrecautionTableItem from "./UserPrecautionTableItem";
5 |
6 | type DropDownProps = {
7 | recordId: number;
8 | userId: string;
9 | pageX: number;
10 | pageY: number;
11 | showDropdown: boolean;
12 | userAccess: { [key: string]: boolean };
13 | isActive: boolean;
14 | onDelete: (id: number) => void;
15 | onEdit: (
16 | id: number,
17 | Precaution: Precaution,
18 | date: Date,
19 | endDate: Date,
20 | isActive: boolean,
21 | reason: string,
22 | status: UserPrecautionStatus,
23 | reporter: string,
24 | number: number,
25 | userId: PrecautionUser,
26 | user: any
27 | ) => void;
28 | };
29 |
30 | export default DropDownProps;
31 |
--------------------------------------------------------------------------------
/src/pages/GoverningBody/Announcement/DeleteConfirm.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Modal } from "antd";
3 | import { ExclamationCircleOutlined } from "@ant-design/icons";
4 | import { deleteAnnouncement } from "../../../api/governingBodiesApi";
5 | import notificationLogic from "../../../components/Notifications/Notification";
6 |
7 | const { confirm } = Modal;
8 |
9 | const DeleteConfirm = (id: number, onDelete: any) => {
10 | return confirm({
11 | title: "Ви справді хочете видалити оголошення?",
12 | icon: ,
13 | okText: "Так",
14 | cancelText: "Ні",
15 | onOk() {
16 | const remove = async () => {
17 | deleteAnnouncement(id);
18 | };
19 | remove();
20 | onDelete(id);
21 | notificationLogic("success", "Оголошення видалено");
22 | },
23 | });
24 | };
25 | export default DeleteConfirm;
26 |
--------------------------------------------------------------------------------
/src/components/HistoryNavi/historyPseudo.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | class PsevdonimCreator {
4 | static pseudonimLocation: { userId: string; psevdonim: string }[] =
5 | sessionStorage.getItem("pseudonimLocation") !== null
6 | ? JSON.parse(sessionStorage["pseudonimLocation"])
7 | : [];
8 |
9 | static setPseudonimLocation = (adressPsevdo: string, userId: string) => {
10 | if (
11 | PsevdonimCreator.pseudonimLocation.find(
12 | (x: { userId: string }) => x.userId === userId
13 | ) === undefined
14 | ) {
15 | let ps = {
16 | userId: `${userId}`,
17 | psevdonim: `${adressPsevdo}`,
18 | };
19 | PsevdonimCreator.pseudonimLocation.push(ps);
20 | }
21 | sessionStorage.setItem(
22 | "pseudonimLocation",
23 | JSON.stringify(PsevdonimCreator.pseudonimLocation)
24 | );
25 | };
26 | }
27 | export default PsevdonimCreator;
28 |
--------------------------------------------------------------------------------
/src/models/UserAccess/IUserAccess.ts:
--------------------------------------------------------------------------------
1 | export default interface IUserAnnualReportAccess {
2 | IsSuperAdmin: boolean;
3 | IsAdmin: boolean;
4 | CanViewReportsPage: boolean;
5 | CanViewCityReportsTable: boolean;
6 | CanViewClubReportsTable: boolean;
7 | CanViewRegionReportsTable: boolean;
8 | CanViewReportDetails: boolean;
9 | CanSubmitCityReport: boolean;
10 | CanSubmitClubReport: boolean;
11 | CanSubmitRegionReport: boolean;
12 | CanEditReport: boolean;
13 | CanChangeReportStatus: boolean;
14 | CanDeleteReport: boolean;
15 | CanCityStatisticsChooseCity: boolean;
16 | CanCityStatisticsChooseYears: boolean;
17 | CanCityStatisticsChooseIndicators: boolean;
18 | CanCityStatisticsFormReport: boolean;
19 | CanRegionStatisticsChooseRegion: boolean;
20 | CanRegionStatisticsСhooseYears: boolean;
21 | CanRegionStatisticsChooseIndicators: boolean;
22 | CanRegionStatisticsFormReport: boolean;
23 | }
24 |
--------------------------------------------------------------------------------
/manifests/ingress-prod.yml:
--------------------------------------------------------------------------------
1 | apiVersion: networking.k8s.io/v1
2 | kind: Ingress
3 | metadata:
4 | namespace: eplast
5 | name: routing-for-eplast-client
6 | annotations:
7 | kubernetes.io/ingress.class: nginx
8 | cert-manager.io/cluster-issuer: letsencrypt-production
9 | nginx.ingress.kubernetes.io/proxy-body-size: "20m"
10 | spec:
11 | tls:
12 | - hosts:
13 | - ___SiteDnsName___
14 | secretName: tls-secret-prd
15 | rules:
16 | - host: ___SiteDnsName___
17 | http:
18 | paths:
19 | - backend:
20 | service:
21 | name: eplastweb
22 | port:
23 | number: 80
24 | path: /
25 | pathType: ImplementationSpecific
26 | - backend:
27 | service:
28 | name: prometheus-grafana
29 | port:
30 | number: 80
31 | path: /grafana
32 | pathType: ImplementationSpecific
33 |
--------------------------------------------------------------------------------
/src/pages/AnnualReport/AnnualReportMenu.less:
--------------------------------------------------------------------------------
1 | .report-menu {
2 | position: fixed;
3 | top: 64px;
4 | right: 0px;
5 | z-index: 1;
6 | vertical-align: center;
7 | top: 120px;
8 | float: right;
9 | }
10 |
11 | .report-menu-item {
12 | background: #3c5438;
13 | border-radius: 0 2px 2px 0;
14 | cursor: pointer;
15 | width: 36px;
16 | height: 42px;
17 | color: #fff;
18 | margin-top: 10px;
19 | font-size: x-large;
20 | line-height: 42px;
21 | text-align: center;
22 | }
23 |
24 | .report-menu-item:hover {
25 | background-color: hsla(111, 20%, 27%, 0.9);
26 | }
27 |
28 | .report-menu-item-clicked {
29 | background-color: hsla(91, 24%, 51%, 0.9);
30 | border-radius: 0 2px 2px 0;
31 | width: 36px;
32 | height: 42px;
33 | color: #fff;
34 | margin-top: 10px;
35 | font-size: x-large;
36 | line-height: 42px;
37 | text-align: center;
38 | }
39 |
--------------------------------------------------------------------------------
/src/pages/userPage/ActiveMembership/PlastDegree/DeleteDegreeConfirm.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Modal } from "antd";
3 | import { ExclamationCircleOutlined } from "@ant-design/icons";
4 | import activeMembershipApi from "../../../../api/activeMembershipApi";
5 | const { confirm } = Modal;
6 |
7 | const DeleteDegreeConfirm = (
8 | userId: string,
9 | plastDegreeId: number,
10 | handleDelete: any
11 | ) => {
12 | const remove = async () => {
13 | await activeMembershipApi.removeUserPlastDegree(userId, plastDegreeId);
14 | };
15 |
16 | return confirm({
17 | title: "Ви справді хочете видалити даний ступінь користувачу?",
18 | icon: ,
19 | okText: "Так",
20 | cancelText: "Ні",
21 | onOk() {
22 | remove();
23 | handleDelete(plastDegreeId);
24 | },
25 | });
26 | };
27 |
28 | export default DeleteDegreeConfirm;
29 |
--------------------------------------------------------------------------------
/src/pages/GoverningBody/Sector/SectorAnnouncement/DeleteConfirm.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Modal } from "antd";
3 | import { ExclamationCircleOutlined } from "@ant-design/icons";
4 | import { deleteSectorAnnouncement } from "../../../../api/governingBodySectorsApi";
5 | import notificationLogic from "../../../../components/Notifications/Notification";
6 |
7 | const { confirm } = Modal;
8 |
9 | const DeleteConfirm = (id: number, onDelete: any) => {
10 | return confirm({
11 | title: "Ви справді хочете видалити оголошення?",
12 | icon: ,
13 | okText: "Так",
14 | cancelText: "Ні",
15 | onOk() {
16 | const remove = async () => {
17 | deleteSectorAnnouncement(id);
18 | };
19 | remove();
20 | onDelete(id);
21 | notificationLogic("success", "Оголошення видалено");
22 | },
23 | });
24 | };
25 | export default DeleteConfirm;
26 |
--------------------------------------------------------------------------------
/manifests/deployment.yml:
--------------------------------------------------------------------------------
1 | apiVersion : apps/v1
2 | kind: Deployment
3 | metadata:
4 | name: eplastweb
5 | labels:
6 | app: eplastweb
7 | spec:
8 | selector:
9 | matchLabels:
10 | app: eplastweb
11 | template:
12 | metadata:
13 | labels:
14 | app: eplastweb
15 | spec:
16 | containers:
17 | - name: eplastweb
18 | image: eplast.azurecr.io/eplastweb:___containerRegistry_version_frontend_test___
19 | resources:
20 | limits:
21 | cpu: "100m"
22 | memory: "100Mi"
23 | ports:
24 | - containerPort: 80
25 |
26 | ---
27 | apiVersion: autoscaling/v1
28 | kind: HorizontalPodAutoscaler
29 | metadata:
30 | name: eplastweb-autoscaler
31 | spec:
32 | scaleTargetRef:
33 | apiVersion: apps/v1
34 | kind: Deployment
35 | name: eplastweb
36 | targetCPUUtilizationPercentage: 70
37 | minReplicas: 1
38 | maxReplicas: 2
39 |
--------------------------------------------------------------------------------
/src/pages/AnnualReport/Interfaces/ClubAnnualReport.ts:
--------------------------------------------------------------------------------
1 | import Club from "../../../models/Club/Club";
2 | import ClubAdmin from "../../../models/Club/ClubAdmin";
3 | import ClubMember from "../../../models/Club/ClubMember";
4 |
5 | interface ClubAnnualReport {
6 | id: number;
7 | idView: any;
8 | name: string;
9 | status: number;
10 | date: Date;
11 | currentClubMembers: number;
12 | currentClubFollowers: number;
13 | clubEnteredMembersCount: number;
14 | clubLeftMembersCount: number;
15 | clubCenters: string;
16 | clubContacts: string;
17 | clubPage: string;
18 | kbUSPWishes: string;
19 | clubId: number;
20 | club: Club | null;
21 | clubMembersSummary: string;
22 | clubAdminContacts: string;
23 | clubName: string;
24 | email?: string;
25 | phoneNumber?: string;
26 | head?: ClubAdmin;
27 | members?: ClubMember[];
28 | admins?: ClubAdmin[];
29 | followers?: ClubMember[];
30 | }
31 |
32 | export default ClubAnnualReport;
33 |
--------------------------------------------------------------------------------
/src/pages/UserTable/AcceptUserToCityModal.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Modal } from "antd";
3 | import AcceptUserToCityForm from "./AcceptUserToCityForm";
4 |
5 | interface Props {
6 | onChange: (id: string, userRoles: string) => void;
7 | record: string;
8 | showModal: boolean;
9 | setShowModal: (showModal: any) => void;
10 | user: any;
11 | }
12 | const AcceptUserToCityModal = ({
13 | record,
14 | showModal,
15 | setShowModal,
16 | onChange,
17 | }: Props) => {
18 | return (
19 | setShowModal(false)}
25 | >
26 |
32 |
33 | );
34 | };
35 |
36 | export default AcceptUserToCityModal;
37 |
--------------------------------------------------------------------------------
/src/models/City/CityProfile.tsx:
--------------------------------------------------------------------------------
1 | import UkraineOblasts from "../Oblast/UkraineOblasts";
2 | import CityAdmin from "./CityAdmin";
3 |
4 | export default class CityProfile {
5 | id: number;
6 | name: string;
7 | logo: string | null;
8 | description: string;
9 | cityURL: string;
10 | phoneNumber: string;
11 | email: string;
12 | region: string;
13 | address: string;
14 | level: number;
15 | head: CityAdmin;
16 | headDeputy: CityAdmin;
17 | isActive: boolean;
18 | oblast: UkraineOblasts;
19 | constructor() {
20 | this.id = 0;
21 | this.name = "";
22 | this.logo = "";
23 | this.description = "";
24 | this.cityURL = "";
25 | this.phoneNumber = "";
26 | this.email = "";
27 | this.region = "";
28 | this.address = "";
29 | this.level = 1;
30 | this.head = new CityAdmin();
31 | this.headDeputy = new CityAdmin();
32 | this.isActive = true;
33 | this.oblast = UkraineOblasts.NotSpecified;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/pages/AboutBase/AddSubsectionModal.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Drawer } from "antd";
3 | import FormAddSubsection from "./FormAddSubsection";
4 |
5 | interface Props {
6 | visibleModal: boolean;
7 | setVisibleModal: (visibleModal: boolean) => void;
8 | sectId: number;
9 | fetchSubData: Function;
10 | }
11 |
12 | const AddSubsectionModal = ({
13 | visibleModal,
14 | setVisibleModal,
15 | sectId,
16 | fetchSubData,
17 | }: Props) => {
18 | const handleCancel = () => {
19 | setVisibleModal(false);
20 | };
21 | return (
22 |
29 |
34 |
35 | );
36 | };
37 |
38 | export default AddSubsectionModal;
39 |
--------------------------------------------------------------------------------
/src/pages/Regions/Form.module.css:
--------------------------------------------------------------------------------
1 |
2 |
3 | .formSelectAlignCenter{
4 | align-Items: flex-start;
5 | }
6 |
7 |
8 | .inputField{
9 | float: right;
10 | text-align: left;
11 |
12 |
13 | }
14 |
15 | .datePicker {
16 | width: 100%;
17 | }
18 |
19 | .submitRow{
20 | flex-direction: row-reverse;
21 | }
22 |
23 | @media (max-width: 576px){
24 | .inputField{
25 | width: 100%;
26 | }
27 | }
28 |
29 |
30 | .selectField {
31 | float: right;
32 | text-align: left;
33 | width:320px;
34 |
35 | }
36 |
37 | .formOption {
38 | display: flex;
39 | justify-content: space-between;
40 | align-items: center;
41 | }
42 |
43 | .formField {
44 | width: 100%;
45 | }
46 |
47 | .cardButton{
48 | float: right;
49 | inline-size: -webkit-fill-available;
50 | margin-top: 7px;
51 | color:#3c5438;
52 | border-color: #3c5438;
53 | max-width: 320px;
54 | min-width: 320px;
55 | }
--------------------------------------------------------------------------------
/src/components/ImagePreview/ImagePreview.less:
--------------------------------------------------------------------------------
1 | .modal-wrapper {
2 | display: flex;
3 | justify-content: center;
4 | align-items: center;
5 | top: 0;
6 | width: auto !important;
7 | height: 100% !important;
8 | margin: 0 !important;
9 | padding: 0 !important;
10 | }
11 |
12 | .modal-wrapper .ant-modal-content .ant-modal-close .ant-modal-close-x {
13 | color: white;
14 | position: fixed;
15 | top: 0;
16 | right: 0;
17 | }
18 |
19 | .modal-wrapper .ant-modal-content {
20 | background: none;
21 | box-shadow: none;
22 | }
23 |
24 | .modal-wrapper .ant-modal-body {
25 | padding: 0;
26 | display: flex;
27 | justify-content: center;
28 | }
29 |
30 | .image {
31 | max-height: 90vh;
32 | max-width: 90%;
33 | margin: auto;
34 | }
35 |
36 | .file-name {
37 | padding-top: 15px;
38 | padding-left: 20px;
39 | position: fixed;
40 |
41 | top: 0;
42 | left: 0;
43 |
44 | font-size: 15px;
45 | color: white;
46 | text-shadow: 0 0 1px black;
47 | }
48 |
--------------------------------------------------------------------------------
/src/pages/UserTable/DeleteGoverningBodyAdminModal.tsx:
--------------------------------------------------------------------------------
1 | import { Modal } from "antd";
2 | import React from "react";
3 | import DeleteGoverningBodyAdminForm from "./DeleteGoverningBodyAdminForm";
4 |
5 | interface Props {
6 | onChange: (id: string, userRoles: string) => void;
7 | showModal: boolean;
8 | setShowModal: (showModal: any) => void;
9 | user: any;
10 | }
11 |
12 | const DeleteGoverningBodyAdminModal = ({
13 | user,
14 | showModal,
15 | setShowModal,
16 | onChange,
17 | }: Props) => {
18 | return (
19 | setShowModal(false)}
25 | destroyOnClose
26 | >
27 |
32 |
33 | );
34 | };
35 |
36 | export default DeleteGoverningBodyAdminModal;
37 |
--------------------------------------------------------------------------------
/src/models/Region/RegionProfile.tsx:
--------------------------------------------------------------------------------
1 | import { UkraineOblasts } from "../Oblast/UkraineOblasts";
2 |
3 | export default class RegionProfile {
4 | id: number;
5 |
6 | regionName: string;
7 |
8 | logo: string | null;
9 |
10 | description: string;
11 |
12 | link: string;
13 |
14 | phoneNumber: string;
15 |
16 | email: string;
17 |
18 | oblast: UkraineOblasts;
19 |
20 | city: string;
21 |
22 | street: string;
23 |
24 | houseNumber: string;
25 |
26 | officeNumber: string;
27 |
28 | postIndex: string;
29 |
30 | isActive: boolean;
31 |
32 | constructor() {
33 | this.id = 0;
34 | this.regionName = "";
35 | this.logo = "";
36 | this.description = "";
37 | this.link = "";
38 | this.phoneNumber = "";
39 | this.email = "";
40 | this.city = "";
41 | this.street = "";
42 | this.houseNumber = "";
43 | this.officeNumber = "";
44 | this.oblast = UkraineOblasts.NotSpecified;
45 | this.postIndex = "";
46 | this.isActive = true;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/pages/Actions/EventTypes/EventTypeCard.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Card } from "antd";
3 | import EvenTypeLogo from "../../../assets/images/ActionLogo.png";
4 |
5 | import { useHistory } from "react-router-dom";
6 |
7 | const classes = require("./EventTypeCard.module.css");
8 |
9 | interface CardProps {
10 | id: number;
11 | eventTypeName: string;
12 | }
13 |
14 | interface Props {
15 | item: CardProps;
16 | }
17 |
18 | const EventTypeCard = ({ item: { id, eventTypeName } }: Props) => {
19 | const { Meta } = Card;
20 | const history = useHistory();
21 |
22 | return (
23 |
24 | }
29 | onClick={() => history.push(`/events/${id}/categories`)}
30 | >
31 |
32 |
33 |
34 | );
35 | };
36 | export default EventTypeCard;
37 |
--------------------------------------------------------------------------------
/src/pages/UserTable/ChangeUserGoverningBodyModal.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Modal } from "antd";
3 | import ChangeUserGoverningBodyForm from "./ChangeUserGoverningBodyForm";
4 |
5 | interface Props {
6 | onChange: (id: string, userRoles: string) => void;
7 | record: string;
8 | showModal: boolean;
9 | setShowModal: (showModal: any) => void;
10 | user: any;
11 | }
12 | const ChangeUserGoverningBodyModal = ({
13 | record,
14 | showModal,
15 | setShowModal,
16 | onChange,
17 | user,
18 | }: Props) => {
19 | return (
20 | setShowModal(false)}
26 | destroyOnClose
27 | >
28 |
34 |
35 | );
36 | };
37 |
38 | export default ChangeUserGoverningBodyModal;
39 |
--------------------------------------------------------------------------------
/craco.config.js:
--------------------------------------------------------------------------------
1 | const CracoLessPlugin = require("craco-less");
2 |
3 | module.exports = {
4 | plugins: [
5 | {
6 | plugin: CracoLessPlugin,
7 | options: {
8 | lessLoaderOptions: {
9 | lessOptions: {
10 | modifyVars: {
11 | "@primary-color": "#3c5438",
12 | "@layout-header-background": "#3c5438",
13 | "@layout-footer-background": "#3c5438",
14 | "@layout-sider-background": "#3c5438",
15 | "@menu-dark-item-hover-bg": "transparent",
16 | "@menu-bg": "#3c5438",
17 | "@menu-item-active-border-width": "none",
18 | "@dropdown-menu-bg": "#3c5438",
19 | "@menu-dark-submenu-bg": "#3c5438",
20 | "@layout-trigger-background": "#3c5438",
21 | "@tooltip-bg": "#3c5438",
22 | "@item-hover-bg": "transparent",
23 | },
24 | javascriptEnabled: true,
25 | },
26 | },
27 | },
28 | },
29 | ],
30 | };
31 |
--------------------------------------------------------------------------------
/src/pages/AnnualReport/ClubMembersTable.tsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState, PropsWithRef } from "react";
2 | import { Table, Spin, Input } from "antd";
3 | import columns from "./columnsClubsMembers";
4 | import { getUsersAdministrations } from "../../api/clubsApi";
5 |
6 | interface props {
7 | UserId: string;
8 | }
9 |
10 | export const ClubMembersTable = ({ UserId }: props) => {
11 | const [data, setData] = useState([
12 | {
13 | id: "",
14 | user: "",
15 | adminType: "",
16 | startDate: "",
17 | endDate: "",
18 | clubId: "",
19 | },
20 | ]);
21 |
22 | const fetchData = async () => {
23 | await getUsersAdministrations(UserId).then((response: { data: any }) => {
24 | setData(response.data);
25 | });
26 | };
27 |
28 | useEffect(() => {
29 | fetchData();
30 | }, []);
31 |
32 | return (
33 |
34 |
Список членів куреня:
35 |
36 |
37 |
38 | );
39 | };
40 |
--------------------------------------------------------------------------------
/src/pages/Actions/ActionEvent/EventInfo/EventDetailsHeader.less:
--------------------------------------------------------------------------------
1 | .descriptions {
2 | width: 100%;
3 | padding: 10px 10px 0 10px;
4 | text-overflow: ellipsis;
5 |
6 | @media (max-width: 750px) {
7 | .ant-descriptions-view > table {
8 | table-layout: fixed;
9 | }
10 | }
11 | }
12 |
13 | .descriptions-item {
14 | background: none !important;
15 | //background-color: rgba(0, 0, 0, 0.05) !important;
16 | border: none !important;
17 | }
18 |
19 | .eventLabel {
20 | color: var(--antd-wave-shadow-color);
21 | font-weight: bold;
22 | }
23 |
24 | .url {
25 | font-weight: bold;
26 | width: 190px;
27 | font-size: 14px;
28 | }
29 |
30 | /* unvisited link */
31 | .ant-typography a:link {
32 | color: rgba(0, 0, 0, 0.65);
33 | }
34 |
35 | /* visited link */
36 | .ant-typography a:visited {
37 | color: rgb(24, 68, 24);
38 | }
39 |
40 | /* mouse over link */
41 | .ant-typography a:hover {
42 | color: rgba(206, 50, 50, 0.65);
43 | }
44 |
45 | /* selected link */
46 | .ant-typography a:active {
47 | color: grey;
48 | }
49 |
--------------------------------------------------------------------------------
/src/components/PrivateLayout/useOneClickOutside.tsx:
--------------------------------------------------------------------------------
1 | import { RefObject, useEffect } from "react";
2 |
3 | type AnyEvent = MouseEvent | TouchEvent;
4 |
5 | function useOnClickOutside(
6 | ref: RefObject,
7 | handler: (event: AnyEvent) => void
8 | ) {
9 | useEffect(() => {
10 | const listener = (event: AnyEvent) => {
11 | const el = ref?.current;
12 |
13 | // Do nothing if clicking ref's element or descendent elements
14 | if (!ref?.current || ref?.current.contains(event.target as Node)) {
15 | return;
16 | }
17 |
18 | handler(event);
19 | };
20 |
21 | document.addEventListener(`mousedown`, listener);
22 | document.addEventListener(`touchstart`, listener);
23 |
24 | return () => {
25 | document.removeEventListener(`mousedown`, listener);
26 | document.removeEventListener(`touchstart`, listener);
27 | };
28 |
29 | // Reload only if ref or handler changes
30 | }, [ref, handler]);
31 | }
32 |
33 | export default useOnClickOutside;
34 |
--------------------------------------------------------------------------------
/src/models/Club/ClubUser.tsx:
--------------------------------------------------------------------------------
1 | import { PlastDegree } from "../../api/activeMembershipApi";
2 |
3 | export default class ClubUser {
4 | id: string;
5 | firstName: string;
6 | lastName: string;
7 | imagePath: string;
8 | email: string;
9 | phoneNumber: string;
10 | userRole: string;
11 | cityName: string;
12 | userPlastDegrees: any;
13 | cityMembers: any;
14 | clubReportCities: any;
15 | clubReportPlastDegrees: any;
16 |
17 | constructor() {
18 | this.id = "";
19 | this.firstName = "";
20 | this.lastName = "";
21 | this.imagePath = "";
22 | this.email = "";
23 | this.phoneNumber = "";
24 | this.userRole = "";
25 | this.cityName = "";
26 | this.userPlastDegrees = {
27 | plastDegree: { id: -1, name: "" },
28 | };
29 | this.cityMembers = {
30 | city: { id: -1, name: "" },
31 | };
32 | this.userPlastDegrees = {
33 | plastDegree: { id: -1, name: "" },
34 | };
35 | this.userPlastDegrees = {
36 | plastDegree: { id: -1, name: "" },
37 | };
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/models/Roles/AdminRole.tsx:
--------------------------------------------------------------------------------
1 | export enum AdminRole {
2 | Admin = 0, // Admin
3 | GoverningBodyAdmin = 1, // Крайовий адмін
4 | GoverningBodyHead = 2, // Голова керівного органу
5 | OkrugaHead = 3, // Голова округи
6 | OkrugaHeadDeputy = 4, // Заступник голови округи
7 | CityHead = 5, // Голова станиці
8 | CityHeadDeputy = 6, // Заступник голови станиці
9 | KurinHead = 7, // Голова куреня
10 | KurinHeadDeputy = 8, // Заступник голови куреня
11 | OkrugaReferentUPS = 9, // Референт/-ка УПС Округи
12 | OkrugaReferentUSP = 10, // Референт/-ка УСП Округи
13 | OkrugaReferentOfActiveMembership = 11, // Референт дійсного членства Округи
14 | CityReferentUPS = 12, // Референт/-ка УПС Станиці
15 | CityReferentUSP = 13, // Референт/-ка УСП Станиці
16 | CityReferentOfActiveMembership = 14, // Референт дійсного членства Станиці
17 | }
18 |
19 | // This enum is used to compare which one of two admins has more rights (user table)
20 | // Roles in enum must be written strictly in descending order, starting with
21 | // role with most rights ('Admin')
22 |
--------------------------------------------------------------------------------
/src/pages/SignIn/FacebookLoginWrapper.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import facebookImg from "../../assets/images/facebook.png";
3 | import FacebookLogin from "react-facebook-login";
4 | import styles from "./SignIn.module.css";
5 |
6 | const FacebookLoginWrapper = (props: any) => {
7 | const responseFacebook = (response: any) => {
8 | if (response.status !== "unknown") {
9 | props.handleFacebookResponse(response);
10 | }
11 | };
12 | return (
13 |
21 |
26 |
27 | }
28 | textButton=" Facebook"
29 | />
30 | );
31 | };
32 | export default FacebookLoginWrapper;
33 |
--------------------------------------------------------------------------------
/src/pages/UserTable/ChangeUserRoleModal.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Modal } from "antd";
3 | import ChangeUserRoleForm from "./ChangeUserRoleForm";
4 | import "./ChangeUserRoleModal.less";
5 | import Form from "antd/lib/form/Form";
6 |
7 | interface Props {
8 | record: string;
9 | showModal: boolean;
10 | setShowModal: (showModal: any) => void;
11 | onChange: (id: string, userRoles: string) => void;
12 | user: any;
13 | }
14 | const ChangeUserRoleModal = ({
15 | record,
16 | showModal,
17 | setShowModal,
18 | onChange,
19 | user,
20 | }: Props) => {
21 | return (
22 | setShowModal(false)}
28 | destroyOnClose={true}
29 | >
30 |
36 |
37 | );
38 | };
39 |
40 | export default ChangeUserRoleModal;
41 |
--------------------------------------------------------------------------------
/src/pages/RegionsBoard/AddMainAdministratorModal/AddRegionBoardMainAdminModal.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Modal } from "antd";
3 | import AddRegionBoardMainAdminForm from "./AddRegionBoardMainAdminForm";
4 |
5 | interface Props {
6 | visibleModal: boolean;
7 | setVisibleModal: (visibleModal: boolean) => void;
8 | handleAddGoverningBodyAdmin: (values: any) => void;
9 | }
10 |
11 | const AddRegionBoardMainAdminModal = ({
12 | visibleModal,
13 | setVisibleModal,
14 | handleAddGoverningBodyAdmin,
15 | }: Props) => {
16 | const handleCancel = () => setVisibleModal(false);
17 |
18 | return (
19 |
25 |
30 |
31 | );
32 | };
33 |
34 | export default AddRegionBoardMainAdminModal;
35 |
--------------------------------------------------------------------------------
/src/pages/Contacts/Contacts.module.css:
--------------------------------------------------------------------------------
1 | #environmentOutlined{
2 | font-size: 24px;
3 | margin-right: 20px;
4 | }
5 |
6 | #InfoOut{
7 | font-size: 24px;
8 | margin: 5px 20px 0 0;
9 | }
10 |
11 | #addonElement{
12 | width: 100%;
13 | }
14 |
15 | .contacts {
16 | display: flex;
17 | justify-content: space-evenly;
18 | margin-top: 50px;
19 | }
20 |
21 | .contactsList {
22 | width: 20%;
23 | }
24 |
25 | .contactsForm {
26 | width: 30%;
27 | }
28 |
29 | .contactsForm button {
30 | height: 40px;
31 | width: 100%;
32 | }
33 |
34 | @media (max-width: 576px) {
35 | .contacts {
36 | display: flex;
37 | flex-direction: column;
38 | padding: 0 30px;
39 | }
40 |
41 | .contactsList,
42 | .contactsForm {
43 | width: 100%;
44 | }
45 |
46 | .contactsList h1 {
47 | margin-left: 25px;
48 | }
49 |
50 | .contactsForm {
51 | margin-top: 40px;
52 | }
53 | }
54 |
55 | @media (min-width: 576px)and(max-width: 768px) {
56 | .contacts {
57 | justify-content: space-around;
58 | }
59 |
60 | .contactsList {
61 | width: 30%;
62 | }
63 | }
64 |
65 |
--------------------------------------------------------------------------------
/src/components/Footer/FooterContainer.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Layout } from "antd";
3 | import Facebook from "../../assets/images/facebook.svg";
4 | import Twitter from "../../assets/images/bird.svg";
5 | import Instagram from "../../assets/images/instagram.svg";
6 | import classes from "./Footer.module.css";
7 | import moment from "moment";
8 |
9 | const FooterContainer = () => {
10 | return (
11 |
12 |
23 |
24 | ePlast © {moment().format("YYYY")}
25 |
26 |
27 | );
28 | };
29 | export default FooterContainer;
30 |
--------------------------------------------------------------------------------
/src/pages/Distinction/DistinctionTable/FormEdit.module.css:
--------------------------------------------------------------------------------
1 | .editIcon {
2 | font-size: 24px;
3 | color: #3c5438;
4 | }
5 | .editIcon :hover {
6 | color: #536150;
7 | cursor: pointer;
8 | }
9 | .deleteIcon {
10 | font-size: 24px;
11 | color: #910202;
12 | }
13 | .deleteIcon :hover {
14 | color: #690606;
15 | cursor: pointer;
16 | }
17 | .editDiv {
18 | display: flex;
19 | justify-content: space-between;
20 | align-items: center;
21 | }
22 | .list {
23 | max-height: 400px;
24 | overflow: auto;
25 | max-width: 520px;
26 | font-size: 16px;
27 | display: flex;
28 | }
29 | .inputField {
30 | size: 50px;
31 | margin-right: auto;
32 | float: right;
33 | text-align: left;
34 | }
35 |
36 | .list > * {
37 | width: 100%;
38 | }
39 |
40 | .buttons {
41 | margin-right: 0px !important;
42 | margin-left: 7px;
43 | }
44 |
45 | @media (max-width: 490px) {
46 | .list {
47 | max-width: 400px;
48 | font-size: 16px;
49 | }
50 | .editIcon {
51 | font-size: 18px;
52 | color: #3c5438;
53 | }
54 | .deleteIcon {
55 | font-size: 18px;
56 | color: #910202;
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/pages/AnnualReport/Interfaces/AnnualReport.ts:
--------------------------------------------------------------------------------
1 | import MembersStatistic from "./MembersStatistic";
2 | import User from "./User";
3 | import City from "./City";
4 |
5 | interface AnnualReport {
6 | id: number;
7 | idView: any;
8 | date: Date;
9 | status: number;
10 | numberOfSeatsPtashat: number;
11 | numberOfIndependentRiy: number;
12 | numberOfClubs: number;
13 | numberOfIndependentGroups: number;
14 | numberOfTeachers: number;
15 | numberOfAdministrators: number;
16 | numberOfTeacherAdministrators: number;
17 | numberOfBeneficiaries: number;
18 | numberOfPlastpryiatMembers: number;
19 | numberOfHonoraryMembers: number;
20 | publicFunds: number;
21 | contributionFunds: number;
22 | plastSalary: number;
23 | sponsorshipFunds: number;
24 | listProperty: string | null;
25 | improvementNeeds: string | null;
26 | membersStatistic: MembersStatistic;
27 | creatorId: string;
28 | creator: User | null;
29 | newCityAdminId: string;
30 | newCityAdmin: User | null;
31 | newCityLegalStatusType: number;
32 | cityId: number;
33 | city: City | null;
34 | }
35 |
36 | export default AnnualReport;
37 |
--------------------------------------------------------------------------------
/src/pages/SignUp/CheckboxsItem.tsx:
--------------------------------------------------------------------------------
1 | import { Checkbox, Form, Space } from "antd";
2 | import React from "react";
3 | import { emptyInput } from "../../components/Notifications/Messages";
4 |
5 | interface RadioOrInputProps {
6 | checkboxList: string[]
7 | title: string
8 | name: string
9 | }
10 |
11 | const CheckboxsItem: React.FC = ({ checkboxList, title, name }) => {
12 | return (
13 | {title}}
20 | name={name}
21 | rules={[{ required: true, message: emptyInput() }]}
22 | >
23 |
24 |
25 | {checkboxList.map(c =>
26 | {c}
27 | )}
28 |
29 |
30 |
31 | );
32 | }
33 |
34 | export default CheckboxsItem;
--------------------------------------------------------------------------------
/src/pages/Precaution/PrecautionTable/FormEdit.module.css:
--------------------------------------------------------------------------------
1 | .editIcon {
2 | font-size: 24px;
3 | color:#3c5438;
4 | }
5 | .editIcon :hover {
6 | color: #536150;
7 | cursor: pointer;
8 | }
9 | .deleteIcon {
10 | font-size: 24px;
11 | color: #910202;
12 | }
13 | .deleteIcon :hover{
14 | color: #690606;
15 | cursor: pointer;
16 | }
17 | .editDiv{
18 | display: flex;
19 | justify-content: space-between;
20 | align-items: center;
21 | }
22 | .list {
23 | max-width: 520px;
24 | font-size: 18px;
25 | display: flex;
26 | }
27 | .inputField {
28 | size: 50px;
29 | margin-right: auto;
30 | float: right;
31 | text-align: left;
32 | }
33 | .list>* {
34 | width: 100%
35 | }
36 |
37 | @media (max-width: 490px){
38 | .list{
39 | max-width: 400px;
40 | font-size: 12px;
41 | }
42 | .editIcon {
43 | font-size: 18px;
44 | color:#3c5438;
45 | }
46 | .deleteIcon {
47 | font-size: 18px;
48 | color: #910202;
49 | }
50 |
51 | }
52 | .buttons{
53 | margin-right: 0px !important;
54 | margin-left: 7px;
55 | }
56 |
57 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 SoftServe IT Academy
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/pages/AnnualReport/Interfaces/RegionMembersInfo.tsx:
--------------------------------------------------------------------------------
1 | interface RegionMembersInfo {
2 | total: number;
3 | cityAnnualReportId: number;
4 | cityId: number;
5 | reportStatus: number;
6 | cityName: string;
7 | numberOfSeatsPtashat: number;
8 | numberOfIndependentRiy: number;
9 | numberOfClubs: number;
10 | numberOfIndependentGroups: number;
11 | numberOfTeachers: number;
12 | numberOfAdministrators: number;
13 | numberOfTeacherAdministrators: number;
14 | numberOfBeneficiaries: number;
15 | numberOfPlastpryiatMembers: number;
16 | numberOfHonoraryMembers: number;
17 | numberOfPtashata: number;
18 | numberOfNovatstva: number;
19 | numberOfUnatstva: number;
20 | numberOfUnatstvaNoname: number;
21 | numberOfUnatstvaSupporters: number;
22 | numberOfUnatstvaMembers: number;
23 | numberOfUnatstvaProspectors: number;
24 | numberOfUnatstvaSkobVirlyts: number;
25 | numberOfSenior: number;
26 | numberOfSeniorPlastynSupporters: number;
27 | numberOfSeniorPlastynMembers: number;
28 | numberOfSeigneur: number;
29 | numberOfSeigneurSupporters: number;
30 | numberOfSeigneurMembers: number;
31 | }
32 |
33 | export default RegionMembersInfo;
34 |
--------------------------------------------------------------------------------
/src/pages/DecisionTable/EditDecisionModal.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Modal, Drawer } from "antd";
3 | import FormEditDecision from "./FormEditDecision";
4 | import { DecisionPost } from "../../api/decisionsApi";
5 |
6 | interface Props {
7 | record: number;
8 | decision: DecisionPost;
9 | showModal: boolean;
10 | setShowModal: (showModal: boolean) => void;
11 | onEdit: (
12 | id: number,
13 | name: string,
14 | description: string,
15 | statusType: string
16 | ) => void;
17 | }
18 | const EditDecisionModal = ({
19 | record,
20 | showModal,
21 | setShowModal,
22 | onEdit,
23 | decision,
24 | }: Props) => {
25 | const handleCancel = () => setShowModal(false);
26 |
27 | return (
28 |
35 |
41 |
42 | );
43 | };
44 |
45 | export default EditDecisionModal;
46 |
--------------------------------------------------------------------------------
/src/pages/SignIn/GoogleLoginWrapper.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Button } from "antd";
3 | import googleImg from "../../assets/images/google.png";
4 | import { GoogleLogin } from "react-google-login";
5 | import styles from "./SignIn.module.css";
6 |
7 | const GoogleLoginWrapper = (props: any) => {
8 | return (
9 | (
12 |
27 | )}
28 | buttonText="Login"
29 | onSuccess={props.handleGoogleResponse}
30 | onFailure={props.getIdprop}
31 | cookiePolicy={"single_host_origin"}
32 | />
33 | );
34 | };
35 | export default GoogleLoginWrapper;
36 |
--------------------------------------------------------------------------------
/src/pages/SignUp/TabList.tsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from "react";
2 | import styles from "./SignUp.module.css";
3 |
4 | import { Tabs } from "antd";
5 | const { TabPane } = Tabs;
6 |
7 | export enum TabRenderMode {
8 | Default,
9 | UnmountOther,
10 | }
11 |
12 | interface TabInputsProps {
13 | renderMode: TabRenderMode
14 | pairs: {
15 | title: string
16 | content: JSX.Element
17 | disabled?: boolean
18 | }[]
19 | }
20 |
21 | const TabList: React.FC = ({ pairs, renderMode }) => {
22 | const [activeTab, setActiveTab] = useState(0);
23 |
24 | const handleChange = (key: number) => {
25 | setActiveTab(key)
26 | }
27 |
28 | return (
29 | handleChange(Number(e))} defaultActiveKey={activeTab.toString()}>
30 | {pairs.map((p, i) =>
31 |
32 | {renderMode === TabRenderMode.UnmountOther &&
33 | activeTab !== i ? <>> : p.content}
34 |
35 | )}
36 |
37 | );
38 | }
39 |
40 | export default TabList;
--------------------------------------------------------------------------------
/src/pages/Actions/ActionEvent/EventEdit/EventEditDrawer.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Drawer, Button } from "antd";
3 | import EventEdit from "./EventEdit";
4 | import ButtonCollapse from "../../../../components/ButtonCollapse/ButtonCollapse";
5 |
6 | interface Props {
7 | visibleEventEditDrawer: boolean;
8 | setShowEventEditDrawer: (visibleEventEditDrawer: boolean) => void;
9 | id: number;
10 | statusId: number;
11 | onEdit: () => void;
12 | }
13 |
14 | const EventEditDrawer = ({
15 | visibleEventEditDrawer,
16 | setShowEventEditDrawer,
17 | id,
18 | statusId,
19 | onEdit,
20 | }: Props) => {
21 | const handleCancel = () => setShowEventEditDrawer(false);
22 | return (
23 |
32 |
38 |
39 | );
40 | };
41 |
42 | export default EventEditDrawer;
43 |
--------------------------------------------------------------------------------
/src/pages/Actions/ActionEvent/EventInfo/GalleryPictureAdd.tsx:
--------------------------------------------------------------------------------
1 | import { PlusOutlined } from "@ant-design/icons";
2 | import { Modal } from "antd";
3 | import React, { useState } from "react";
4 | import FormAddPictures from "./FormAddPictures";
5 | import "./GalleryPicture.less";
6 |
7 | interface AddPictureProps {
8 | eventId: number;
9 | pictureList: number[];
10 | addPicturesHook: (pictures: number[]) => void;
11 | }
12 |
13 | const GalleryPictureAdd: React.FC = (p: AddPictureProps) => {
14 | const [isModalVisible, setModalVisible] = useState(false);
15 |
16 | return (
17 |
18 |
setModalVisible(true)}
21 | />
22 | setModalVisible(false)}
27 | >
28 |
33 |
34 |
35 | );
36 | };
37 |
38 | export default GalleryPictureAdd;
39 |
--------------------------------------------------------------------------------
/src/pages/GoverningBody/Announcement/AddAnnouncementModal.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Drawer } from "antd";
3 | import FormAddAnnouncement from "./FormAddAnnouncement";
4 |
5 | interface Props {
6 | governingBodyId?: number;
7 | visibleModal: boolean;
8 | setVisibleModal: (visibleModal: boolean) => void;
9 | onAdd: (
10 | title: string,
11 | text: string,
12 | images: string[],
13 | isPined: boolean,
14 | gvbId: number,
15 | sectorId: number
16 | ) => void;
17 | }
18 |
19 | const AddAnnouncementModal = ({
20 | governingBodyId,
21 | visibleModal,
22 | setVisibleModal,
23 | onAdd,
24 | }: Props) => {
25 | const handleCancel = () => {
26 | setVisibleModal(false);
27 | };
28 | return (
29 |
38 |
43 |
44 | );
45 | };
46 |
47 | export default AddAnnouncementModal;
48 |
--------------------------------------------------------------------------------
/src/pages/userPage/Secretaries/columnsSectors.tsx:
--------------------------------------------------------------------------------
1 | import moment from "moment";
2 |
3 | const minDate = "01.01.0001";
4 |
5 | const columns = [
6 | {
7 | title: "ID",
8 | dataIndex: "id",
9 | },
10 | {
11 | title: "Користувач",
12 | dataIndex: "userName",
13 | render: (userName: string) => {
14 | return userName;
15 | },
16 | },
17 | {
18 | title: "Тип адміністрування",
19 | dataIndex: "adminType",
20 | render: (adminType: string) => {
21 | return adminType;
22 | },
23 | },
24 | {
25 | title: "Початок каденції",
26 | dataIndex: "startDate",
27 | render: (startDate: Date) => {
28 | return moment.utc(startDate).local().format("DD.MM.YYYY");
29 | },
30 | },
31 | {
32 | title: "Кінець каденції",
33 | dataIndex: "endDate",
34 | render: (endDate: Date) => {
35 | const instanceDate = moment.utc(endDate).local().format("DD.MM.YYYY");
36 | return instanceDate === minDate ? " Не закінчена " : instanceDate;
37 | },
38 | },
39 | {
40 | title: "Напрям",
41 | dataIndex: "sectorName",
42 | render: (sectorName: string) => {
43 | return sectorName;
44 | },
45 | },
46 | ];
47 |
48 | export default columns;
49 |
--------------------------------------------------------------------------------
/src/pages/WebChat/Demo.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from "react";
2 | import { Launcher } from "react-chat-window";
3 |
4 | export class Demo extends Component {
5 | constructor() {
6 | super();
7 | this.state = {
8 | messageList: [],
9 | };
10 | }
11 |
12 | _onMessageWasSent(message) {
13 | this.setState({
14 | messageList: [...this.state.messageList, message],
15 | });
16 | }
17 |
18 | _sendMessage(text) {
19 | if (text.length > 0) {
20 | this.setState({
21 | messageList: [
22 | ...this.state.messageList,
23 | {
24 | author: "them",
25 | type: "text",
26 | data: { text },
27 | },
28 | ],
29 | });
30 | }
31 | }
32 |
33 | render() {
34 | return (
35 |
36 |
46 |
47 | );
48 | }
49 | }
50 |
--------------------------------------------------------------------------------