Add salw_client
23
salw_client/.gitignore
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
/node_modules
|
||||||
|
/.pnp
|
||||||
|
.pnp.js
|
||||||
|
|
||||||
|
# testing
|
||||||
|
/coverage
|
||||||
|
|
||||||
|
# production
|
||||||
|
/build
|
||||||
|
|
||||||
|
# misc
|
||||||
|
.DS_Store
|
||||||
|
.env.local
|
||||||
|
.env.development.local
|
||||||
|
.env.test.local
|
||||||
|
.env.production.local
|
||||||
|
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
1
salw_client/.npmrc
Normal file
@ -0,0 +1 @@
|
|||||||
|
//registry.npmjs.org/:_authToken=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
|
37
salw_client/Dockerfile
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
# Front-End
|
||||||
|
|
||||||
|
# frontend/Dockerfile
|
||||||
|
|
||||||
|
# Build stage
|
||||||
|
FROM node:18 AS build
|
||||||
|
|
||||||
|
# Set working directory
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Copy package.json and package-lock.json
|
||||||
|
COPY package.json ./
|
||||||
|
COPY package-lock.json ./
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
RUN npm install
|
||||||
|
|
||||||
|
# Copy the rest of the application code
|
||||||
|
COPY . ./
|
||||||
|
|
||||||
|
# Build the React app
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# Production stage
|
||||||
|
FROM nginx:stable-alpine
|
||||||
|
|
||||||
|
# Copy the build output to nginx html directory
|
||||||
|
COPY --from=build /app/build /usr/share/nginx/html
|
||||||
|
|
||||||
|
# Copy the custom Nginx configuration file
|
||||||
|
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||||
|
|
||||||
|
# Expose port 80
|
||||||
|
EXPOSE 80
|
||||||
|
|
||||||
|
# Start nginx
|
||||||
|
CMD ["nginx", "-g", "daemon off;"]
|
70
salw_client/README.md
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
# Getting Started with Create React App
|
||||||
|
|
||||||
|
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
|
||||||
|
|
||||||
|
## Available Scripts
|
||||||
|
|
||||||
|
In the project directory, you can run:
|
||||||
|
|
||||||
|
### `npm start`
|
||||||
|
|
||||||
|
Runs the app in the development mode.\
|
||||||
|
Open [http://localhost:3000](http://localhost:3000) to view it in your browser.
|
||||||
|
|
||||||
|
The page will reload when you make changes.\
|
||||||
|
You may also see any lint errors in the console.
|
||||||
|
|
||||||
|
### `npm test`
|
||||||
|
|
||||||
|
Launches the test runner in the interactive watch mode.\
|
||||||
|
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
|
||||||
|
|
||||||
|
### `npm run build`
|
||||||
|
|
||||||
|
Builds the app for production to the `build` folder.\
|
||||||
|
It correctly bundles React in production mode and optimizes the build for the best performance.
|
||||||
|
|
||||||
|
The build is minified and the filenames include the hashes.\
|
||||||
|
Your app is ready to be deployed!
|
||||||
|
|
||||||
|
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
|
||||||
|
|
||||||
|
### `npm run eject`
|
||||||
|
|
||||||
|
**Note: this is a one-way operation. Once you `eject`, you can't go back!**
|
||||||
|
|
||||||
|
If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
|
||||||
|
|
||||||
|
Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own.
|
||||||
|
|
||||||
|
You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it.
|
||||||
|
|
||||||
|
## Learn More
|
||||||
|
|
||||||
|
You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
|
||||||
|
|
||||||
|
To learn React, check out the [React documentation](https://reactjs.org/).
|
||||||
|
|
||||||
|
### Code Splitting
|
||||||
|
|
||||||
|
This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting)
|
||||||
|
|
||||||
|
### Analyzing the Bundle Size
|
||||||
|
|
||||||
|
This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size)
|
||||||
|
|
||||||
|
### Making a Progressive Web App
|
||||||
|
|
||||||
|
This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app)
|
||||||
|
|
||||||
|
### Advanced Configuration
|
||||||
|
|
||||||
|
This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration)
|
||||||
|
|
||||||
|
### Deployment
|
||||||
|
|
||||||
|
This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment)
|
||||||
|
|
||||||
|
### `npm run build` fails to minify
|
||||||
|
|
||||||
|
This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify)
|
21
salw_client/nginx.conf
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
|
||||||
|
server_name localhost;
|
||||||
|
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
# All requests are routed to index.html
|
||||||
|
try_files $uri /index.html;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Optional: Cache static files to improve performance
|
||||||
|
location ~* \.(?:ico|css|js|gif|jpe?g|png|woff2?|eot|ttf|svg|otf|webp)$ {
|
||||||
|
expires 6M;
|
||||||
|
access_log off;
|
||||||
|
add_header Cache-Control "public";
|
||||||
|
}
|
||||||
|
}
|
20317
salw_client/package-lock.json
generated
Normal file
55
salw_client/package.json
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
{
|
||||||
|
"name": "salw_client",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"private": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@fortawesome/fontawesome-svg-core": "^6.5.2",
|
||||||
|
"@fortawesome/free-solid-svg-icons": "^6.5.2",
|
||||||
|
"@fortawesome/react-fontawesome": "^0.2.1",
|
||||||
|
"@testing-library/jest-dom": "^5.17.0",
|
||||||
|
"@testing-library/react": "^13.4.0",
|
||||||
|
"@testing-library/user-event": "^13.5.0",
|
||||||
|
"axios": "^1.7.7",
|
||||||
|
"bootstrap": "^5.3.2",
|
||||||
|
"dompurify": "^3.1.4",
|
||||||
|
"html-react-parser": "^5.1.10",
|
||||||
|
"leaflet": "^1.9.4",
|
||||||
|
"leaflet.bigimage": "^1.0.1",
|
||||||
|
"node-sass": "^7.0.3",
|
||||||
|
"react": "^18.2.0",
|
||||||
|
"react-bootstrap": "^2.9.1",
|
||||||
|
"react-dom": "^18.2.0",
|
||||||
|
"react-leaflet": "^4.2.1",
|
||||||
|
"react-query": "^3.39.3",
|
||||||
|
"react-router-dom": "^6.22.3",
|
||||||
|
"react-scripts": "5.0.1",
|
||||||
|
"react-select": "^5.8.0",
|
||||||
|
"sass": "^1.77.0",
|
||||||
|
"swiper": "^11.0.2",
|
||||||
|
"web-vitals": "^2.1.4"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"start": "react-scripts start",
|
||||||
|
"build": "react-scripts build",
|
||||||
|
"test": "react-scripts test",
|
||||||
|
"eject": "react-scripts eject"
|
||||||
|
},
|
||||||
|
"eslintConfig": {
|
||||||
|
"extends": [
|
||||||
|
"react-app",
|
||||||
|
"react-app/jest"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"browserslist": {
|
||||||
|
"production": [
|
||||||
|
">0.2%",
|
||||||
|
"not dead",
|
||||||
|
"not op_mini all"
|
||||||
|
],
|
||||||
|
"development": [
|
||||||
|
"last 1 chrome version",
|
||||||
|
"last 1 firefox version",
|
||||||
|
"last 1 safari version"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
BIN
salw_client/public/favicon.ico
Normal file
After Width: | Height: | Size: 3.8 KiB |
49
salw_client/public/index.html
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<meta name="theme-color" content="#000000" />
|
||||||
|
<meta
|
||||||
|
name="description"
|
||||||
|
content="Web site created using create-react-app"
|
||||||
|
/>
|
||||||
|
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
|
||||||
|
<!--
|
||||||
|
manifest.json provides metadata used when your web app is installed on a
|
||||||
|
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
||||||
|
-->
|
||||||
|
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
||||||
|
<!--
|
||||||
|
Notice the use of %PUBLIC_URL% in the tags above.
|
||||||
|
It will be replaced with the URL of the `public` folder during the build.
|
||||||
|
Only files inside the `public` folder can be referenced from the HTML.
|
||||||
|
|
||||||
|
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
||||||
|
work correctly both with client-side routing and a non-root public URL.
|
||||||
|
Learn how to configure a non-root public URL by running `npm run build`.
|
||||||
|
-->
|
||||||
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
|
||||||
|
integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY="
|
||||||
|
crossorigin=""
|
||||||
|
/>
|
||||||
|
<title>React App</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||||
|
<div id="root"></div>
|
||||||
|
<!--
|
||||||
|
This HTML file is a template.
|
||||||
|
If you open it directly in the browser, you will see an empty page.
|
||||||
|
|
||||||
|
You can add webfonts, meta tags, or analytics to this file.
|
||||||
|
The build step will place the bundled scripts into the <body> tag.
|
||||||
|
|
||||||
|
To begin the development, run `npm start` or `yarn start`.
|
||||||
|
To create a production bundle, use `npm run build` or `yarn build`.
|
||||||
|
-->
|
||||||
|
</body>
|
||||||
|
</html>
|
BIN
salw_client/public/logo192.png
Normal file
After Width: | Height: | Size: 5.2 KiB |
BIN
salw_client/public/logo512.png
Normal file
After Width: | Height: | Size: 9.4 KiB |
25
salw_client/public/manifest.json
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"short_name": "React App",
|
||||||
|
"name": "Create React App Sample",
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"src": "favicon.ico",
|
||||||
|
"sizes": "64x64 32x32 24x24 16x16",
|
||||||
|
"type": "image/x-icon"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "logo192.png",
|
||||||
|
"type": "image/png",
|
||||||
|
"sizes": "192x192"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "logo512.png",
|
||||||
|
"type": "image/png",
|
||||||
|
"sizes": "512x512"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"start_url": ".",
|
||||||
|
"display": "standalone",
|
||||||
|
"theme_color": "#000000",
|
||||||
|
"background_color": "#ffffff"
|
||||||
|
}
|
3
salw_client/public/robots.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# https://www.robotstxt.org/robotstxt.html
|
||||||
|
User-agent: *
|
||||||
|
Disallow:
|
41
salw_client/src/App.css
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
.App {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.App-logo {
|
||||||
|
height: 40vmin;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-reduced-motion: no-preference) {
|
||||||
|
.App-logo {
|
||||||
|
animation: App-logo-spin infinite 20s linear;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.App-header {
|
||||||
|
background-color: #282c34;
|
||||||
|
min-height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: calc(10px + 2vmin);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.App-link {
|
||||||
|
color: #61dafb;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes App-logo-spin {
|
||||||
|
from {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
19
salw_client/src/App.js
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import logo from "./logo.svg";
|
||||||
|
import "./App.css";
|
||||||
|
import NavBarSalw from "./Components/Layout/NavBarSalw/NavBarSalw.js";
|
||||||
|
import { QueryClient, QueryClientProvider } from "react-query";
|
||||||
|
import { DataProvider } from "./Context/DataContext.js";
|
||||||
|
|
||||||
|
const queryClient = new QueryClient();
|
||||||
|
|
||||||
|
const App = () => {
|
||||||
|
return (
|
||||||
|
<QueryClientProvider client={queryClient}>
|
||||||
|
<DataProvider>
|
||||||
|
<NavBarSalw></NavBarSalw>
|
||||||
|
</DataProvider>
|
||||||
|
</QueryClientProvider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default App;
|
8
salw_client/src/App.test.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { render, screen } from '@testing-library/react';
|
||||||
|
import App from './App';
|
||||||
|
|
||||||
|
test('renders learn react link', () => {
|
||||||
|
render(<App />);
|
||||||
|
const linkElement = screen.getByText(/learn react/i);
|
||||||
|
expect(linkElement).toBeInTheDocument();
|
||||||
|
});
|
@ -0,0 +1,25 @@
|
|||||||
|
.content-wrapper {
|
||||||
|
position: relative;
|
||||||
|
max-height: 150px; /* Adjust this value to the desired truncated height */
|
||||||
|
overflow: hidden;
|
||||||
|
transition: max-height 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-wrapper.expanded {
|
||||||
|
max-height: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.read-more {
|
||||||
|
display: block;
|
||||||
|
margin-top: 10px;
|
||||||
|
color: blue;
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
text-decoration: underline;
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.read-more:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
import "./TruncateContent.css";
|
||||||
|
|
||||||
|
const TruncateContent = ({ children }) => {
|
||||||
|
const [isExpanded, setIsExpanded] = useState(false);
|
||||||
|
|
||||||
|
const toggleReadMore = () => {
|
||||||
|
setIsExpanded(!isExpanded);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div
|
||||||
|
className={`content-wrapper ${isExpanded ? "expanded" : "truncated"}`}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
<button className="read-more" onClick={toggleReadMore}>
|
||||||
|
{isExpanded ? "Read Less" : "Read More"}
|
||||||
|
</button>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TruncateContent;
|
@ -0,0 +1,58 @@
|
|||||||
|
import React, { useState, useEffect } from "react";
|
||||||
|
import Africa from "../../../Data/TestAfrica.geojson";
|
||||||
|
import Dropdown from "react-bootstrap/Dropdown";
|
||||||
|
import DropdownButton from "react-bootstrap/DropdownButton";
|
||||||
|
import Select from "react-select";
|
||||||
|
|
||||||
|
const AfricaMapFilters = ({ handleCountrySelect }) => {
|
||||||
|
|
||||||
|
const [africaCountries, setAfricaCountries] = useState(null);
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
|
const [error, setError] = useState(null);
|
||||||
|
const [selectedOption, setSelectedOption] = useState(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchAfricaCountries = async () => {
|
||||||
|
try {
|
||||||
|
const response = await fetch(Africa);
|
||||||
|
const data = await response.json();
|
||||||
|
setAfricaCountries(
|
||||||
|
data.features.map((country) => ({
|
||||||
|
value: country.properties.name,
|
||||||
|
label: country.properties.name,
|
||||||
|
target: country,
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
setLoading(false);
|
||||||
|
} catch (error) {
|
||||||
|
setError(error);
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
fetchAfricaCountries();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleChange = (selectedOption) => {
|
||||||
|
setSelectedOption(selectedOption);
|
||||||
|
handleCountrySelect(selectedOption);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
AfricaMapFilters
|
||||||
|
<div>
|
||||||
|
<h3>Select a country:</h3>
|
||||||
|
<Select
|
||||||
|
value={selectedOption}
|
||||||
|
onChange={handleChange}
|
||||||
|
options={africaCountries}
|
||||||
|
isSearchable={true}
|
||||||
|
placeholder="Search..."
|
||||||
|
menuPortalTarget={document.body}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AfricaMapFilters;
|
@ -0,0 +1,36 @@
|
|||||||
|
import React from "react";
|
||||||
|
import Carousel from "react-bootstrap/Carousel";
|
||||||
|
import Container from "react-bootstrap/esm/Container";
|
||||||
|
import Classes from "./CarouselsSalw.module.css";
|
||||||
|
|
||||||
|
import weapon1 from "../../../img/weapon1.png";
|
||||||
|
import weapon2 from "../../../img/weapon2.png";
|
||||||
|
import weapon3 from "../../../img/weapon3.png";
|
||||||
|
import weapon4 from "../../../img/weapon4.png";
|
||||||
|
import weapon5 from "../../../img/weapon5.png";
|
||||||
|
|
||||||
|
const CarouselsSalw = () => {
|
||||||
|
return (
|
||||||
|
<Container className="mt-5">
|
||||||
|
<Carousel className={`${Classes.swiper} text-center w-75 m-auto`}>
|
||||||
|
<Carousel.Item>
|
||||||
|
<img src={weapon1} alt="" className="d-block mx-auto" />
|
||||||
|
</Carousel.Item>
|
||||||
|
<Carousel.Item>
|
||||||
|
<img src={weapon2} alt="" className="d-block mx-auto"/>
|
||||||
|
</Carousel.Item>
|
||||||
|
<Carousel.Item>
|
||||||
|
<img src={weapon3} alt="" className="d-block mx-auto"/>
|
||||||
|
</Carousel.Item>
|
||||||
|
<Carousel.Item>
|
||||||
|
<img src={weapon4} alt="" className="d-block mx-auto"/>
|
||||||
|
</Carousel.Item>
|
||||||
|
<Carousel.Item>
|
||||||
|
<img src={weapon5} alt="" className="d-block mx-auto"/>
|
||||||
|
</Carousel.Item>
|
||||||
|
</Carousel>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CarouselsSalw;
|
@ -0,0 +1,6 @@
|
|||||||
|
.swiper {
|
||||||
|
border: solid 1px #ccc;
|
||||||
|
border-radius: 15px;
|
||||||
|
background-color: #ccc;
|
||||||
|
height: 100%;
|
||||||
|
}
|
@ -0,0 +1,816 @@
|
|||||||
|
import React, { createRef } from "react";
|
||||||
|
import { MapContainer, GeoJSON, Marker, Tooltip } from "react-leaflet";
|
||||||
|
import L from "leaflet";
|
||||||
|
import Africa from "../../../Data/ControlinAfrica.geojson";
|
||||||
|
|
||||||
|
import Orgs from "../../../Data/Orgs.geojson";
|
||||||
|
import "../../../Styles/main.scss";
|
||||||
|
import { CountryStyle, CountrySelectedStyle } from "./countryStyles";
|
||||||
|
import MapInfoBox from "./MapInfoBox"; // Import the InfoBox component
|
||||||
|
import MarkerIcon from "./MarkerIcon";
|
||||||
|
import CountryPopup from "./CountryPopup";
|
||||||
|
import FilterBox from "./FilterBox";
|
||||||
|
import Container from "react-bootstrap/Container";
|
||||||
|
import Row from "react-bootstrap/Row";
|
||||||
|
import Col from "react-bootstrap/Col";
|
||||||
|
import SelectedFilters from "./SelectedFilters";
|
||||||
|
import TreatyInfoBox from "./TreatyInfoBox";
|
||||||
|
|
||||||
|
import Icon1 from "../../../Icons/icon1.svg";
|
||||||
|
import Icon2 from "../../../Icons/icon2.svg";
|
||||||
|
import Icon3 from "../../../Icons/icon3.svg";
|
||||||
|
import Icon4 from "../../../Icons/icon4.svg";
|
||||||
|
import Icon5 from "../../../Icons/icon5.svg";
|
||||||
|
import Icon6 from "../../../Icons/icon6.svg";
|
||||||
|
import Icon7 from "../../../Icons/icon7.svg";
|
||||||
|
import Icon8 from "../../../Icons/icon8.svg";
|
||||||
|
import Icon9 from "../../../Icons/icon9.svg";
|
||||||
|
import Icon10 from "../../../Icons/icon10.svg";
|
||||||
|
import Icon11 from "../../../Icons/icon11.svg";
|
||||||
|
import Icon12 from "../../../Icons/icon12.svg";
|
||||||
|
import Icon13 from "../../../Icons/icon13.svg";
|
||||||
|
import Icon14 from "../../../Icons/icon14.svg";
|
||||||
|
import Icon15 from "../../../Icons/icon15.svg";
|
||||||
|
import Icon16 from "../../../Icons/icon16.svg";
|
||||||
|
import Icon17 from "../../../Icons/icon17.svg";
|
||||||
|
import Icon18 from "../../../Icons/icon18.svg";
|
||||||
|
import Icon19 from "../../../Icons/icon19.svg";
|
||||||
|
import Icon20 from "../../../Icons/icon20.svg";
|
||||||
|
import Icon21 from "../../../Icons/icon21.svg";
|
||||||
|
import Icon22 from "../../../Icons/icon22.svg";
|
||||||
|
import Icon23 from "../../../Icons/icon23.svg";
|
||||||
|
import Icon24 from "../../../Icons/icon24.svg";
|
||||||
|
import Icon25 from "../../../Icons/icon25.svg";
|
||||||
|
import Icon26 from "../../../Icons/icon26.svg";
|
||||||
|
import Card_ from "../../UI/Card_/Card_";
|
||||||
|
|
||||||
|
const iconMap = {
|
||||||
|
Icon1: Icon1,
|
||||||
|
Icon2: Icon2,
|
||||||
|
Icon3: Icon3,
|
||||||
|
Icon4: Icon4,
|
||||||
|
Icon5: Icon5,
|
||||||
|
Icon6: Icon6,
|
||||||
|
Icon7: Icon7,
|
||||||
|
Icon8: Icon8,
|
||||||
|
Icon9: Icon9,
|
||||||
|
Icon10: Icon10,
|
||||||
|
Icon11: Icon11,
|
||||||
|
Icon12: Icon12,
|
||||||
|
Icon13: Icon13,
|
||||||
|
Icon14: Icon14,
|
||||||
|
Icon15: Icon15,
|
||||||
|
Icon16: Icon16,
|
||||||
|
Icon17: Icon17,
|
||||||
|
Icon18: Icon18,
|
||||||
|
Icon19: Icon19,
|
||||||
|
Icon20: Icon20,
|
||||||
|
Icon21: Icon21,
|
||||||
|
Icon22: Icon22,
|
||||||
|
Icon23: Icon23,
|
||||||
|
Icon24: Icon24,
|
||||||
|
Icon25: Icon25,
|
||||||
|
Icon26: Icon26,
|
||||||
|
};
|
||||||
|
|
||||||
|
class ControlInAfricaMap extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.mapRef = createRef(); // Create a ref to store the MapContainer instance
|
||||||
|
this.state = {
|
||||||
|
africaCountries: null, // The GeoJSON data for the African countries
|
||||||
|
countriesNames: [], // The names of the countries for select list
|
||||||
|
regional_organisations: [], // The regional organisations data
|
||||||
|
geographical_regions: [], // The geographical regions data
|
||||||
|
regional_treaties: [], // The regional treaties data
|
||||||
|
international_treaties: [], // The international treaties data
|
||||||
|
internationalIntsruments: [], // The international instruments data
|
||||||
|
africanIntsruments: [], // The african instruments data
|
||||||
|
|
||||||
|
loading: true,
|
||||||
|
error: null,
|
||||||
|
|
||||||
|
center: [3, 15],
|
||||||
|
zoom: this.getZoomLevel(window.innerWidth),
|
||||||
|
scrollWheelZoom: false,
|
||||||
|
zoomControl: false,
|
||||||
|
|
||||||
|
openedTooltipLayer: null,
|
||||||
|
|
||||||
|
selectedCountry: "", // The name of the selected country
|
||||||
|
selectedRegion: "", // The name of the selected region
|
||||||
|
selectedTreaty: "", // The name of the selected treaty
|
||||||
|
selectedTreatyOfficialName: "", // For the Slescted filters box
|
||||||
|
|
||||||
|
selectedCountriesNamesRegions: [],
|
||||||
|
selectedCountriesNamesTreaties: [],
|
||||||
|
selectedCountriesFeaturesRegions: [],
|
||||||
|
selectedCountriesFeaturesTreaties: [],
|
||||||
|
selectedCommonCountries: [],
|
||||||
|
|
||||||
|
selectedCountryColor: "yellow",
|
||||||
|
selectedIcon: "none",
|
||||||
|
|
||||||
|
currentStatuesTreaty: "",
|
||||||
|
prevStatuesTreaty: "",
|
||||||
|
|
||||||
|
infoBox: [],
|
||||||
|
showInfoBox: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.fetchData();
|
||||||
|
window.addEventListener("resize", this.handleResize);
|
||||||
|
if (L.control.bigImage) {
|
||||||
|
L.control.bigImage({ position: 'topright' }).addTo(this.mapRef);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
window.removeEventListener("resize", this.handleResize);
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchData = async () => {
|
||||||
|
try {
|
||||||
|
const response = await fetch(Africa);
|
||||||
|
const data = await response.json();
|
||||||
|
this.setState(
|
||||||
|
{
|
||||||
|
africaCountries: data.features,
|
||||||
|
countriesNames: data.features
|
||||||
|
.map((feature) => feature.properties.name)
|
||||||
|
.sort(),
|
||||||
|
loading: false,
|
||||||
|
},
|
||||||
|
() => {}
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
this.setState({
|
||||||
|
error: error,
|
||||||
|
loading: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
//console.log("fetching data");
|
||||||
|
const response = await fetch(Orgs); // Ensure this is a valid URL
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`HTTP error! status: ${response.status}`);
|
||||||
|
}
|
||||||
|
const data = await response.json();
|
||||||
|
// Replace icon names with actual icon objects
|
||||||
|
const regional_treaties = data.regional_treaties.map((treaty) => ({
|
||||||
|
...treaty,
|
||||||
|
icon_eligible: iconMap[treaty.icon_eligible] || null,
|
||||||
|
icon_signed: iconMap[treaty.icon_signed] || null,
|
||||||
|
icon_ratified: iconMap[treaty.icon_ratified] || null,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const international_treaties = data.international_treaties.map(
|
||||||
|
(treaty) => ({
|
||||||
|
...treaty,
|
||||||
|
icon_eligible: iconMap[treaty.icon_eligible] || null,
|
||||||
|
icon_signed: iconMap[treaty.icon_signed] || null,
|
||||||
|
icon_ratified: iconMap[treaty.icon_ratified] || null,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
const internationalIntsruments = data.internationalIntsruments.map(
|
||||||
|
(instrument) => ({
|
||||||
|
...instrument,
|
||||||
|
icon: iconMap[instrument.icon] || null,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
const africanIntsruments = data.africanIntsruments.map((instrument) => ({
|
||||||
|
...instrument,
|
||||||
|
icon: iconMap[instrument.icon] || null,
|
||||||
|
}));
|
||||||
|
|
||||||
|
this.setState(
|
||||||
|
{
|
||||||
|
regional_organisations: data.regional_organisations,
|
||||||
|
geographical_regions: data.geographical_regions,
|
||||||
|
regional_treaties,
|
||||||
|
international_treaties,
|
||||||
|
internationalIntsruments,
|
||||||
|
africanIntsruments,
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
// Callback after state has been updated (optional)
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
//console.error("Error fetching the JSON file:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
getZoomLevel = () => {
|
||||||
|
const screenWidth = window.innerWidth;
|
||||||
|
//console.log(screenWidth);
|
||||||
|
if (screenWidth <= 800) {
|
||||||
|
//console.log("small screen");
|
||||||
|
return 3;
|
||||||
|
} else if (screenWidth <= 1024) {
|
||||||
|
return 4;
|
||||||
|
} else {
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
handleResize = () => {
|
||||||
|
this.setState({
|
||||||
|
zoom: this.getZoomLevel(window.innerWidth),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
resetMap = () => {
|
||||||
|
if (this.mapRef.current) {
|
||||||
|
this.mapRef.current.setView(this.state.center, this.state.zoom); // Set the center and zoom to initial values
|
||||||
|
}
|
||||||
|
};
|
||||||
|
zoomIn = () => {
|
||||||
|
if (this.mapRef.current) {
|
||||||
|
this.mapRef.current.setZoom(this.mapRef.current.getZoom() + 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
zoomOut = () => {
|
||||||
|
if (this.mapRef.current) {
|
||||||
|
this.mapRef.current.setZoom(this.mapRef.current.getZoom() - 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
handleCountryChange = (e) => {
|
||||||
|
const countryName = e.target.value || e.target.getAttribute("data-country");
|
||||||
|
const { selectedCountry } = this.state;
|
||||||
|
if (countryName === selectedCountry) {
|
||||||
|
this.setState({ selectedCountry: "" });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.setState({ selectedCountry: countryName }, () => {
|
||||||
|
//this.openTooltipForCountry(countryName);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
onEachFeature = (feature, layer) => {
|
||||||
|
// Bind event to layer
|
||||||
|
layer.on({
|
||||||
|
//mouseover: this.onMouseOver,
|
||||||
|
//mouseout: this.onMouseOut,
|
||||||
|
click: this.onMouseClick,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// To Do: Delete this function
|
||||||
|
openTooltipForCountry = (countryName) => {
|
||||||
|
const { africaCountries } = this.state;
|
||||||
|
if (!africaCountries) return;
|
||||||
|
|
||||||
|
const feature = africaCountries.find(
|
||||||
|
(feature) => feature.properties.name === countryName
|
||||||
|
);
|
||||||
|
if (!feature) return;
|
||||||
|
|
||||||
|
const { openedTooltipLayer } = this.state;
|
||||||
|
if (openedTooltipLayer) {
|
||||||
|
openedTooltipLayer.closeTooltip(); // Close the previously opened tooltip
|
||||||
|
}
|
||||||
|
|
||||||
|
const layer = L.geoJSON(feature);
|
||||||
|
|
||||||
|
// Update the state to store the currently opened tooltip
|
||||||
|
this.setState({ openedTooltipLayer: layer });
|
||||||
|
};
|
||||||
|
|
||||||
|
onMouseClick = (e) => {
|
||||||
|
const countryName = e.target.feature.properties.name;
|
||||||
|
if (countryName === this.state.selectedCountry) {
|
||||||
|
this.setState({
|
||||||
|
selectedCountry: "",
|
||||||
|
selectedRegion: "",
|
||||||
|
selectedTreaty: "",
|
||||||
|
selectedTreatyOfficialName: "",
|
||||||
|
|
||||||
|
selectedCountriesNamesRegions: [],
|
||||||
|
selectedCountriesNamesTreaties: [],
|
||||||
|
selectedCountriesFeaturesRegions: [],
|
||||||
|
selectedCountriesFeaturesTreaties: [],
|
||||||
|
|
||||||
|
selectedCountryColor: "yellow",
|
||||||
|
|
||||||
|
prevStatuesTreaty: "",
|
||||||
|
|
||||||
|
infoBox: [],
|
||||||
|
showInfoBox: false,
|
||||||
|
});
|
||||||
|
this.props.updateCountryID(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
selectedCountry: countryName,
|
||||||
|
selectedRegion: "",
|
||||||
|
selectedTreaty: "",
|
||||||
|
selectedTreatyOfficialName: "",
|
||||||
|
|
||||||
|
selectedCountriesNamesRegions: [],
|
||||||
|
selectedCountriesNamesTreaties: [],
|
||||||
|
selectedCountriesFeaturesRegions: [],
|
||||||
|
selectedCountriesFeaturesTreaties: [],
|
||||||
|
|
||||||
|
selectedCountryColor: "yellow",
|
||||||
|
|
||||||
|
prevStatuesTreaty: "",
|
||||||
|
|
||||||
|
infoBox: [],
|
||||||
|
showInfoBox: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
this.props.updateCountryID(e.target.feature.properties.id);
|
||||||
|
};
|
||||||
|
|
||||||
|
handleOrganizationClick = (name, color) => {
|
||||||
|
const { selectedRegion, prevStatuesTreaty, africaCountries } = this.state;
|
||||||
|
|
||||||
|
if (selectedRegion === name) {
|
||||||
|
//console.log("same");
|
||||||
|
this.setState({
|
||||||
|
selectedCountriesNamesRegions: [],
|
||||||
|
selectedCountriesNamesTreaties: [],
|
||||||
|
selectedCountryColor: "yellow",
|
||||||
|
selectedCountry: "",
|
||||||
|
selectedRegion: "",
|
||||||
|
showInfoBox: false,
|
||||||
|
currentStatuesTreaty: "",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prevStatuesTreaty) {
|
||||||
|
//console.log("change");
|
||||||
|
this.setState({
|
||||||
|
selectedCountriesNamesTreaties: [],
|
||||||
|
selectedCountry: "",
|
||||||
|
currentStatuesTreaty: "",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let selectedCountriesNamesRegions = [];
|
||||||
|
let selectedCountriesFeaturesRegions = [];
|
||||||
|
|
||||||
|
africaCountries.forEach((feature) => {
|
||||||
|
if (feature.properties[name] === 1) {
|
||||||
|
selectedCountriesNamesRegions.push(feature.properties.name);
|
||||||
|
selectedCountriesFeaturesRegions.push(feature);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
selectedCountriesNamesRegions,
|
||||||
|
selectedCountryColor: color,
|
||||||
|
selectedCountry: "",
|
||||||
|
selectedRegion: name,
|
||||||
|
selectedCountriesFeaturesRegions,
|
||||||
|
selectedTreaty: "",
|
||||||
|
selectedTreatyOfficialName: "",
|
||||||
|
showInfoBox: true,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
handleTreatiesClick = (name, status, official_name) => {
|
||||||
|
const {
|
||||||
|
selectedRegion,
|
||||||
|
selectedTreaty,
|
||||||
|
selectedCountriesNamesRegions,
|
||||||
|
prevStatuesTreaty,
|
||||||
|
africaCountries,
|
||||||
|
regional_treaties,
|
||||||
|
international_treaties,
|
||||||
|
internationalIntsruments,
|
||||||
|
africanIntsruments,
|
||||||
|
currentStatuesTreaty,
|
||||||
|
} = this.state;
|
||||||
|
|
||||||
|
// get the icon of the selected treaty based on the name and status of the treaty
|
||||||
|
//console.log(name, status);
|
||||||
|
|
||||||
|
let org =
|
||||||
|
regional_treaties.find((org) => org.name2 === name) ||
|
||||||
|
international_treaties.find((org) => org.name2 === name);
|
||||||
|
|
||||||
|
let instrument =
|
||||||
|
internationalIntsruments.find(
|
||||||
|
(instrument) => instrument.name2 === name
|
||||||
|
) || africanIntsruments.find((instrument) => instrument.name2 === name);
|
||||||
|
|
||||||
|
const selectedIcon = org
|
||||||
|
? org[`icon_${status.toLowerCase()}`] || "none"
|
||||||
|
: instrument
|
||||||
|
? instrument[`icon`] || "none"
|
||||||
|
: "none";
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
selectedIcon,
|
||||||
|
currentStatuesTreaty: status,
|
||||||
|
});
|
||||||
|
|
||||||
|
// console.log(status, ":", currentStatuesTreaty, prevStatuesTreaty);
|
||||||
|
|
||||||
|
// if the same treaty is selected previously and the region is not selected
|
||||||
|
// then the treaty will be deselected
|
||||||
|
if (
|
||||||
|
selectedTreaty === name &&
|
||||||
|
prevStatuesTreaty === status &&
|
||||||
|
selectedRegion === ""
|
||||||
|
) {
|
||||||
|
//console.log("1");
|
||||||
|
this.setState({
|
||||||
|
selectedCountriesNamesRegions: [],
|
||||||
|
selectedCountriesNamesTreaties: [],
|
||||||
|
selectedCountryColor: "yellow",
|
||||||
|
selectedCountry: "",
|
||||||
|
selectedTreaty: "",
|
||||||
|
selectedTreatyOfficialName: "",
|
||||||
|
currentStatuesTreaty: "",
|
||||||
|
prevStatuesTreaty: "",
|
||||||
|
prevStatuesRegion: "",
|
||||||
|
selectedIcon: "none",
|
||||||
|
showInfoBox: false,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the same treaty is selected previously and the region is selected
|
||||||
|
// then the treaty will be deselected
|
||||||
|
if (selectedTreaty === name && prevStatuesTreaty === status) {
|
||||||
|
//console.log("2");
|
||||||
|
this.setState({
|
||||||
|
selectedCountriesNamesTreaties: [],
|
||||||
|
selectedCountry: "",
|
||||||
|
selectedTreaty: "",
|
||||||
|
selectedTreatyOfficialName: "",
|
||||||
|
prevStatuesTreaty: "",
|
||||||
|
currentStatuesTreaty: "",
|
||||||
|
selectedIcon: "none",
|
||||||
|
showInfoBox: true,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let selectedCountriesNamesTreaties = [];
|
||||||
|
let selectedCountriesFeaturesTreaties = [];
|
||||||
|
|
||||||
|
africaCountries.forEach((feature) => {
|
||||||
|
if (
|
||||||
|
feature.properties[name] === 1 ||
|
||||||
|
feature.properties[name] === status
|
||||||
|
) {
|
||||||
|
selectedCountriesNamesTreaties.push(feature.properties.name);
|
||||||
|
selectedCountriesFeaturesTreaties.push(feature);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// if the region is selected then the treaty will be selected based on the
|
||||||
|
// intersection of the region and the treaty
|
||||||
|
if (selectedRegion) {
|
||||||
|
//console.log("intersect");
|
||||||
|
const intersection = selectedCountriesNamesTreaties.filter((country) =>
|
||||||
|
selectedCountriesNamesRegions.includes(country)
|
||||||
|
);
|
||||||
|
const selectedCommonCountries = selectedCountriesNamesTreaties
|
||||||
|
.filter((country) => selectedCountriesNamesRegions.includes(country))
|
||||||
|
.map((country) => ({
|
||||||
|
country,
|
||||||
|
status,
|
||||||
|
}));
|
||||||
|
this.setState({
|
||||||
|
selectedCountriesNamesTreaties: intersection,
|
||||||
|
selectedCountry: "",
|
||||||
|
selectedTreaty: name,
|
||||||
|
selectedTreatyOfficialName: official_name,
|
||||||
|
currentStatuesTreaty: status,
|
||||||
|
prevStatuesTreaty: status,
|
||||||
|
showInfoBox: true,
|
||||||
|
selectedCommonCountries,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
selectedCountriesNamesTreaties,
|
||||||
|
selectedCountry: "",
|
||||||
|
selectedTreaty: name,
|
||||||
|
selectedTreatyOfficialName: official_name,
|
||||||
|
currentStatuesTreaty: status,
|
||||||
|
prevStatuesTreaty: status,
|
||||||
|
selectedCountriesFeaturesTreaties,
|
||||||
|
});
|
||||||
|
|
||||||
|
// if region and treaty selected
|
||||||
|
if (
|
||||||
|
this.state.selectedRegion &&
|
||||||
|
regional_treaties.some((org) => org.name2 === name)
|
||||||
|
) {
|
||||||
|
this.setState({
|
||||||
|
selectedTreaty: name,
|
||||||
|
selectedTreatyOfficialName: official_name,
|
||||||
|
currentStatuesTreaty: status,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
regionalOrganisationStatistics = () => {
|
||||||
|
const {
|
||||||
|
selectedCountriesFeaturesRegions,
|
||||||
|
regional_treaties,
|
||||||
|
international_treaties,
|
||||||
|
internationalIntsruments,
|
||||||
|
africanIntsruments,
|
||||||
|
} = this.state;
|
||||||
|
|
||||||
|
// Helper function to process treaties
|
||||||
|
const processTreaties = (treaties) => {
|
||||||
|
return treaties.map((org) => {
|
||||||
|
let countriesSigned = 0;
|
||||||
|
let countriesEligible = 0;
|
||||||
|
let countriesRatified = 0;
|
||||||
|
|
||||||
|
selectedCountriesFeaturesRegions.forEach((feature) => {
|
||||||
|
const status = feature.properties[org.name2];
|
||||||
|
if (status === "Signed") {
|
||||||
|
countriesSigned++;
|
||||||
|
} else if (status === "Eligible") {
|
||||||
|
countriesEligible++;
|
||||||
|
} else if (status === "Ratified") {
|
||||||
|
countriesRatified++;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: org.name,
|
||||||
|
signed: countriesSigned,
|
||||||
|
eligible: countriesEligible,
|
||||||
|
ratified: countriesRatified,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper function to process instruments
|
||||||
|
const processInstruments = (instruments) => {
|
||||||
|
return instruments.map((instrument) => {
|
||||||
|
const countris = selectedCountriesFeaturesRegions.filter(
|
||||||
|
(feature) => feature.properties[instrument.name2] === 1
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
name: instrument.name,
|
||||||
|
countries: countris.length,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const organisationsRegionalTreaties = processTreaties(regional_treaties);
|
||||||
|
const organisationsInternationalTreaties = processTreaties(
|
||||||
|
international_treaties
|
||||||
|
);
|
||||||
|
|
||||||
|
const internationalIntsruments_ = processInstruments(
|
||||||
|
internationalIntsruments
|
||||||
|
);
|
||||||
|
const africanIntsruments_ = processInstruments(africanIntsruments);
|
||||||
|
|
||||||
|
return {
|
||||||
|
organisationsRegionalTreaties,
|
||||||
|
organisationsInternationalTreaties,
|
||||||
|
internationalIntsruments_,
|
||||||
|
africanIntsruments_,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Define the function to determine the style
|
||||||
|
getFeatureStyle = (
|
||||||
|
feature,
|
||||||
|
selectedCountry,
|
||||||
|
selectedCountriesNamesRegions,
|
||||||
|
selectedCountriesNamesTreaties,
|
||||||
|
selectedCountryColor
|
||||||
|
) => {
|
||||||
|
const { name } = feature.properties;
|
||||||
|
// select one country
|
||||||
|
if (name === selectedCountry) {
|
||||||
|
//console.log("one country selected");
|
||||||
|
return CountrySelectedStyle(selectedCountryColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
const inSelectedRegions = selectedCountriesNamesRegions.includes(name);
|
||||||
|
const inSelectedTreaties = selectedCountriesNamesTreaties.includes(name);
|
||||||
|
// select one region
|
||||||
|
if (inSelectedRegions && !selectedCountriesNamesTreaties.length) {
|
||||||
|
//console.log("region selected");
|
||||||
|
return CountrySelectedStyle(selectedCountryColor);
|
||||||
|
}
|
||||||
|
// select one treaty
|
||||||
|
if (inSelectedRegions && !inSelectedTreaties) {
|
||||||
|
//console.log("region and treaty selected 1");
|
||||||
|
return CountrySelectedStyle(selectedCountryColor);
|
||||||
|
}
|
||||||
|
// select region and treaty
|
||||||
|
if (inSelectedRegions && inSelectedTreaties) {
|
||||||
|
//console.log("region and treaty selected 2");
|
||||||
|
return CountrySelectedStyle(selectedCountryColor, 0.7);
|
||||||
|
}
|
||||||
|
// default style
|
||||||
|
//console.log("default");
|
||||||
|
return CountryStyle();
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {
|
||||||
|
africaCountries,
|
||||||
|
loading,
|
||||||
|
error,
|
||||||
|
zoom,
|
||||||
|
zoomControl,
|
||||||
|
center,
|
||||||
|
scrollWheelZoom,
|
||||||
|
showInfoBox,
|
||||||
|
countriesNames,
|
||||||
|
selectedCountry,
|
||||||
|
selectedCountriesNamesRegions,
|
||||||
|
selectedCountriesNamesTreaties,
|
||||||
|
currentStatuesTreaty,
|
||||||
|
selectedCountryColor,
|
||||||
|
selectedRegion,
|
||||||
|
selectedTreaty,
|
||||||
|
selectedTreatyOfficialName,
|
||||||
|
selectedIcon,
|
||||||
|
geographical_regions,
|
||||||
|
regional_organisations,
|
||||||
|
regional_treaties,
|
||||||
|
international_treaties,
|
||||||
|
internationalIntsruments,
|
||||||
|
africanIntsruments,
|
||||||
|
} = this.state;
|
||||||
|
|
||||||
|
if (loading) {
|
||||||
|
return <div>Loading...</div>;
|
||||||
|
}
|
||||||
|
if (error) {
|
||||||
|
return <div>Error: {error.message}</div>;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Container fluid>
|
||||||
|
<Row>
|
||||||
|
<Col className="filter-section" sm={2}>
|
||||||
|
<FilterBox
|
||||||
|
selectedCountry={selectedCountry}
|
||||||
|
countriesNames={countriesNames}
|
||||||
|
handleCountryChange={this.handleCountryChange}
|
||||||
|
handleOrganizationClick={this.handleOrganizationClick}
|
||||||
|
handleTreatiesClick={this.handleTreatiesClick}
|
||||||
|
geographical_regions={geographical_regions}
|
||||||
|
regional_organisations={regional_organisations}
|
||||||
|
regional_treaties={regional_treaties}
|
||||||
|
international_treaties={international_treaties}
|
||||||
|
internationalIntsruments={internationalIntsruments}
|
||||||
|
africanIntsruments={africanIntsruments}
|
||||||
|
></FilterBox>
|
||||||
|
</Col>
|
||||||
|
<Col className="map-section" sm={10}>
|
||||||
|
<div id="map" className="map-container">
|
||||||
|
<MapContainer
|
||||||
|
center={center}
|
||||||
|
zoom={zoom}
|
||||||
|
ref={this.mapRef}
|
||||||
|
zoomControl={zoomControl}
|
||||||
|
style={{ width: "100%", height: "100%" }}
|
||||||
|
scrollWheelZoom={scrollWheelZoom}
|
||||||
|
>
|
||||||
|
{africaCountries && (
|
||||||
|
<>
|
||||||
|
<GeoJSON
|
||||||
|
ref={this.geoJsonLayerRef}
|
||||||
|
onEachFeature={this.onEachFeature}
|
||||||
|
id="africa-map"
|
||||||
|
style={(feature) =>
|
||||||
|
this.getFeatureStyle(
|
||||||
|
feature,
|
||||||
|
selectedCountry,
|
||||||
|
selectedCountriesNamesRegions,
|
||||||
|
selectedCountriesNamesTreaties,
|
||||||
|
selectedCountryColor
|
||||||
|
)
|
||||||
|
}
|
||||||
|
key="africa-map"
|
||||||
|
data={africaCountries}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{selectedCountry &&
|
||||||
|
africaCountries.map((feature) => {
|
||||||
|
if (feature.properties.name === selectedCountry) {
|
||||||
|
return (
|
||||||
|
<Marker
|
||||||
|
key={feature.properties.name}
|
||||||
|
position={[
|
||||||
|
feature.properties.y,
|
||||||
|
feature.properties.x,
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Tooltip
|
||||||
|
direction="bottom"
|
||||||
|
offset={[-13, 27]}
|
||||||
|
opacity={1}
|
||||||
|
permanent
|
||||||
|
className="tooltip-custom"
|
||||||
|
>
|
||||||
|
<CountryPopup
|
||||||
|
feature={feature}
|
||||||
|
regional_organisations={regional_organisations}
|
||||||
|
regional_treaties={regional_treaties}
|
||||||
|
international_treaties={international_treaties}
|
||||||
|
></CountryPopup>
|
||||||
|
</Tooltip>
|
||||||
|
</Marker>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})}
|
||||||
|
|
||||||
|
{selectedTreaty &&
|
||||||
|
selectedCountriesNamesTreaties &&
|
||||||
|
africaCountries.map((feature, index) => {
|
||||||
|
if (
|
||||||
|
selectedCountriesNamesTreaties.includes(
|
||||||
|
feature.properties.name
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return (
|
||||||
|
<MarkerIcon
|
||||||
|
key={index}
|
||||||
|
position={[
|
||||||
|
feature.properties.y,
|
||||||
|
feature.properties.x,
|
||||||
|
]}
|
||||||
|
icon={selectedIcon}
|
||||||
|
></MarkerIcon>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})}
|
||||||
|
|
||||||
|
<div className="custom-zoom-control">
|
||||||
|
<button onClick={this.zoomIn}>+</button>
|
||||||
|
<button onClick={this.zoomOut}>-</button>
|
||||||
|
<button onClick={this.resetMap}>*</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="country-select">
|
||||||
|
<select
|
||||||
|
onChange={this.handleCountryChange}
|
||||||
|
value={selectedCountry}
|
||||||
|
>
|
||||||
|
<option value="">Select a country</option>
|
||||||
|
{countriesNames.map((country, index) => (
|
||||||
|
<option key={index} value={country}>
|
||||||
|
{country}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{selectedRegion || selectedTreatyOfficialName ? (
|
||||||
|
<SelectedFilters
|
||||||
|
selectedRegion={selectedRegion}
|
||||||
|
selectedTreatyOfficialName={selectedTreatyOfficialName}
|
||||||
|
></SelectedFilters>
|
||||||
|
) : (
|
||||||
|
<></>
|
||||||
|
)}
|
||||||
|
{selectedRegion && selectedTreaty && (
|
||||||
|
<TreatyInfoBox
|
||||||
|
selectedRegion={selectedRegion}
|
||||||
|
selectedTreatyOfficialName={selectedTreatyOfficialName}
|
||||||
|
currentStatuesTreaty={currentStatuesTreaty}
|
||||||
|
selectedCountriesNamesTreaties={
|
||||||
|
selectedCountriesNamesTreaties
|
||||||
|
}
|
||||||
|
handleCountryChange={this.handleCountryChange}
|
||||||
|
></TreatyInfoBox>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{showInfoBox && (
|
||||||
|
<MapInfoBox
|
||||||
|
className="info-box"
|
||||||
|
selectedCountryColor={selectedCountryColor}
|
||||||
|
selectedRegion={selectedRegion}
|
||||||
|
info={this.regionalOrganisationStatistics()}
|
||||||
|
></MapInfoBox>
|
||||||
|
)}
|
||||||
|
</MapContainer>
|
||||||
|
</div>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ControlInAfricaMap;
|
@ -0,0 +1,90 @@
|
|||||||
|
import React from "react";
|
||||||
|
import "../../../Styles/main.scss";
|
||||||
|
|
||||||
|
import Icon1 from "../../../Icons/icon1.svg";
|
||||||
|
import Icon16 from "../../../Icons/icon16.svg";
|
||||||
|
import Icon20 from "../../../Icons/icon20.svg";
|
||||||
|
|
||||||
|
const findColorByName = (name, regional_organisations) => {
|
||||||
|
const org = regional_organisations.find((org) => org.name === name);
|
||||||
|
return org ? org.color : ""; // Return color value if found, otherwise return an empty string
|
||||||
|
};
|
||||||
|
|
||||||
|
const CountryPopup = (props) => {
|
||||||
|
const {
|
||||||
|
feature,
|
||||||
|
regional_organisations,
|
||||||
|
regional_treaties,
|
||||||
|
international_treaties,
|
||||||
|
} = props;
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<h5>{feature.properties.name}</h5>
|
||||||
|
<div className="matrix">
|
||||||
|
{regional_organisations.map((org) => (
|
||||||
|
<div
|
||||||
|
key={org.name}
|
||||||
|
className="rectangle"
|
||||||
|
style={
|
||||||
|
feature.properties[org.name] === 1
|
||||||
|
? {
|
||||||
|
backgroundColor: findColorByName(org.name, regional_organisations),
|
||||||
|
}
|
||||||
|
: {}
|
||||||
|
}
|
||||||
|
title={org.name}
|
||||||
|
></div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<div className="matrix-treaties-map">
|
||||||
|
{regional_treaties.map((treaty) => (
|
||||||
|
<div key={treaty.name2}>
|
||||||
|
<img
|
||||||
|
src={
|
||||||
|
treaty["icon_" + feature.properties[treaty.name2].toLowerCase()]
|
||||||
|
}
|
||||||
|
alt=""
|
||||||
|
srcSet="No Image"
|
||||||
|
className="img-fluid"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="matrix-treaties-map">
|
||||||
|
{international_treaties.map((treaty) => (
|
||||||
|
<div key={treaty.name2}>
|
||||||
|
<img
|
||||||
|
src={
|
||||||
|
treaty["icon_" + feature.properties[treaty.name2].toLowerCase()]
|
||||||
|
}
|
||||||
|
alt=""
|
||||||
|
srcSet="No Image"
|
||||||
|
className="img-fluid"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="matrix-treaties-map">
|
||||||
|
<div>
|
||||||
|
{feature.properties.UNProgrammeofAction === 1 && (
|
||||||
|
<img src={Icon20} alt="" srcSet="" />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{feature.properties.InternationalTracingInstrument === 1 && (
|
||||||
|
<img src={Icon16} alt="" srcSet="" />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{feature.properties["StG-PoA"] === 1 && (
|
||||||
|
<img src={Icon1} alt="" srcSet="" />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CountryPopup;
|
@ -0,0 +1,342 @@
|
|||||||
|
import React, { useState, useEffect } from "react";
|
||||||
|
import Stack from "react-bootstrap/Stack";
|
||||||
|
import Card_ from "../../UI/Card_/Card_";
|
||||||
|
import { useAfricaData } from "../../../Context/DataContext";
|
||||||
|
|
||||||
|
import Icon1 from "../../../Icons/icon1.svg";
|
||||||
|
import Icon2 from "../../../Icons/icon2.svg";
|
||||||
|
import Icon3 from "../../../Icons/icon3.svg";
|
||||||
|
import Icon4 from "../../../Icons/icon4.svg";
|
||||||
|
import Icon5 from "../../../Icons/icon5.svg";
|
||||||
|
import Icon6 from "../../../Icons/icon6.svg";
|
||||||
|
import Icon7 from "../../../Icons/icon7.svg";
|
||||||
|
import Icon8 from "../../../Icons/icon8.svg";
|
||||||
|
import Icon9 from "../../../Icons/icon9.svg";
|
||||||
|
import Icon10 from "../../../Icons/icon10.svg";
|
||||||
|
import Icon11 from "../../../Icons/icon11.svg";
|
||||||
|
import Icon12 from "../../../Icons/icon12.svg";
|
||||||
|
import Icon13 from "../../../Icons/icon13.svg";
|
||||||
|
import Icon14 from "../../../Icons/icon14.svg";
|
||||||
|
import Icon15 from "../../../Icons/icon15.svg";
|
||||||
|
import Icon16 from "../../../Icons/icon16.svg";
|
||||||
|
import Icon17 from "../../../Icons/icon17.svg";
|
||||||
|
import Icon18 from "../../../Icons/icon18.svg";
|
||||||
|
import Icon19 from "../../../Icons/icon19.svg";
|
||||||
|
import Icon20 from "../../../Icons/icon20.svg";
|
||||||
|
import Icon21 from "../../../Icons/icon21.svg";
|
||||||
|
import Icon22 from "../../../Icons/icon22.svg";
|
||||||
|
import Icon23 from "../../../Icons/icon23.svg";
|
||||||
|
import Icon24 from "../../../Icons/icon24.svg";
|
||||||
|
import Icon25 from "../../../Icons/icon25.svg";
|
||||||
|
import Icon26 from "../../../Icons/icon26.svg";
|
||||||
|
|
||||||
|
const regional_organisations = [
|
||||||
|
{ name: "AU", color: "#b2df8a" },
|
||||||
|
{ name: "EAC", color: "#33a02c" },
|
||||||
|
{ name: "IGAD", color: "#fb9a99" },
|
||||||
|
{ name: "UMA", color: "#e31a1c" },
|
||||||
|
{ name: "COMESA", color: "#fdbf6f" },
|
||||||
|
{ name: "ECOWAS", color: "#ff7f00" },
|
||||||
|
{ name: "CEN-SAD", color: "#cab2d6" },
|
||||||
|
{ name: "SADC", color: "#6a3d9a" },
|
||||||
|
{ name: "ECCAS", color: "#ffff99" },
|
||||||
|
{ name: "ICGLR", color: "#b15928" },
|
||||||
|
{ name: "RECSA", color: "#a6cee3" },
|
||||||
|
{ name: "SARCOM", color: "#1f78b4" },
|
||||||
|
];
|
||||||
|
|
||||||
|
const regional_treaties = [
|
||||||
|
{
|
||||||
|
name: "Bamako Declaration",
|
||||||
|
name2: "BamakoDeclaration",
|
||||||
|
icon_eligible: Icon26,
|
||||||
|
icon_signed: Icon24,
|
||||||
|
icon_ratified: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Kinshasa Convention",
|
||||||
|
name2: "KinshasaConvention",
|
||||||
|
icon_eligible: Icon4,
|
||||||
|
icon_signed: Icon6,
|
||||||
|
icon_ratified: Icon5,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ECOWAS Convention",
|
||||||
|
name2: "ECOWASConvention",
|
||||||
|
icon_eligible: Icon2,
|
||||||
|
icon_signed: Icon3,
|
||||||
|
icon_ratified: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Khartoum Declaration",
|
||||||
|
name2: "KhartoumDeclaration",
|
||||||
|
icon_eligible: Icon21,
|
||||||
|
icon_signed: Icon23,
|
||||||
|
icon_ratified: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Nairobi Protocol",
|
||||||
|
name2: "NairobiProtocol",
|
||||||
|
icon_eligible: Icon22,
|
||||||
|
icon_signed: Icon25,
|
||||||
|
icon_ratified: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "SADC Firearms Protocol",
|
||||||
|
name2: "SADCFirearmsProtocol",
|
||||||
|
icon_eligible: Icon8,
|
||||||
|
icon_signed: Icon7,
|
||||||
|
icon_ratified: Icon9,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const international_treaties = [
|
||||||
|
{
|
||||||
|
name: "Arms Trade Treaty",
|
||||||
|
name2: "ArmsTradeTreaty",
|
||||||
|
icon_eligible: Icon19,
|
||||||
|
icon_signed: Icon17,
|
||||||
|
icon_ratified: Icon18,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Firearms Protocol",
|
||||||
|
name2: "FirearmsProtocol",
|
||||||
|
icon_eligible: Icon12,
|
||||||
|
icon_signed: Icon10,
|
||||||
|
icon_ratified: Icon11,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Wassenaar Agreement",
|
||||||
|
name2: "WassenaarAgreement",
|
||||||
|
icon_eligible: Icon15,
|
||||||
|
icon_signed: Icon13,
|
||||||
|
icon_ratified: Icon14,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const international_guidelines = [
|
||||||
|
{
|
||||||
|
name: "UN Programme of Action",
|
||||||
|
name2: "UNProgrammeofAction",
|
||||||
|
icon_eligible: Icon20,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "International Tracing Instrument",
|
||||||
|
name2: "InternationalTracingInstrument",
|
||||||
|
icon_eligible: Icon16,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const african_guidelines = [
|
||||||
|
{
|
||||||
|
name: "Silencing the Guns in Africa Programme of Action",
|
||||||
|
name2: "StG-PoA",
|
||||||
|
icon_eligible: Icon1,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const DetailesSection = (props) => {
|
||||||
|
const { data, error, isLoading } = useAfricaData();
|
||||||
|
const countryID = props.countryID;
|
||||||
|
|
||||||
|
const [selectedCountry, setSelectedCountry] = useState("");
|
||||||
|
const [selectedRegionalOrganisations, setSelectedRegionalOrganisations] =
|
||||||
|
useState([]);
|
||||||
|
const [selectedRegionalTreaties, setSelectedRegionalTreaties] = useState([]);
|
||||||
|
const [selectedInternationalTreaties, setSelectedInternationalTreaties] =
|
||||||
|
useState([]);
|
||||||
|
const [selectedInternationalGuidelines, setSelectedInternationalGuidelines] =
|
||||||
|
useState([]);
|
||||||
|
const [selectedAfricanGuidelines, setSelectedAfricanGuidelines] = useState(
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (data && countryID !== null) {
|
||||||
|
const foundCountry = data.features.find(
|
||||||
|
(item) => item.properties.id === countryID
|
||||||
|
);
|
||||||
|
setSelectedCountry(foundCountry);
|
||||||
|
|
||||||
|
const regionalOrgs = regional_organisations.filter(
|
||||||
|
(item) => foundCountry.properties[item.name] === 1
|
||||||
|
);
|
||||||
|
setSelectedRegionalOrganisations(regionalOrgs);
|
||||||
|
|
||||||
|
const regionalTreats = regional_treaties
|
||||||
|
.filter((item) => foundCountry.properties[item.name2] !== "0")
|
||||||
|
.map((item) => {
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
state: foundCountry.properties[item.name2],
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const internationalTreats = international_treaties
|
||||||
|
.filter((item) => foundCountry.properties[item.name2] !== "0")
|
||||||
|
.map((item) => {
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
state: foundCountry.properties[item.name2],
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const internationalGuidelines = international_guidelines.filter(
|
||||||
|
(item) => foundCountry.properties[item.name2] === 1
|
||||||
|
);
|
||||||
|
|
||||||
|
const africanGuidelines = african_guidelines.filter(
|
||||||
|
(item) => foundCountry.properties[item.name2] === 1
|
||||||
|
);
|
||||||
|
|
||||||
|
setSelectedRegionalTreaties(regionalTreats);
|
||||||
|
setSelectedInternationalTreaties(internationalTreats);
|
||||||
|
setSelectedInternationalGuidelines(internationalGuidelines);
|
||||||
|
setSelectedAfricanGuidelines(africanGuidelines);
|
||||||
|
}
|
||||||
|
}, [data, countryID]);
|
||||||
|
|
||||||
|
// useEffect(() => {
|
||||||
|
// console.log(selectedAfricanGuidelines)
|
||||||
|
// }, [selectedAfricanGuidelines]);
|
||||||
|
|
||||||
|
if (isLoading) {
|
||||||
|
return <div>Loading...</div>;
|
||||||
|
}
|
||||||
|
if (error) {
|
||||||
|
return <div>Error</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card_ className="mt-3 p-3">
|
||||||
|
{selectedCountry && (
|
||||||
|
<div>
|
||||||
|
<h2>{selectedCountry.properties.name}</h2>
|
||||||
|
<p>
|
||||||
|
<strong>Regional Organisations: </strong>
|
||||||
|
{selectedRegionalOrganisations.map((item) => {
|
||||||
|
return (
|
||||||
|
<span
|
||||||
|
key={item.name}
|
||||||
|
style={{ color: item.color, padding: "0 5px" }}
|
||||||
|
>
|
||||||
|
{item.name}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</p>
|
||||||
|
<table className="table-sm table-bordered">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<strong>Regional Treaties: </strong>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<table className="table">
|
||||||
|
{selectedRegionalTreaties.map((item) => {
|
||||||
|
return (
|
||||||
|
<tr key={item.name}>
|
||||||
|
<td>{item.name}</td>
|
||||||
|
<td>{item.state}</td>
|
||||||
|
<td>
|
||||||
|
<img
|
||||||
|
title={item.name}
|
||||||
|
src={item["icon_" + item.state.toLowerCase()]}
|
||||||
|
alt=""
|
||||||
|
srcSet="No Image"
|
||||||
|
className="section-icon"
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<strong>International Treaties: </strong>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<table className="table">
|
||||||
|
{selectedInternationalTreaties.map((item) => {
|
||||||
|
return (
|
||||||
|
<tr key={item.name}>
|
||||||
|
<td>{item.name}</td>
|
||||||
|
<td>{item.state}</td>
|
||||||
|
<td>
|
||||||
|
<img
|
||||||
|
title={item.name}
|
||||||
|
src={item["icon_" + item.state.toLowerCase()]}
|
||||||
|
alt=""
|
||||||
|
srcSet="No Image"
|
||||||
|
className="section-icon"
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<strong>International Guidelines & Instruments: </strong>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<table className="table">
|
||||||
|
{selectedInternationalGuidelines.map((item) => {
|
||||||
|
return (
|
||||||
|
<tr key={item.name}>
|
||||||
|
<td>
|
||||||
|
<span>{item.name}</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<img
|
||||||
|
title={item.name}
|
||||||
|
src={item["icon_eligible"]}
|
||||||
|
alt=""
|
||||||
|
srcSet="No Image"
|
||||||
|
className="section-icon"
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<strong>African Guidelines & Instrumentss: </strong>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<table className="table">
|
||||||
|
{selectedAfricanGuidelines.map((item) => {
|
||||||
|
return (
|
||||||
|
<tr key={item.name}>
|
||||||
|
<td>
|
||||||
|
<span>{item.name}</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<img
|
||||||
|
title={item.name}
|
||||||
|
src={item["icon_eligible"]}
|
||||||
|
alt=""
|
||||||
|
srcSet="No Image"
|
||||||
|
className="section-icon"
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Card_>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DetailesSection;
|
@ -0,0 +1,76 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
import Col from "react-bootstrap/Col";
|
||||||
|
import "../../../Styles/main.scss";
|
||||||
|
import Geo_Org_Filter from "./Geo_Org_Filter";
|
||||||
|
import Reg_Org_Filter from "./Reg_Org_Filter";
|
||||||
|
import Treaties_Filter from "./Treaties_Filter";
|
||||||
|
import LanguageSelect from "./LanguageSelect";
|
||||||
|
|
||||||
|
import Button from "react-bootstrap/Button";
|
||||||
|
import Offcanvas from "react-bootstrap/Offcanvas";
|
||||||
|
|
||||||
|
const FilterBox = (props) => {
|
||||||
|
const [language, setLanguage] = useState("en");
|
||||||
|
const [show, setShow] = useState(false);
|
||||||
|
|
||||||
|
const handleLanguageChange = (language) => {
|
||||||
|
setLanguage(language);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClose = () => setShow(false);
|
||||||
|
const toggleShow = () => setShow((s) => !s);
|
||||||
|
|
||||||
|
const {
|
||||||
|
handleOrganizationClick,
|
||||||
|
handleTreatiesClick,
|
||||||
|
regional_organisations,
|
||||||
|
regional_treaties,
|
||||||
|
international_treaties,
|
||||||
|
geographical_regions,
|
||||||
|
instruments,
|
||||||
|
internationalIntsruments,
|
||||||
|
africanIntsruments,
|
||||||
|
} = props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Button variant="primary" className="d-lg-none" onClick={toggleShow}>
|
||||||
|
Filters
|
||||||
|
</Button>
|
||||||
|
<Offcanvas show={show} onHide={handleClose} backdrop={false} scroll={true} responsive="lg">
|
||||||
|
<Offcanvas.Header closeButton>
|
||||||
|
<Offcanvas.Title>Filter Box</Offcanvas.Title>
|
||||||
|
</Offcanvas.Header>
|
||||||
|
<Offcanvas.Body>
|
||||||
|
<div className={`filters-box`}>
|
||||||
|
<LanguageSelect onLanguageChange={handleLanguageChange} />
|
||||||
|
<hr />
|
||||||
|
<Geo_Org_Filter
|
||||||
|
handleOrganizationClick={handleOrganizationClick}
|
||||||
|
geographical_regions={geographical_regions}
|
||||||
|
language={language}
|
||||||
|
/>
|
||||||
|
<hr />
|
||||||
|
<Reg_Org_Filter
|
||||||
|
handleOrganizationClick={handleOrganizationClick}
|
||||||
|
regional_organisations={regional_organisations}
|
||||||
|
language={language}
|
||||||
|
/>
|
||||||
|
<hr />
|
||||||
|
<Treaties_Filter
|
||||||
|
regional_treaties={regional_treaties}
|
||||||
|
international_treaties={international_treaties}
|
||||||
|
instruments={instruments}
|
||||||
|
internationalIntsruments={internationalIntsruments}
|
||||||
|
africanIntsruments={africanIntsruments}
|
||||||
|
handleTreatiesClick={handleTreatiesClick}
|
||||||
|
language={language}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Offcanvas.Body>
|
||||||
|
</Offcanvas>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default FilterBox;
|
@ -0,0 +1,30 @@
|
|||||||
|
import React from "react";
|
||||||
|
|
||||||
|
const Geo_Org_Filter = (props) => {
|
||||||
|
const headings = {
|
||||||
|
en: "Geographical Regions",
|
||||||
|
fr: "Régions Géographiques",
|
||||||
|
ar: "المناطق الجغرافية",
|
||||||
|
};
|
||||||
|
const { handleOrganizationClick, geographical_regions, language } =
|
||||||
|
props;
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<h5>{headings[language] || headings['en']} </h5>
|
||||||
|
<div className="geographical-organisations">
|
||||||
|
{geographical_regions.map((org, index) => (
|
||||||
|
<div
|
||||||
|
key={org.name}
|
||||||
|
className="organization-item p-1"
|
||||||
|
style={{ backgroundColor: org.color }}
|
||||||
|
onClick={() => handleOrganizationClick(org.name, "", org.color)}
|
||||||
|
>
|
||||||
|
<div className="name">{org.name}</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Geo_Org_Filter;
|
@ -0,0 +1,41 @@
|
|||||||
|
import React, {useState} from "react";
|
||||||
|
import Button from 'react-bootstrap/Button';
|
||||||
|
import ButtonGroup from "react-bootstrap/ButtonGroup";
|
||||||
|
import ToggleButton from "react-bootstrap/ToggleButton";
|
||||||
|
const LanguageSelect = ({onLanguageChange}) => {
|
||||||
|
|
||||||
|
const [languageValue, setLanguageValue] = useState("en")
|
||||||
|
|
||||||
|
const languages = [
|
||||||
|
{ lang: "En", value: "en" },
|
||||||
|
{ lang: "Fr", value: "fr" },
|
||||||
|
{ lang: "ع", value: "ar" },
|
||||||
|
];
|
||||||
|
const handleLanguageChange = (language) => {
|
||||||
|
setLanguageValue(language);
|
||||||
|
onLanguageChange(language);
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ButtonGroup>
|
||||||
|
<Button variant="secondary" disabled>Language:</Button>{' '}
|
||||||
|
{languages.map((language, idx) => (
|
||||||
|
<ToggleButton
|
||||||
|
key={idx}
|
||||||
|
id={`language-${idx}`}
|
||||||
|
type="radio"
|
||||||
|
variant={"outline-secondary"}
|
||||||
|
name="language"
|
||||||
|
value={language.value}
|
||||||
|
checked={languageValue === language.value}
|
||||||
|
onChange={(e) => handleLanguageChange(e.currentTarget.value)}
|
||||||
|
>
|
||||||
|
{language.lang}
|
||||||
|
</ToggleButton>
|
||||||
|
))}
|
||||||
|
</ButtonGroup>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default LanguageSelect;
|
202
salw_client/src/Components/Layout/ControlInAfrica/MapInfoBox.jsx
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
import Collapse from "react-bootstrap/Collapse";
|
||||||
|
import Card_ from "../../UI/Card_/Card_";
|
||||||
|
|
||||||
|
const MapInfoBox = (props) => {
|
||||||
|
const { internationalIntsruments_, africanIntsruments_ } = props.info;
|
||||||
|
const regional_treaties = props.info.organisationsRegionalTreaties;
|
||||||
|
const international_treaties = props.info.organisationsInternationalTreaties;
|
||||||
|
const [open, setOpen] = useState(true);
|
||||||
|
const [isHidden, setIsHidden] = useState(false);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card_ className={props.className}>
|
||||||
|
<div
|
||||||
|
onClick={() => {
|
||||||
|
setOpen(!open);
|
||||||
|
setIsHidden(!isHidden);
|
||||||
|
}}
|
||||||
|
aria-controls="example-collapse-text"
|
||||||
|
aria-expanded={open}
|
||||||
|
style={{ display: "flex", justifyContent: "space-between" }}
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
<h3>{props.selectedRegion}</h3>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
<h3>{isHidden ? "Show" : "Hide"}</h3>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<Collapse in={open}>
|
||||||
|
<div className="example-collapse-text">
|
||||||
|
<p>Number of countries</p>
|
||||||
|
<div className="table-responsive-sm">
|
||||||
|
<table className="table table-sm table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th className="text-center" scope="col"></th>
|
||||||
|
<th className="text-center" scope="col">
|
||||||
|
Signed
|
||||||
|
</th>
|
||||||
|
<th className="text-center" scope="col">
|
||||||
|
Eligible
|
||||||
|
</th>
|
||||||
|
<th className="text-center" scope="col">
|
||||||
|
Ratified
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{regional_treaties &&
|
||||||
|
regional_treaties.map((item, index) => {
|
||||||
|
return (
|
||||||
|
<tr key={index}>
|
||||||
|
<th scope="row">{item.name}</th>
|
||||||
|
<td
|
||||||
|
className="text-center"
|
||||||
|
style={
|
||||||
|
item.signed
|
||||||
|
? {
|
||||||
|
color: props.selectedCountryColor,
|
||||||
|
fontWeight: "bold",
|
||||||
|
fontSize: "16px",
|
||||||
|
}
|
||||||
|
: {}
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{item.signed}
|
||||||
|
</td>
|
||||||
|
<td
|
||||||
|
className="text-center"
|
||||||
|
style={
|
||||||
|
item.eligible
|
||||||
|
? {
|
||||||
|
color: props.selectedCountryColor,
|
||||||
|
fontWeight: "bold",
|
||||||
|
fontSize: "16px",
|
||||||
|
}
|
||||||
|
: {}
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{item.eligible}
|
||||||
|
</td>
|
||||||
|
<td
|
||||||
|
className="text-center"
|
||||||
|
style={
|
||||||
|
item.ratified
|
||||||
|
? {
|
||||||
|
color: props.selectedCountryColor,
|
||||||
|
fontWeight: "bold",
|
||||||
|
fontSize: "16px",
|
||||||
|
}
|
||||||
|
: {}
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{item.ratified}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
|
||||||
|
{international_treaties &&
|
||||||
|
international_treaties.map((item, index) => {
|
||||||
|
return (
|
||||||
|
<tr key={index}>
|
||||||
|
<th scope="row">{item.name}</th>
|
||||||
|
<td
|
||||||
|
className="text-center"
|
||||||
|
style={
|
||||||
|
item.signed
|
||||||
|
? {
|
||||||
|
color: props.selectedCountryColor,
|
||||||
|
fontWeight: "bold",
|
||||||
|
fontSize: "16px",
|
||||||
|
}
|
||||||
|
: {}
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{item.signed}
|
||||||
|
</td>
|
||||||
|
<td
|
||||||
|
className="text-center"
|
||||||
|
style={
|
||||||
|
item.eligible
|
||||||
|
? {
|
||||||
|
color: props.selectedCountryColor,
|
||||||
|
fontWeight: "bold",
|
||||||
|
fontSize: "16px",
|
||||||
|
}
|
||||||
|
: {}
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{item.eligible}
|
||||||
|
</td>
|
||||||
|
<td
|
||||||
|
className="text-center"
|
||||||
|
style={
|
||||||
|
item.ratified
|
||||||
|
? {
|
||||||
|
color: props.selectedCountryColor,
|
||||||
|
fontWeight: "bold",
|
||||||
|
fontSize: "16px",
|
||||||
|
}
|
||||||
|
: {}
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{item.ratified}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{internationalIntsruments_ &&
|
||||||
|
internationalIntsruments_.map((item, index) => {
|
||||||
|
return (
|
||||||
|
<p className="mb-1" key={index}>
|
||||||
|
<strong>{item.name}:</strong>{" "}
|
||||||
|
<span
|
||||||
|
style={
|
||||||
|
item.countries
|
||||||
|
? {
|
||||||
|
color: props.selectedCountryColor,
|
||||||
|
fontWeight: "bold",
|
||||||
|
fontSize: "16px",
|
||||||
|
}
|
||||||
|
: {}
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{item.countries}
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
{africanIntsruments_ &&
|
||||||
|
africanIntsruments_.map((item, index) => {
|
||||||
|
return (
|
||||||
|
<p className="mb-1" key={index}>
|
||||||
|
<strong>{item.name}:</strong>{" "}
|
||||||
|
<span
|
||||||
|
style={
|
||||||
|
item.countries
|
||||||
|
? {
|
||||||
|
color: props.selectedCountryColor,
|
||||||
|
fontWeight: "bold",
|
||||||
|
fontSize: "16px",
|
||||||
|
}
|
||||||
|
: {}
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{item.countries}
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</Collapse>
|
||||||
|
</Card_>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default MapInfoBox;
|
@ -0,0 +1,22 @@
|
|||||||
|
import React from "react";
|
||||||
|
import L from "leaflet";
|
||||||
|
import { Marker } from "react-leaflet";
|
||||||
|
|
||||||
|
const MarkerIcon = (props) => {
|
||||||
|
return (
|
||||||
|
<Marker
|
||||||
|
key={props.index}
|
||||||
|
position= {props.position}
|
||||||
|
icon={
|
||||||
|
new L.Icon({
|
||||||
|
iconUrl: props.icon,
|
||||||
|
iconRetinaUrl: props.icon,
|
||||||
|
iconSize: [35, 35],
|
||||||
|
className: "leaflet-div-icon",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
></Marker>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default MarkerIcon;
|
@ -0,0 +1,26 @@
|
|||||||
|
import React from "react";
|
||||||
|
|
||||||
|
const Reg_Org_Filter = (props) => {
|
||||||
|
const { handleOrganizationClick, regional_organisations, language } = props;
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{language === "en" && <h5>Regional Organisations</h5>}
|
||||||
|
{language === "fr" && <h5>Organisations internationales</h5>}
|
||||||
|
{language === "ar" && <h5>المنظمات الإقليمية</h5>}
|
||||||
|
<div className="regional-organisations">
|
||||||
|
{regional_organisations.map((org, index) => (
|
||||||
|
<div
|
||||||
|
key={org.name}
|
||||||
|
className="organization-item"
|
||||||
|
style={{ backgroundColor: org.color }}
|
||||||
|
onClick={() => handleOrganizationClick(org.name, org.color)}
|
||||||
|
>
|
||||||
|
<div className="name">{org.name}</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Reg_Org_Filter;
|
@ -0,0 +1,15 @@
|
|||||||
|
import React from "react";
|
||||||
|
import Card_ from "../../UI/Card_/Card_";
|
||||||
|
|
||||||
|
const SelectedFilters = (props) => {
|
||||||
|
const { selectedRegion, selectedTreatyOfficialName } = props;
|
||||||
|
return (
|
||||||
|
<Card_ className="selected-filters p-2">
|
||||||
|
<h5>Selected Filter/s:</h5>
|
||||||
|
{selectedRegion && <li><i>{selectedRegion}</i></li>}
|
||||||
|
{selectedTreatyOfficialName && <li><i>{selectedTreatyOfficialName}</i></li>}
|
||||||
|
</Card_>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SelectedFilters;
|
21
salw_client/src/Components/Layout/ControlInAfrica/Title.js
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import React from "react";
|
||||||
|
|
||||||
|
const Title = () => {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="responsive-text text-center">
|
||||||
|
<h4 className="h4">
|
||||||
|
SALW control in Africa: Organisations, treaties and instruments
|
||||||
|
</h4>
|
||||||
|
<h4 className="h4">
|
||||||
|
مراقبة الاسلحة الصغيرة و الاسلحة الخفيفة في أفريقيا: المنظمات و
|
||||||
|
المعاهدات و الأدوات
|
||||||
|
</h4>
|
||||||
|
<h4 className="h4">
|
||||||
|
Contrôle des ALPC en Afrique : Organisations, traités et instruments
|
||||||
|
</h4>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Title;
|
@ -0,0 +1,238 @@
|
|||||||
|
import React from "react";
|
||||||
|
import Icon1 from "../../../Icons/icon1.svg";
|
||||||
|
import Icon16 from "../../../Icons/icon16.svg";
|
||||||
|
import Icon20 from "../../../Icons/icon20.svg";
|
||||||
|
|
||||||
|
const Treaties_Filter = (props) => {
|
||||||
|
const regionalTreatiesHeadings = {
|
||||||
|
en: "Regional Treaties",
|
||||||
|
fr: "Traités régionales",
|
||||||
|
ar: "المعاهدات الأقليمية",
|
||||||
|
};
|
||||||
|
const internationalTreatiesHeadings = {
|
||||||
|
en: "International Treaties",
|
||||||
|
fr: "Traités internationales",
|
||||||
|
ar: "المعاهدات الدولية",
|
||||||
|
};
|
||||||
|
|
||||||
|
const africanGuidelinesHeadings = {
|
||||||
|
en: "African Guidelines & Instrumentss",
|
||||||
|
fr: "Directives & instruments africains",
|
||||||
|
ar: "المبادىء التوجيهية و الأدوات السياسية في افريقيا",
|
||||||
|
};
|
||||||
|
const {
|
||||||
|
international_treaties,
|
||||||
|
handleTreatiesClick,
|
||||||
|
regional_treaties,
|
||||||
|
language,
|
||||||
|
instruments,
|
||||||
|
internationalIntsruments,
|
||||||
|
africanIntsruments,
|
||||||
|
} = props;
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<h5>
|
||||||
|
{regionalTreatiesHeadings[language] || regionalTreatiesHeadings["en"]}
|
||||||
|
</h5>
|
||||||
|
|
||||||
|
<div className="regional-treaties">
|
||||||
|
{language === "en" && (
|
||||||
|
<div className="treaty-item">
|
||||||
|
<div className="treaty-item-name">Eligible</div>
|
||||||
|
<div className="treaty-item-name">Signed</div>
|
||||||
|
<div className="treaty-item-name">Ratified</div>
|
||||||
|
<div className="treaty-item-name"></div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{language === "fr" && (
|
||||||
|
<div className="treaty-item">
|
||||||
|
<div className="treaty-item-name">Eligible</div>
|
||||||
|
<div className="treaty-item-name">Signé</div>
|
||||||
|
<div className="treaty-item-name">Ratifié</div>
|
||||||
|
<div className="treaty-item-name"></div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{language === "ar" && (
|
||||||
|
<div className="treaty-item">
|
||||||
|
<div className="treaty-item-name">المتفق عليها</div>
|
||||||
|
<div className="treaty-item-name">موقعة</div>
|
||||||
|
<div className="treaty-item-name">مصدق عليها</div>
|
||||||
|
<div className="treaty-item-name"></div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{regional_treaties.map((treaty) => (
|
||||||
|
<div key={treaty.name} className="treaty-item">
|
||||||
|
{treaty.icon_eligible ? (
|
||||||
|
<img
|
||||||
|
src={treaty.icon_eligible}
|
||||||
|
alt={`${treaty.name}-Eligible`}
|
||||||
|
title={`${treaty.name}-Eligible`}
|
||||||
|
srcSet=""
|
||||||
|
className="icon"
|
||||||
|
onClick={() =>
|
||||||
|
handleTreatiesClick(treaty.name2, "Eligible", treaty.name)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<div className="icon"></div>
|
||||||
|
)}
|
||||||
|
{treaty.icon_signed ? (
|
||||||
|
<img
|
||||||
|
src={treaty.icon_signed}
|
||||||
|
alt={`${treaty.name}-Signed`}
|
||||||
|
title={`${treaty.name}-Signed`}
|
||||||
|
srcSet=""
|
||||||
|
className="icon"
|
||||||
|
onClick={() =>
|
||||||
|
handleTreatiesClick(treaty.name2, "Signed", treaty.name)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<div className="icon"></div>
|
||||||
|
)}
|
||||||
|
{treaty.icon_ratified ? (
|
||||||
|
<img
|
||||||
|
src={treaty.icon_ratified}
|
||||||
|
alt={`${treaty.name}-Ratified`}
|
||||||
|
title={`${treaty.name}-Ratified`}
|
||||||
|
srcSet=""
|
||||||
|
className="icon"
|
||||||
|
onClick={() =>
|
||||||
|
handleTreatiesClick(treaty.name2, "Ratified", treaty.name)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<div className="icon"></div>
|
||||||
|
)}
|
||||||
|
<div className="treaty-item-name">{treaty.name}</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<hr />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h5>
|
||||||
|
{internationalTreatiesHeadings[language] ||
|
||||||
|
internationalTreatiesHeadings["en"]}
|
||||||
|
</h5>
|
||||||
|
{international_treaties.map((treaty) => (
|
||||||
|
<div key={treaty.name} className="treaty-item">
|
||||||
|
{treaty.icon_eligible ? (
|
||||||
|
<img
|
||||||
|
src={treaty.icon_eligible}
|
||||||
|
alt={`${treaty.name}-Eligible`}
|
||||||
|
title={`${treaty.name}-Eligible`}
|
||||||
|
srcSet=""
|
||||||
|
className="icon-2"
|
||||||
|
onClick={() =>
|
||||||
|
handleTreatiesClick(treaty.name2, "Eligible", treaty.name)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<div className="icon"></div>
|
||||||
|
)}
|
||||||
|
{treaty.icon_signed ? (
|
||||||
|
<img
|
||||||
|
src={treaty.icon_signed}
|
||||||
|
alt={`${treaty.name}-Signed`}
|
||||||
|
title={`${treaty.name}-Signed`}
|
||||||
|
srcSet=""
|
||||||
|
className="icon-2"
|
||||||
|
onClick={() =>
|
||||||
|
handleTreatiesClick(treaty.name2, "Signed", treaty.name)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<div className="icon"></div>
|
||||||
|
)}
|
||||||
|
{treaty.icon_ratified ? (
|
||||||
|
<img
|
||||||
|
src={treaty.icon_ratified}
|
||||||
|
alt={`${treaty.name}-Ratified`}
|
||||||
|
title={`${treaty.name}-Ratified`}
|
||||||
|
srcSet=""
|
||||||
|
className="icon-2"
|
||||||
|
onClick={() =>
|
||||||
|
handleTreatiesClick(treaty.name2, "Ratified", treaty.name)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<div className="icon"></div>
|
||||||
|
)}
|
||||||
|
<div className="treaty-item-name">{treaty.name}</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
<hr />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{language === "en" && (
|
||||||
|
<h5>
|
||||||
|
International Guidelines & Instruments <br />
|
||||||
|
<small>(countries with recent activities only, 2014 - 2019)</small>
|
||||||
|
</h5>
|
||||||
|
)}
|
||||||
|
{language === "fr" && (
|
||||||
|
<h5>
|
||||||
|
Directives & instruments internationaux <br />
|
||||||
|
<small>(pays avec activité récente uniquement, 2014 - 2019)</small>
|
||||||
|
</h5>
|
||||||
|
)}
|
||||||
|
{language === "ar" && (
|
||||||
|
<h5>
|
||||||
|
المبادىء التوجيهية و الأدوات الدولية <br />
|
||||||
|
<small>(فقط الدول ذات النشاطات الحديثة 2014-2019)</small>
|
||||||
|
</h5>
|
||||||
|
)}
|
||||||
|
{internationalIntsruments.map((instrument) => (
|
||||||
|
<div key={instrument.name} className="instrument-item">
|
||||||
|
<img
|
||||||
|
src={instrument.icon}
|
||||||
|
alt={instrument.name}
|
||||||
|
title={instrument.name}
|
||||||
|
srcSet=""
|
||||||
|
className="icon-2"
|
||||||
|
onClick={() =>
|
||||||
|
handleTreatiesClick(
|
||||||
|
instrument.name2,
|
||||||
|
"checked",
|
||||||
|
instrument.name
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<div className="treaty-item-name">{instrument.name}</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
<hr />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h5>
|
||||||
|
{africanGuidelinesHeadings[language] ||
|
||||||
|
africanGuidelinesHeadings["en"]}
|
||||||
|
</h5>
|
||||||
|
|
||||||
|
{africanIntsruments.map((instrument) => (
|
||||||
|
<div key={instrument.name} className="instrument-item">
|
||||||
|
<img
|
||||||
|
src={instrument.icon}
|
||||||
|
alt={instrument.name}
|
||||||
|
title={instrument.name}
|
||||||
|
srcSet=""
|
||||||
|
className="icon-2"
|
||||||
|
onClick={() =>
|
||||||
|
handleTreatiesClick(
|
||||||
|
instrument.name2,
|
||||||
|
"checked",
|
||||||
|
instrument.name
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<div className="treaty-item-name">{instrument.name}</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Treaties_Filter;
|
@ -0,0 +1,54 @@
|
|||||||
|
import React, {useState} from "react";
|
||||||
|
import Card_ from "../../UI/Card_/Card_";
|
||||||
|
import Collapse from "react-bootstrap/Collapse";
|
||||||
|
|
||||||
|
const TreatyInfoBox = (props) => {
|
||||||
|
const [open, setOpen] = useState(true);
|
||||||
|
const [isHidden, setIsHidden] = useState(false);
|
||||||
|
const {
|
||||||
|
selectedRegion,
|
||||||
|
currentStatuesTreaty,
|
||||||
|
selectedTreatyOfficialName,
|
||||||
|
selectedCountriesNamesTreaties,
|
||||||
|
handleCountryChange,
|
||||||
|
} = props;
|
||||||
|
return (
|
||||||
|
<Card_ className="selected-treaty-card">
|
||||||
|
<div
|
||||||
|
onClick={() => setOpen(!open)}
|
||||||
|
aria-controls="example-collapse-text"
|
||||||
|
aria-expanded={open}
|
||||||
|
>
|
||||||
|
<h5>
|
||||||
|
{selectedRegion} members {currentStatuesTreaty}{" "}
|
||||||
|
{selectedTreatyOfficialName}
|
||||||
|
</h5>
|
||||||
|
</div>
|
||||||
|
<Collapse in={open}>
|
||||||
|
<div id="example-collapse-text">
|
||||||
|
{selectedCountriesNamesTreaties.length > 0 ? (
|
||||||
|
<ul>
|
||||||
|
{selectedCountriesNamesTreaties.map((country, index) => (
|
||||||
|
<li
|
||||||
|
onClick={handleCountryChange}
|
||||||
|
data-country={country}
|
||||||
|
key={index}
|
||||||
|
className="countries-list"
|
||||||
|
>
|
||||||
|
{country}
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
) : (
|
||||||
|
<p>
|
||||||
|
No {selectedRegion} members have {currentStatuesTreaty}{" "}
|
||||||
|
{selectedTreatyOfficialName}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</Collapse>
|
||||||
|
</Card_>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TreatyInfoBox;
|
@ -0,0 +1,26 @@
|
|||||||
|
export const CountryStyle = () => {
|
||||||
|
return {
|
||||||
|
color: "black",
|
||||||
|
weight: 1,
|
||||||
|
opacity: 1,
|
||||||
|
fillColor: "#FDEDE2",
|
||||||
|
fillOpacity: 0.3,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const CountrySelectedStyle = (color, opacity = 0.3) => {
|
||||||
|
return {
|
||||||
|
fillColor: color,
|
||||||
|
color: "black",
|
||||||
|
weight: 3,
|
||||||
|
fillOpacity: opacity,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const CountryHighlightStyle = () => {
|
||||||
|
return {
|
||||||
|
fillColor: "yellow",
|
||||||
|
color: "black",
|
||||||
|
weight: 3,
|
||||||
|
};
|
||||||
|
};
|
@ -0,0 +1,29 @@
|
|||||||
|
import React from "react";
|
||||||
|
|
||||||
|
import Container from "react-bootstrap/esm/Container";
|
||||||
|
|
||||||
|
const MainDescription = () => {
|
||||||
|
return (
|
||||||
|
<Container className="mt-5">
|
||||||
|
<p>
|
||||||
|
<strong>SALW Guide</strong> The Interactive Guide on Small Arms and Light Weapons is an
|
||||||
|
online database that provides information on the global distribution of,
|
||||||
|
and how to identify commonly used* small arms and light weapons (SALW)
|
||||||
|
in organized violence. It is designed to build knowledge on how to
|
||||||
|
recognize different types, makes and models of commonly used SALW; to
|
||||||
|
collect data on the global and country-specific spread of these SALW;
|
||||||
|
and to describe some of their visual and technical specifications. The
|
||||||
|
guide is not an exhaustive list of all SALW that are used around the
|
||||||
|
world. The interactive Guide was developed by BICC in close cooperation
|
||||||
|
with the Bundeswehr Verification Center (BwVC) and with generous support
|
||||||
|
of the Federal Foreign Office, Germany. * This is based on information
|
||||||
|
provided by the German Bundeswehr Verification Center. The SALW Guide is
|
||||||
|
also a contribution to the UN Programme of Action (PoA) to Prevent,
|
||||||
|
Combat and Eradicate the Illicit Trade in Small Arms and Light Weapons
|
||||||
|
in All Its Aspects.
|
||||||
|
</p>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default MainDescription;
|
43
salw_client/src/Components/Layout/NavBarSalw/NavBarSalw.js
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
|
||||||
|
|
||||||
|
import Container from "react-bootstrap/Container";
|
||||||
|
import Nav from "react-bootstrap/Nav";
|
||||||
|
import Navbar from "react-bootstrap/Navbar";
|
||||||
|
import Home from "../../Pages/Home";
|
||||||
|
import About from "../../Pages/About";
|
||||||
|
import ControlInAfrica from "../../Pages/ControlInAfrica";
|
||||||
|
import PSSM from "../../Pages/PSSM";
|
||||||
|
|
||||||
|
const NavBarSalw = () => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Router>
|
||||||
|
<Navbar expand="lg" className="bg-body-tertiary nav-bar">
|
||||||
|
<Container fluid className="ps-5">
|
||||||
|
<Navbar.Brand className="nav-bar-title" href="#home">SALW Guide |</Navbar.Brand>
|
||||||
|
|
||||||
|
<Navbar.Toggle aria-controls="basic-navbar-nav" />
|
||||||
|
<Navbar.Collapse id="basic-navbar-nav">
|
||||||
|
<Nav className="me-auto">
|
||||||
|
<Nav.Link className="nav-bar-item" href="home">Home</Nav.Link>
|
||||||
|
<Nav.Link className="nav-bar-item" href="ControlInAfrica">SALW Control in Africa</Nav.Link>
|
||||||
|
<Nav.Link className="nav-bar-item" href="pssm">PSSM</Nav.Link>
|
||||||
|
<Nav.Link className="nav-bar-item" href="about">About</Nav.Link>
|
||||||
|
</Nav>
|
||||||
|
</Navbar.Collapse>
|
||||||
|
</Container>
|
||||||
|
</Navbar>
|
||||||
|
|
||||||
|
<Routes>
|
||||||
|
<Route path="/home" element={<Home />} />
|
||||||
|
<Route path="/ControlInAfrica" element={<ControlInAfrica />} />
|
||||||
|
<Route path="/pssm" element={<PSSM />} />
|
||||||
|
<Route path="/about" element={<About />} />
|
||||||
|
</Routes>
|
||||||
|
</Router>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default NavBarSalw;
|
174
salw_client/src/Components/Layout/PSSM/Blurb.js
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
import Card_ from "../../UI/Card_/Card_";
|
||||||
|
import DOMPurify from "dompurify";
|
||||||
|
import parse from "html-react-parser";
|
||||||
|
import Collapse from "react-bootstrap/Collapse";
|
||||||
|
|
||||||
|
const Blurb = () => {
|
||||||
|
DOMPurify.addHook("afterSanitizeAttributes", function (node) {
|
||||||
|
// set all elements owning target to target=_blank
|
||||||
|
if ("target" in node) {
|
||||||
|
node.setAttribute("target", "_blank");
|
||||||
|
node.setAttribute("rel", "noopener");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const [footnotes, setFootnotes] = useState([
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
text: "Weapons are illegally given out for a short period of time in return for some money. These weapons are often used in criminal activities and then returned. This practice has been used to supplement a low salary/income.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
text: "UNODA Training Manual on Gender-Mainstreaming Small Arms Control, p.132, UNODA-Gender-SALW-Training-Manual®.pdf (un-arm.org)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
text: "Organization for Security and Co-operation in Europe (OSCE), Best Practice Guide on National Procedures for Stockpile Management and Security of Small Arms and Light Weapons, 511204.pdf (<a href='https://www.osce.org/files/f/documents/6/1/511204.pdf' target='_blank'>osce.org</a>), p.2",
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card_ className="blurb p-3">
|
||||||
|
<MainText footnotes={footnotes} />
|
||||||
|
</Card_>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const MainText = ({ footnotes }) => {
|
||||||
|
const [open, setOpen] = useState(true);
|
||||||
|
const [isHidden, setIsHidden] = useState(true);
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h3>Physical Security and Stockpile Management (PSSM)</h3>
|
||||||
|
<p>
|
||||||
|
Diverted or ‘lost’ from poorly managed storage facilities, ‘recycled’
|
||||||
|
from one conflict to another or ‘rented out’
|
||||||
|
<sup>
|
||||||
|
<a href="#footnote-1">1</a>
|
||||||
|
</sup>
|
||||||
|
, small arms and light weapons (SALW) and their ammunition remain a
|
||||||
|
primary obstacle to the de-escalation of violent conflicts, national and
|
||||||
|
regional stability and peace-building efforts. Coupled with inadequate
|
||||||
|
storage practices, they further pose a serious threat to the safety and
|
||||||
|
security of nearby communities and civilian infrastructure, such as
|
||||||
|
schools and hospitals, and their easy accessibility increases the risk
|
||||||
|
that they are misused to commit armed violence (often against young men)
|
||||||
|
or acts of gender-based violence (GBV), often against women
|
||||||
|
<sup>
|
||||||
|
<a href="#footnote-2">2</a>
|
||||||
|
</sup>
|
||||||
|
.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<Collapse in={open}>
|
||||||
|
<div id="example-collapse-text">
|
||||||
|
<p>
|
||||||
|
Physical Security and Stockpile Management (PSSM) consists of the
|
||||||
|
“procedures and activities that are necessary for the safe and
|
||||||
|
secure accounting, storage, transportation and handling of SALW”
|
||||||
|
<sup>
|
||||||
|
<a href="#footnote-3">3</a>
|
||||||
|
</sup>
|
||||||
|
. It can therefore be viewed as a key element of practical weapons
|
||||||
|
and ammunition management, and it significantly decreases the risk
|
||||||
|
of illicit proliferation, trafficking and diversion of firearms,
|
||||||
|
ammunition, and explosives as well as reduces the risk of
|
||||||
|
Unintentional Munitions Explosions.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Responsible management of stockpiles can therefore positively impact
|
||||||
|
on efforts to reduce armed violence and contribute towards enhancing
|
||||||
|
the security of the surrounding communities as well as the security
|
||||||
|
at the local, national and regional level.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>Regional PSSM Training of Trainers (ToT) processes</h3>
|
||||||
|
<p>
|
||||||
|
Since 2016, the bicc advisory team on Weapons and Ammunition
|
||||||
|
Management (WAM) has been supporting two multi-stakeholder regional
|
||||||
|
PSSM Training of Trainers (ToT) processes; one in East Africa (with
|
||||||
|
the Regional Centre on Small Arms in the Great Lakes Region, the
|
||||||
|
Horn of Africa and Bordering States, RECSA) and one in West Africa
|
||||||
|
(with the Economic Community of West African States, ECOWAS).
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The aim of both processes was to support and enhance regional
|
||||||
|
ownership, strengthen PSSM capacities, establish sustainable
|
||||||
|
structures by creating a regional trainer pool whose trainers can
|
||||||
|
independently train more trainers that equally possess the necessary
|
||||||
|
regional and local knowledge, thereby decreasing a dependency on
|
||||||
|
foreign experts. The focus on regional ownership and sustainability
|
||||||
|
represents a crucial piece of the peace and security puzzle, in
|
||||||
|
alignment with SDG 16.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Based on the UN Programme of Action, and acknowledging PSSM as a key
|
||||||
|
element of WAM, the Multinational Small Arms and Ammunition Group
|
||||||
|
(MSAG) initiated a training programme on the security and stockpile
|
||||||
|
management of weapons, ammunition, and explosives for East African
|
||||||
|
states in Kenya in 2012. Participants of the ToT processes derived
|
||||||
|
from among the military, police and wildlife service sectors. Up
|
||||||
|
until March 2024, 469 participants have been trained, out of which
|
||||||
|
42 were certified as PSSM Instructors and 13 as Senior Instructors.
|
||||||
|
The map below shows their geographical distribution.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
In the meantime, the need for another regional PSSM ToT process was
|
||||||
|
identified in the ECOWAS region (West Africa), which was established
|
||||||
|
in 2018 and completed in 2023. Based on the identified need for a
|
||||||
|
regional trainer pool and more accountable PSSM practices, this
|
||||||
|
process also took into account lessons learned from the East Africa
|
||||||
|
ToT process. Between 2018 and 2023, a total of 000 participants have
|
||||||
|
been trained, out of which 000 were certified as PSSM Instructors
|
||||||
|
and 000 as Senior Instructors. The map below shows their
|
||||||
|
geographical distribution.
|
||||||
|
</p>
|
||||||
|
<p>Stakeholders implementing the regional PSSM ToT trainings were:</p>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
RECSA, MSAG nations (namely the Bundeswehr Verification Centre,
|
||||||
|
the Austrian Verification Centre, Denmark, among others), IPSTC
|
||||||
|
(International Peace Support Training Centre) in Nairobi/Kenya and
|
||||||
|
bicc.
|
||||||
|
</li>
|
||||||
|
<li>ECOWAS, MSAG (the Bundeswehr Verification Centre) and bicc.</li>
|
||||||
|
</ul>
|
||||||
|
<p>
|
||||||
|
Each of these partners brings a unique skillset that complements
|
||||||
|
that of the other stakeholders.
|
||||||
|
</p>
|
||||||
|
<div>
|
||||||
|
<h4>
|
||||||
|
<hr />
|
||||||
|
</h4>
|
||||||
|
{footnotes.map((footnote) => (
|
||||||
|
<ul key={footnote.id}>
|
||||||
|
<li
|
||||||
|
className="list-unstyled"
|
||||||
|
key={footnote.id}
|
||||||
|
id={`footnote-${footnote.id}`}
|
||||||
|
>
|
||||||
|
<small>{parse(`${footnote.id}. ${footnote.text}`)}</small>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Collapse>
|
||||||
|
{/* <a
|
||||||
|
href="#"
|
||||||
|
onClick={() => {
|
||||||
|
setOpen(!open);
|
||||||
|
setIsHidden(!isHidden);
|
||||||
|
}}
|
||||||
|
aria-controls="example-collapse-text"
|
||||||
|
aria-expanded={open}
|
||||||
|
>
|
||||||
|
{isHidden ? "Read more" : "Read less"}
|
||||||
|
</a> */}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Blurb;
|
53
salw_client/src/Components/Layout/PSSM/ImageGallery.jsx
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
import usePhotos from "./ImportImages";
|
||||||
|
import Card_ from "../../UI/Card_/Card_";
|
||||||
|
|
||||||
|
const ImageGallery = () => {
|
||||||
|
const [selectedImage, setSelectedImage] = useState(null);
|
||||||
|
|
||||||
|
const handleThumbnailClick = (image) => {
|
||||||
|
setSelectedImage(image);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCloseModal = () => {
|
||||||
|
setSelectedImage(null);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card_ className="mt-3 p-3">
|
||||||
|
<div className="image-gallery">
|
||||||
|
{Object.keys(usePhotos).map((key, index) => (
|
||||||
|
<img
|
||||||
|
key={index}
|
||||||
|
src={usePhotos[key]}
|
||||||
|
alt={key}
|
||||||
|
className="thumbnail"
|
||||||
|
onClick={() => handleThumbnailClick(usePhotos[key])}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
{selectedImage && (
|
||||||
|
<div className="modal" onClick={handleCloseModal}>
|
||||||
|
<div className="modal-content" onClick={(e) => e.stopPropagation()}>
|
||||||
|
<span className="close" onClick={handleCloseModal}>
|
||||||
|
×
|
||||||
|
</span>
|
||||||
|
<img
|
||||||
|
src={selectedImage}
|
||||||
|
alt="Full Size"
|
||||||
|
className="full-size-image"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div className="mt-3">
|
||||||
|
<p>
|
||||||
|
Pictures have been taken by ©Nikhil Achary, ©IPSTC/Kenya, ©MSAG AUT,
|
||||||
|
and ©Hans Lampalzer (BLMV).{" "}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Card_>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ImageGallery;
|
10
salw_client/src/Components/Layout/PSSM/ImpactStories.jsx
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import Card_ from '../../UI/Card_/Card_'
|
||||||
|
const ImpactStories = (props) => {
|
||||||
|
const {className} = props;
|
||||||
|
return (
|
||||||
|
<Card_ className={className}>ImpactStories</Card_>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ImpactStories
|
22
salw_client/src/Components/Layout/PSSM/ImportImages.js
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// src/importImages.js
|
||||||
|
function importAll(r) {
|
||||||
|
let images = {};
|
||||||
|
r.keys().map((item, index) => {
|
||||||
|
images[item.replace('./', '')] = r(item);
|
||||||
|
});
|
||||||
|
return images;
|
||||||
|
}
|
||||||
|
|
||||||
|
const images = importAll(require.context('../../../img/pssm', false, /\.(png|jpe?g|svg)$/));
|
||||||
|
|
||||||
|
fetch('../../../data/Photos.geojson').then(response => {
|
||||||
|
return response.json();
|
||||||
|
}).then(data => {
|
||||||
|
// Work with JSON data here
|
||||||
|
console.log("Test")
|
||||||
|
console.log(data);
|
||||||
|
}).catch(err => {
|
||||||
|
// Do something for an error here
|
||||||
|
});
|
||||||
|
|
||||||
|
export default images;
|
18
salw_client/src/Components/Layout/PSSM/Legend.jsx
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import React from "react";
|
||||||
|
|
||||||
|
const Legend = () => {
|
||||||
|
return (
|
||||||
|
<div className="legend-container">
|
||||||
|
<div className="legend-item">
|
||||||
|
<div className="legend-recsa"></div>
|
||||||
|
<span>RECSA</span>
|
||||||
|
</div>
|
||||||
|
<div className="legend-item">
|
||||||
|
<div className="legend-ecowas"></div>
|
||||||
|
<span>ECOWAS</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Legend;
|
53
salw_client/src/Components/Layout/PSSM/MarkerCustom.jsx
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { Marker, Tooltip } from "react-leaflet";
|
||||||
|
|
||||||
|
import Person from "../../../Icons/person.svg";
|
||||||
|
import Person2 from "../../../Icons/person2.svg";
|
||||||
|
import Person3 from "../../../Icons/person3.svg";
|
||||||
|
|
||||||
|
const MarkerCustom = (props) => {
|
||||||
|
const { feature, pssmCountryData } = props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Marker
|
||||||
|
position={[feature.properties.y, feature.properties.x]}
|
||||||
|
>
|
||||||
|
<Tooltip
|
||||||
|
direction="bottom"
|
||||||
|
offset={[-13, 27]}
|
||||||
|
opacity={1}
|
||||||
|
permanent
|
||||||
|
className="tooltip-custom"
|
||||||
|
>
|
||||||
|
<h5>{feature.properties.name}</h5>
|
||||||
|
<div>
|
||||||
|
<ul className="list-unstyled tooltip-text">
|
||||||
|
<li>
|
||||||
|
<img src={Person3} className="person-icon" /> Number of
|
||||||
|
participants trained:{" "}
|
||||||
|
<span className="tooltip-text-number">
|
||||||
|
{pssmCountryData["trained_participants"] || "-"}
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<img src={Person2} className="person-icon" /> Number of PSSM
|
||||||
|
instractors:{" "}
|
||||||
|
<span className="tooltip-text-number">
|
||||||
|
{pssmCountryData["pssm_instractors"] || "-"}
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<img src={Person} className="person-icon" /> Number of senior PSSM
|
||||||
|
instractors:{" "}
|
||||||
|
<span className="tooltip-text-number">
|
||||||
|
{pssmCountryData["senior_pssm_instractors"] || "-"}
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
|
</Marker>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default MarkerCustom;
|
300
salw_client/src/Components/Layout/PSSM/PSSM.jsx
Normal file
@ -0,0 +1,300 @@
|
|||||||
|
import React, { useEffect, createRef } from "react";
|
||||||
|
|
||||||
|
import { MapContainer, GeoJSON, useMap } from "react-leaflet";
|
||||||
|
import L from "leaflet";
|
||||||
|
import Africa from "../../../Data/PSSM.geojson";
|
||||||
|
import Photos from "../../../Data/Photos.geojson";
|
||||||
|
import Africa_Outline from "../../../Data/Africa_outline.geojson";
|
||||||
|
import { fetchPSSMCountries } from '../../../api/api';
|
||||||
|
|
||||||
|
import "../../../Styles/main.scss";
|
||||||
|
import Card_ from "../../UI/Card_/Card_";
|
||||||
|
import { CountrySelectedStyle, NotPSSMCountryStyle } from "./countryStyles";
|
||||||
|
import MarkerCustom from "./MarkerCustom";
|
||||||
|
import SelectMenu from "./SelectMenu";
|
||||||
|
import Legend from "./Legend";
|
||||||
|
|
||||||
|
// Custom Zoom Control Component
|
||||||
|
const CustomZoomControl = React.memo(() => {
|
||||||
|
const map = useMap();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const zoomControl = L.control.zoom({
|
||||||
|
position: "topright", // Change the position to bottom right
|
||||||
|
});
|
||||||
|
map.addControl(zoomControl);
|
||||||
|
|
||||||
|
// Clean up the control on component unmount
|
||||||
|
return () => {
|
||||||
|
map.removeControl(zoomControl);
|
||||||
|
};
|
||||||
|
}, [map]);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
|
class PSSM extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.mapRef = createRef(); // Create a ref to store the MapContainer instance
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
africaOutline: null,
|
||||||
|
africaCountries: null,
|
||||||
|
photos: null,
|
||||||
|
//countriesNames: [],
|
||||||
|
pssmCountries: [],
|
||||||
|
pssmData: [],
|
||||||
|
recsaCountries: [],
|
||||||
|
ecowasCountries: [],
|
||||||
|
loading: true,
|
||||||
|
error: null,
|
||||||
|
selectedCountry: "",
|
||||||
|
|
||||||
|
center: [3, 15],
|
||||||
|
zoom: 3.5,
|
||||||
|
zoomSnap: 0.5,
|
||||||
|
scrollWheelZoom: false,
|
||||||
|
zoomControl: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.fetchData();
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchData = async () => {
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response_countries = await fetch(Africa);
|
||||||
|
const data_africa = await response_countries.json();
|
||||||
|
|
||||||
|
const response_africa_outline = await fetch(Africa_Outline);
|
||||||
|
const data_outline = await response_africa_outline.json();
|
||||||
|
|
||||||
|
const response_photos = await fetch(Photos);
|
||||||
|
const data_photos = await response_photos.json();
|
||||||
|
|
||||||
|
const data_pssm_data = await fetchPSSMCountries();
|
||||||
|
|
||||||
|
this.setState(
|
||||||
|
{
|
||||||
|
africaCountries: data_africa.features,
|
||||||
|
|
||||||
|
pssmCountries: data_africa.features.filter(
|
||||||
|
(feature) =>
|
||||||
|
data_pssm_data.find(
|
||||||
|
(item) =>
|
||||||
|
item.country === feature.properties.id && item.recsa === true
|
||||||
|
) ||
|
||||||
|
data_pssm_data.find(
|
||||||
|
(item) =>
|
||||||
|
item.country === feature.properties.id && item.ecowas === true
|
||||||
|
)
|
||||||
|
),
|
||||||
|
|
||||||
|
recsaCountries: data_africa.features.filter((feature) =>
|
||||||
|
data_pssm_data.find(
|
||||||
|
(item) =>
|
||||||
|
item.country === feature.properties.id && item.recsa === true
|
||||||
|
)
|
||||||
|
),
|
||||||
|
ecowasCountries: data_africa.features.filter((feature) =>
|
||||||
|
data_pssm_data.find(
|
||||||
|
(item) =>
|
||||||
|
item.country === feature.properties.id && item.ecowas === true
|
||||||
|
)
|
||||||
|
),
|
||||||
|
|
||||||
|
pssmData: data_pssm_data,
|
||||||
|
africaOutline: data_outline.features,
|
||||||
|
photos: data_photos.PSSM_PHOTOS,
|
||||||
|
loading: false,
|
||||||
|
},
|
||||||
|
() => {}
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
this.setState({
|
||||||
|
error: error,
|
||||||
|
loading: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
onEachFeature = (feature, layer) => {
|
||||||
|
// Bind event to layer
|
||||||
|
layer.on({
|
||||||
|
click: this.onMouseClick,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
resetMap = () => {
|
||||||
|
if (this.mapRef.current) {
|
||||||
|
this.mapRef.current.setView(this.state.center, this.state.zoom); // Set the center and zoom to initial values
|
||||||
|
}
|
||||||
|
};
|
||||||
|
zoomIn = () => {
|
||||||
|
if (this.mapRef.current) {
|
||||||
|
this.mapRef.current.setZoom(this.mapRef.current.getZoom() + 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
zoomOut = () => {
|
||||||
|
if (this.mapRef.current) {
|
||||||
|
this.mapRef.current.setZoom(this.mapRef.current.getZoom() - 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
onMouseClick = (e) => {
|
||||||
|
this.setState({
|
||||||
|
selectedCountriesFilter: [],
|
||||||
|
selectedCountryColor: "yellow",
|
||||||
|
});
|
||||||
|
const countryName = e.target.feature.properties.name;
|
||||||
|
if (countryName === this.state.selectedCountry) {
|
||||||
|
this.setState({ selectedCountry: "" });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.setState({ selectedCountry: countryName });
|
||||||
|
};
|
||||||
|
|
||||||
|
handleCountryChange = (e) => {
|
||||||
|
const countryName = e.target.value;
|
||||||
|
const { selectedCountry } = this.state;
|
||||||
|
if (countryName === selectedCountry) {
|
||||||
|
this.setState({ selectedCountry: "" });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.setState({ selectedCountry: countryName });
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {
|
||||||
|
africaCountries,
|
||||||
|
africaOutline,
|
||||||
|
pssmCountries,
|
||||||
|
pssmData,
|
||||||
|
loading,
|
||||||
|
error,
|
||||||
|
selectedCountry,
|
||||||
|
recsaCountries,
|
||||||
|
ecowasCountries,
|
||||||
|
zoomControl,
|
||||||
|
} = this.state;
|
||||||
|
if (loading) {
|
||||||
|
return <div>Loading...</div>;
|
||||||
|
}
|
||||||
|
if (error) {
|
||||||
|
return <div>Error: {error.message}</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card_ id="map" className="map-container">
|
||||||
|
<MapContainer
|
||||||
|
ref={this.mapRef}
|
||||||
|
center={this.state.center}
|
||||||
|
zoom={this.state.zoom}
|
||||||
|
zoomSnap={this.state.zoomSnap}
|
||||||
|
style={{ width: "100%", height: "100%" }}
|
||||||
|
scrollWheelZoom={this.state.scrollWheelZoom}
|
||||||
|
zoomControl={zoomControl}
|
||||||
|
>
|
||||||
|
{africaCountries && (
|
||||||
|
<>
|
||||||
|
<GeoJSON
|
||||||
|
ref={this.geoJsonLayerRef}
|
||||||
|
onEachFeature={this.onEachFeature}
|
||||||
|
id="africa-map"
|
||||||
|
style={(feature) => {
|
||||||
|
if (
|
||||||
|
pssmData.find(
|
||||||
|
(item) =>
|
||||||
|
item.country === feature.properties.id &&
|
||||||
|
item.recsa === true
|
||||||
|
) &&
|
||||||
|
pssmData.find(
|
||||||
|
(item) =>
|
||||||
|
item.country === feature.properties.id &&
|
||||||
|
item.ecowas === true
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return CountrySelectedStyle("red");
|
||||||
|
} else if (
|
||||||
|
pssmData.find(
|
||||||
|
(item) =>
|
||||||
|
item.country === feature.properties.id &&
|
||||||
|
item.recsa === true
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return CountrySelectedStyle("#a6cee3");
|
||||||
|
} else if (
|
||||||
|
pssmData.find(
|
||||||
|
(item) =>
|
||||||
|
item.country === feature.properties.id &&
|
||||||
|
item.ecowas === true
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return CountrySelectedStyle("#ff7f00");
|
||||||
|
} else {
|
||||||
|
return NotPSSMCountryStyle();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
key="africa-map"
|
||||||
|
data={africaCountries}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{africaOutline && (
|
||||||
|
<GeoJSON
|
||||||
|
onEachFeature={this.onEachFeature}
|
||||||
|
id="africa-outline"
|
||||||
|
data={africaOutline}
|
||||||
|
style={() => {
|
||||||
|
return {
|
||||||
|
color: "black",
|
||||||
|
weight: 3,
|
||||||
|
opacity: 1,
|
||||||
|
};
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{selectedCountry &&
|
||||||
|
pssmCountries.map((feature) => {
|
||||||
|
if (feature.properties.name === selectedCountry) {
|
||||||
|
const pssmCountryData = pssmData.find(
|
||||||
|
(item) => item.country === feature.properties.id
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<MarkerCustom
|
||||||
|
key={feature.properties.name}
|
||||||
|
feature={feature}
|
||||||
|
pssmCountryData={pssmCountryData}
|
||||||
|
></MarkerCustom>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})}
|
||||||
|
|
||||||
|
{/* <CustomZoomControl /> */}
|
||||||
|
<div className="custom-zoom-control">
|
||||||
|
<button onClick={this.zoomIn}>+</button>
|
||||||
|
<button onClick={this.zoomOut}>-</button>
|
||||||
|
<button onClick={this.resetMap}>*</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<SelectMenu
|
||||||
|
ecowasCountries={ecowasCountries}
|
||||||
|
recsaCountries={recsaCountries}
|
||||||
|
selectedCountry={selectedCountry}
|
||||||
|
handleCountryChange={this.handleCountryChange}
|
||||||
|
></SelectMenu>
|
||||||
|
|
||||||
|
<Legend />
|
||||||
|
</MapContainer>
|
||||||
|
</Card_>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PSSM;
|
10
salw_client/src/Components/Layout/PSSM/PssmResources.jsx
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import Card_ from '../../UI/Card_/Card_';
|
||||||
|
const PssmResources = (props) => {
|
||||||
|
const {className} = props;
|
||||||
|
return (
|
||||||
|
<Card_ className={className}>PSSM Resources</Card_>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PssmResources
|
37
salw_client/src/Components/Layout/PSSM/SelectMenu.jsx
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import React from "react";
|
||||||
|
|
||||||
|
const SelectMenu = (props) => {
|
||||||
|
const {
|
||||||
|
ecowasCountries,
|
||||||
|
recsaCountries,
|
||||||
|
selectedCountry,
|
||||||
|
handleCountryChange,
|
||||||
|
} = props;
|
||||||
|
return (
|
||||||
|
<div className="country-select">
|
||||||
|
<select onChange={handleCountryChange} value={selectedCountry}>
|
||||||
|
<option value="">Select a country</option>
|
||||||
|
<option className="options-title-recsa" value="" disabled>
|
||||||
|
RECSA
|
||||||
|
</option>
|
||||||
|
{recsaCountries.map((feature, index) => (
|
||||||
|
<option className="" key={feature.properties.name} value={feature.properties.name}>
|
||||||
|
{feature.properties.name}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
|
||||||
|
<option className="options-title-ecowas" value="" disabled>
|
||||||
|
ECOWAS
|
||||||
|
</option>
|
||||||
|
|
||||||
|
{ecowasCountries.map((feature, index) => (
|
||||||
|
<option className="" key={feature.properties.name} value={feature.properties.name}>
|
||||||
|
{feature.properties.name}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SelectMenu;
|
36
salw_client/src/Components/Layout/PSSM/countryStyles.js
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
export const CountryStyle = () => {
|
||||||
|
return {
|
||||||
|
color: "black",
|
||||||
|
weight: 1,
|
||||||
|
opacity: 1,
|
||||||
|
fillColor: "#FDEDE2",
|
||||||
|
fillOpacity: 0.3,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const CountrySelectedStyle = (color) => {
|
||||||
|
return {
|
||||||
|
fillColor: color,
|
||||||
|
color: "black",
|
||||||
|
weight: 2,
|
||||||
|
opacity: 1,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const CountryHighlightStyle = () => {
|
||||||
|
return {
|
||||||
|
fillColor: "yellow",
|
||||||
|
color: "black",
|
||||||
|
weight: 3,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const NotPSSMCountryStyle = () => {
|
||||||
|
return {
|
||||||
|
fillColor: "#cccccc",
|
||||||
|
color: "#e3e3e3",
|
||||||
|
weight: 1,
|
||||||
|
opacity: 1,
|
||||||
|
fillOpacity: 0,
|
||||||
|
};
|
||||||
|
};
|
47
salw_client/src/Components/Layout/SwiperSalw/SwiperSalw.js
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import React from "react";
|
||||||
|
import Container from "react-bootstrap/esm/Container";
|
||||||
|
// Import Swiper React components
|
||||||
|
import { Swiper, SwiperSlide } from "swiper/react";
|
||||||
|
// Import Swiper styles
|
||||||
|
// Import Swiper styles
|
||||||
|
import "swiper/css";
|
||||||
|
import 'swiper/css/effect-fade';
|
||||||
|
import "swiper/css/navigation";
|
||||||
|
import "swiper/css/pagination";
|
||||||
|
import "swiper/css/scrollbar";
|
||||||
|
import classes from "./SwiperSalw.module.css";
|
||||||
|
// import required modules
|
||||||
|
import { EffectFade,Navigation, Pagination, Autoplay } from 'swiper/modules';
|
||||||
|
|
||||||
|
import weapon1 from "../../../img/weapon1.png"
|
||||||
|
import weapon2 from "../../../img/weapon2.png"
|
||||||
|
import weapon3 from "../../../img/weapon3.png"
|
||||||
|
import weapon4 from "../../../img/weapon4.png"
|
||||||
|
import weapon5 from "../../../img/weapon5.png"
|
||||||
|
|
||||||
|
const SwiperSalw = () => {
|
||||||
|
return (
|
||||||
|
<Container className="mt-5">
|
||||||
|
<Swiper
|
||||||
|
loop={true}
|
||||||
|
effect={'fade'}
|
||||||
|
autoplay={{
|
||||||
|
delay: 2500,
|
||||||
|
disableOnInteraction: false,
|
||||||
|
}}
|
||||||
|
navigation={true}
|
||||||
|
modules={[Autoplay, Navigation]}
|
||||||
|
className={`${classes.swiper}`}
|
||||||
|
>
|
||||||
|
<SwiperSlide className={classes['swiper-slide']}><img src={weapon1} alt="" /></SwiperSlide>
|
||||||
|
<SwiperSlide className={classes['swiper-slide']}><img src={weapon2} alt="" /></SwiperSlide>
|
||||||
|
<SwiperSlide className={classes['swiper-slide']}><img src={weapon3} alt="" /></SwiperSlide>
|
||||||
|
<SwiperSlide className={classes['swiper-slide']}><img src={weapon4} alt="" /></SwiperSlide>
|
||||||
|
<SwiperSlide className={classes['swiper-slide']}><img src={weapon5} alt="" /></SwiperSlide>
|
||||||
|
|
||||||
|
</Swiper>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SwiperSalw;
|
@ -0,0 +1,17 @@
|
|||||||
|
.swiper {
|
||||||
|
width: 70%;
|
||||||
|
height: 70%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
border: solid 1px #ccc;
|
||||||
|
border-radius: 15px;
|
||||||
|
background-color: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.swiper-slide img {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
import React from "react";
|
||||||
|
|
||||||
|
import Container from "react-bootstrap/esm/Container";
|
||||||
|
import Stack from "react-bootstrap/Stack";
|
||||||
|
import Card_ from "../../UI/Card_/Card_";
|
||||||
|
import Button from "react-bootstrap/esm/Button";
|
||||||
|
|
||||||
|
|
||||||
|
import weapon1 from "../../../img/weapon1.png";
|
||||||
|
import weapon2 from "../../../img/weapon2.png";
|
||||||
|
|
||||||
|
const WeaponAmmuBut = () => {
|
||||||
|
return (
|
||||||
|
<Container className="mt-5">
|
||||||
|
<Stack direction="horizontal" gap={3} className="w-75 text-center m-auto">
|
||||||
|
<div
|
||||||
|
role="button"
|
||||||
|
className="w-100 text-center border rounded-end rounded-4 p-3"
|
||||||
|
>
|
||||||
|
<strong>Weapons</strong>
|
||||||
|
<p>
|
||||||
|
Do you know which SALW are commonly found around the world? Enter
|
||||||
|
here for an overview of some widely spread SALW including photos,
|
||||||
|
technical specifications, markings, distribution maps, and short
|
||||||
|
descriptions.
|
||||||
|
</p>
|
||||||
|
<img src={weapon1} alt="" srcset="" />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
role="button"
|
||||||
|
className="w-100 text-center border rounded-start rounded-4 p-3"
|
||||||
|
>
|
||||||
|
<strong>Ammunition</strong>
|
||||||
|
<p>
|
||||||
|
Do you know which SALW are commonly found around the world? Enter
|
||||||
|
here for an overview of some widely spread SALW including photos,
|
||||||
|
technical specifications, markings, distribution maps, and short
|
||||||
|
descriptions.
|
||||||
|
</p>
|
||||||
|
<img src={weapon2} alt="" srcset="" />
|
||||||
|
</div>
|
||||||
|
</Stack>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default WeaponAmmuBut;
|
12
salw_client/src/Components/Pages/About.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
const About = () => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h1>About Us</h1>
|
||||||
|
<p>This is the about page content.</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default About;
|
27
salw_client/src/Components/Pages/ControlInAfrica.js
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
import Container from "react-bootstrap/Container";
|
||||||
|
import ControlInAfricaMap from "../Layout/ControlInAfrica/ControlInAfricaMap";
|
||||||
|
import Title from "../Layout/ControlInAfrica/Title";
|
||||||
|
import DetailsSection from "../Layout/ControlInAfrica/DetailsSection";
|
||||||
|
|
||||||
|
const ControlInAfrica = (props) => {
|
||||||
|
const [countryID, setCountryID] = useState(null);
|
||||||
|
|
||||||
|
const updateCountryID = (countryID) => {
|
||||||
|
setCountryID(countryID);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container fluid className="p-5">
|
||||||
|
<Title></Title>
|
||||||
|
<ControlInAfricaMap
|
||||||
|
updateCountryID={updateCountryID}
|
||||||
|
></ControlInAfricaMap>
|
||||||
|
{countryID !== null && (
|
||||||
|
<DetailsSection countryID={countryID}></DetailsSection>
|
||||||
|
)}
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ControlInAfrica;
|
12
salw_client/src/Components/Pages/Home.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
const Home = () => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h1>Welcome to the Home Page!</h1>
|
||||||
|
<p>This is the home page content.</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Home;
|
33
salw_client/src/Components/Pages/PSSM.js
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import React from "react";
|
||||||
|
import Container from "react-bootstrap/Container";
|
||||||
|
import Row from "react-bootstrap/Row";
|
||||||
|
import Col from "react-bootstrap/Col";
|
||||||
|
import Blurb from "../Layout/PSSM/Blurb";
|
||||||
|
import PSSM from "../Layout/PSSM/PSSM";
|
||||||
|
import ImageGallery from "../Layout/PSSM/ImageGallery";
|
||||||
|
import ImpactStories from "../Layout/PSSM/ImpactStories";
|
||||||
|
import PssmResources from "../Layout/PSSM/PssmResources";
|
||||||
|
const Treaties = () => {
|
||||||
|
return (
|
||||||
|
<Container fluid className="p-5">
|
||||||
|
<Row>
|
||||||
|
<Col sm={7}>
|
||||||
|
<Blurb></Blurb>
|
||||||
|
</Col>
|
||||||
|
<Col sm={5}>
|
||||||
|
<PSSM></PSSM>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Col sm={6}><ImpactStories className="mt-3 p-3"></ImpactStories></Col>
|
||||||
|
<Col sm={6}><PssmResources className="mt-3 p-3"></PssmResources></Col>
|
||||||
|
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<ImageGallery className="mt-3"></ImageGallery>
|
||||||
|
</Row>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Treaties;
|
11
salw_client/src/Components/UI/Button_/Button_.js
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
import classes from './Button_.module.css'
|
||||||
|
|
||||||
|
const Button_ = props => {
|
||||||
|
return (
|
||||||
|
<button className={`${classes.card} ${props.className}`}>{props.children}</button>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Button_
|
10
salw_client/src/Components/UI/Card_/Card_.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import React from "react";
|
||||||
|
|
||||||
|
|
||||||
|
const Card_ = props => {
|
||||||
|
return (
|
||||||
|
<div className={`card ${props.className} `}>{props.children}</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Card_;
|
5
salw_client/src/Components/UI/Card_/Card_.module.css
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
.card{
|
||||||
|
/* background-color: antiquewhite; */
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.26);
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
25
salw_client/src/Context/DataContext.js
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import React, { createContext, useContext } from 'react';
|
||||||
|
import { useQuery } from 'react-query';
|
||||||
|
import Africa from "../Data/ControlinAfrica.geojson";
|
||||||
|
|
||||||
|
const DataContext = createContext();
|
||||||
|
|
||||||
|
export const DataProvider = ({ children }) => {
|
||||||
|
const fetchData = async () => {
|
||||||
|
const response = await fetch(Africa);
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error('Network response was not ok');
|
||||||
|
}
|
||||||
|
return response.json();
|
||||||
|
};
|
||||||
|
|
||||||
|
const { data, error, isLoading } = useQuery('dataKey', fetchData);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DataContext.Provider value={{ data, error, isLoading }}>
|
||||||
|
{children}
|
||||||
|
</DataContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useAfricaData = () => useContext(DataContext);
|
8
salw_client/src/Data/Africa_outline.geojson
Normal file
16671
salw_client/src/Data/ControlinAfrica.geojson
Normal file
132
salw_client/src/Data/Orgs.geojson
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
{
|
||||||
|
"regional_organisations": [
|
||||||
|
{ "name": "AU", "color": "#b2df8a" },
|
||||||
|
{ "name": "EAC", "color": "#33a02c" },
|
||||||
|
{ "name": "IGAD", "color": "#fb9a99" },
|
||||||
|
{ "name": "UMA", "color": "#e31a1c" },
|
||||||
|
{ "name": "COMESA", "color": "#fdbf6f" },
|
||||||
|
{ "name": "ECOWAS", "color": "#ff7f00" },
|
||||||
|
{ "name": "CEN-SAD", "color": "#cab2d6" },
|
||||||
|
{ "name": "SADC", "color": "#6a3d9a" },
|
||||||
|
{ "name": "ECCAS", "color": "#ffff99" },
|
||||||
|
{ "name": "ICGLR", "color": "#b15928" },
|
||||||
|
{ "name": "RECSA", "color": "#a6cee3" },
|
||||||
|
{ "name": "SARCOM", "color": "#1f78b4" }
|
||||||
|
],
|
||||||
|
|
||||||
|
"geographical_regions": [
|
||||||
|
{ "name": "Northern-Africa", "color": "#e3e3e3" },
|
||||||
|
{ "name": "Eastern-Africa", "color": "#e3e3e3" },
|
||||||
|
{ "name": "Southern-Africa", "color": "#e3e3e3" },
|
||||||
|
{ "name": "Western-Africa", "color": "#e3e3e3" },
|
||||||
|
{ "name": "Central-Africa", "color": "#e3e3e3" }
|
||||||
|
],
|
||||||
|
|
||||||
|
"regional_treaties": [
|
||||||
|
{
|
||||||
|
"name": "Bamako Declaration",
|
||||||
|
"name2": "BamakoDeclaration",
|
||||||
|
"icon_eligible": "Icon26",
|
||||||
|
"icon_signed": "Icon24",
|
||||||
|
"icon_ratified": "none"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Kinshasa Convention",
|
||||||
|
"name2": "KinshasaConvention",
|
||||||
|
"icon_eligible": "Icon4",
|
||||||
|
"icon_signed": "Icon6",
|
||||||
|
"icon_ratified": "Icon5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ECOWAS Convention",
|
||||||
|
"name2": "ECOWASConvention",
|
||||||
|
"icon_eligible": "Icon2",
|
||||||
|
"icon_signed": "Icon3",
|
||||||
|
"icon_ratified": "none"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Khartoum Declaration",
|
||||||
|
"name2": "KhartoumDeclaration",
|
||||||
|
"icon_eligible": "Icon21",
|
||||||
|
"icon_signed": "Icon23",
|
||||||
|
"icon_ratified": "none"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Nairobi Protocol",
|
||||||
|
"name2": "NairobiProtocol",
|
||||||
|
"icon_eligible": "Icon22",
|
||||||
|
"icon_signed": "Icon25",
|
||||||
|
"icon_ratified": "none"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "SADC Firearms Protocol",
|
||||||
|
"name2": "SADCFirearmsProtocol",
|
||||||
|
"icon_eligible": "Icon8",
|
||||||
|
"icon_signed": "Icon7",
|
||||||
|
"icon_ratified": "Icon9"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
"international_treaties": [
|
||||||
|
{
|
||||||
|
"name": "Arms Trade Treaty",
|
||||||
|
"name2": "ArmsTradeTreaty",
|
||||||
|
"icon_eligible": "Icon19",
|
||||||
|
"icon_signed": "Icon17",
|
||||||
|
"icon_ratified": "Icon18"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Firearms Protocol",
|
||||||
|
"name2": "FirearmsProtocol",
|
||||||
|
"icon_eligible": "Icon12",
|
||||||
|
"icon_signed": "Icon10",
|
||||||
|
"icon_ratified": "Icon11"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Wassenaar Agreement",
|
||||||
|
"name2": "WassenaarAgreement",
|
||||||
|
"icon_eligible": "Icon15",
|
||||||
|
"icon_signed": "Icon13",
|
||||||
|
"icon_ratified": "Icon14"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
"internationalIntsruments": [
|
||||||
|
{
|
||||||
|
"name2": "UNProgrammeofAction",
|
||||||
|
"name": "UN Programme of Action",
|
||||||
|
"icon": "Icon20"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name2": "InternationalTracingInstrument",
|
||||||
|
"name": "International Tracing Instrument",
|
||||||
|
"icon": "Icon16"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
"africanIntsruments": [
|
||||||
|
{
|
||||||
|
"name2": "StG-PoA",
|
||||||
|
"name": "Silencing the Guns in Africa Programme of Action",
|
||||||
|
"icon": "Icon1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
"intsruments": [
|
||||||
|
{
|
||||||
|
"name2": "UNProgrammeofAction",
|
||||||
|
"name": "UN Programme of Action",
|
||||||
|
"icon": "Icon20"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name2": "InternationalTracingInstrument",
|
||||||
|
"name": "International Tracing Instrument",
|
||||||
|
"icon": "Icon16"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name2": "StG-PoA",
|
||||||
|
"name": "Silencing the Guns in Africa Programme of Action",
|
||||||
|
"icon": "Icon1"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
16781
salw_client/src/Data/PSSM.geojson
Normal file
17
salw_client/src/Data/Photos.geojson
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"PSSM_PHOTOS": [
|
||||||
|
{"image":"Bild1_Nikhil.jpg","copy_right":"©Nikhil Acharya"},
|
||||||
|
{"image":"Bild2_Nikhil.jpg","copy_right":"©Nikhil Acharya"},
|
||||||
|
{"image":"Storekeeper and Policewoman.jpg","copy_right":"©Nikhil Acharya"},
|
||||||
|
{"image":"Opening 2.jpg","copy_right":"©IPSTC/Kenya"},
|
||||||
|
{"image":"Group of Senior Instructors and Instructors.jpg","copy_right":"©MSAG AUT"},
|
||||||
|
{"image":"Image 1.jpg","copy_right":"©MSAG AUT"},
|
||||||
|
{"image":"bild.jpg","copy_right":""},
|
||||||
|
{"image":"1000013063.jpg","copy_right":"©Hans Lampalzer (BLMV)"},
|
||||||
|
{"image":"1000013066.jpg","copy_right":"©Hans Lampalzer (BLMV)"},
|
||||||
|
{"image":"1000013069.jpg","copy_right":"©Hans Lampalzer (BLMV)"},
|
||||||
|
{"image":"1000013072.jpg","copy_right":"©Hans Lampalzer (BLMV)"},
|
||||||
|
{"image":"1000013075.jpg","copy_right":"©Hans Lampalzer (BLMV)"},
|
||||||
|
{"image":"1000013078.jpg","copy_right":"©Hans Lampalzer (BLMV)"}
|
||||||
|
]
|
||||||
|
}
|
218
salw_client/src/Data/pssm_data.geojson
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id":18,
|
||||||
|
"ECOWAS":0.0,
|
||||||
|
"RECSA":1.0,
|
||||||
|
"Trained-Participants":31,
|
||||||
|
"PSSM-Instructors":2,
|
||||||
|
"PSSM-Senior-Instructors":3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":20,
|
||||||
|
"ECOWAS":1.0,
|
||||||
|
"RECSA":0.0,
|
||||||
|
"Trained-Participants":0,
|
||||||
|
"PSSM-Instructors":0,
|
||||||
|
"PSSM-Senior-Instructors":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":39,
|
||||||
|
"ECOWAS":0.0,
|
||||||
|
"RECSA":1.0,
|
||||||
|
"Trained-Participants":5,
|
||||||
|
"PSSM-Instructors":0,
|
||||||
|
"PSSM-Senior-Instructors":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":45,
|
||||||
|
"ECOWAS":1.0,
|
||||||
|
"RECSA":0.0,
|
||||||
|
"Trained-Participants":0,
|
||||||
|
"PSSM-Instructors":0,
|
||||||
|
"PSSM-Senior-Instructors":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":47,
|
||||||
|
"ECOWAS":0.0,
|
||||||
|
"RECSA":1.0,
|
||||||
|
"Trained-Participants":2,
|
||||||
|
"PSSM-Instructors":0,
|
||||||
|
"PSSM-Senior-Instructors":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":48,
|
||||||
|
"ECOWAS":0.0,
|
||||||
|
"RECSA":1.0,
|
||||||
|
"Trained-Participants":0,
|
||||||
|
"PSSM-Instructors":0,
|
||||||
|
"PSSM-Senior-Instructors":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":52,
|
||||||
|
"ECOWAS":1.0,
|
||||||
|
"RECSA":0.0,
|
||||||
|
"Trained-Participants":0,
|
||||||
|
"PSSM-Instructors":0,
|
||||||
|
"PSSM-Senior-Instructors":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":61,
|
||||||
|
"ECOWAS":0.0,
|
||||||
|
"RECSA":1.0,
|
||||||
|
"Trained-Participants":0,
|
||||||
|
"PSSM-Instructors":0,
|
||||||
|
"PSSM-Senior-Instructors":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":68,
|
||||||
|
"ECOWAS":0.0,
|
||||||
|
"RECSA":1.0,
|
||||||
|
"Trained-Participants":8,
|
||||||
|
"PSSM-Instructors":0,
|
||||||
|
"PSSM-Senior-Instructors":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":72,
|
||||||
|
"ECOWAS":0.0,
|
||||||
|
"RECSA":1.0,
|
||||||
|
"Trained-Participants":15,
|
||||||
|
"PSSM-Instructors":2,
|
||||||
|
"PSSM-Senior-Instructors":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":83,
|
||||||
|
"ECOWAS":1.0,
|
||||||
|
"RECSA":0.0,
|
||||||
|
"Trained-Participants":0,
|
||||||
|
"PSSM-Instructors":0,
|
||||||
|
"PSSM-Senior-Instructors":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":85,
|
||||||
|
"ECOWAS":1.0,
|
||||||
|
"RECSA":0.0,
|
||||||
|
"Trained-Participants":0,
|
||||||
|
"PSSM-Instructors":0,
|
||||||
|
"PSSM-Senior-Instructors":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":87,
|
||||||
|
"ECOWAS":1.0,
|
||||||
|
"RECSA":0.0,
|
||||||
|
"Trained-Participants":0,
|
||||||
|
"PSSM-Instructors":0,
|
||||||
|
"PSSM-Senior-Instructors":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":88,
|
||||||
|
"ECOWAS":1.0,
|
||||||
|
"RECSA":0.0,
|
||||||
|
"Trained-Participants":0,
|
||||||
|
"PSSM-Instructors":0,
|
||||||
|
"PSSM-Senior-Instructors":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":118,
|
||||||
|
"ECOWAS":0.0,
|
||||||
|
"RECSA":1.0,
|
||||||
|
"Trained-Participants":138,
|
||||||
|
"PSSM-Instructors":15,
|
||||||
|
"PSSM-Senior-Instructors":4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":127,
|
||||||
|
"ECOWAS":1.0,
|
||||||
|
"RECSA":0.0,
|
||||||
|
"Trained-Participants":0,
|
||||||
|
"PSSM-Instructors":0,
|
||||||
|
"PSSM-Senior-Instructors":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":164,
|
||||||
|
"ECOWAS":1.0,
|
||||||
|
"RECSA":0.0,
|
||||||
|
"Trained-Participants":1,
|
||||||
|
"PSSM-Instructors":0,
|
||||||
|
"PSSM-Senior-Instructors":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":191,
|
||||||
|
"ECOWAS":0.0,
|
||||||
|
"RECSA":1.0,
|
||||||
|
"Trained-Participants":0,
|
||||||
|
"PSSM-Instructors":2,
|
||||||
|
"PSSM-Senior-Instructors":2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":193,
|
||||||
|
"ECOWAS":0.0,
|
||||||
|
"RECSA":1.0,
|
||||||
|
"Trained-Participants":29,
|
||||||
|
"PSSM-Instructors":2,
|
||||||
|
"PSSM-Senior-Instructors":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":194,
|
||||||
|
"ECOWAS":1.0,
|
||||||
|
"RECSA":0.0,
|
||||||
|
"Trained-Participants":0,
|
||||||
|
"PSSM-Instructors":0,
|
||||||
|
"PSSM-Senior-Instructors":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":200,
|
||||||
|
"ECOWAS":1.0,
|
||||||
|
"RECSA":0.0,
|
||||||
|
"Trained-Participants":0,
|
||||||
|
"PSSM-Instructors":0,
|
||||||
|
"PSSM-Senior-Instructors":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":203,
|
||||||
|
"ECOWAS":0.0,
|
||||||
|
"RECSA":1.0,
|
||||||
|
"Trained-Participants":10,
|
||||||
|
"PSSM-Instructors":0,
|
||||||
|
"PSSM-Senior-Instructors":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":206,
|
||||||
|
"ECOWAS":0.0,
|
||||||
|
"RECSA":1.0,
|
||||||
|
"Trained-Participants":53,
|
||||||
|
"PSSM-Instructors":4,
|
||||||
|
"PSSM-Senior-Instructors":1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":214,
|
||||||
|
"ECOWAS":0.0,
|
||||||
|
"RECSA":1.0,
|
||||||
|
"Trained-Participants":12,
|
||||||
|
"PSSM-Instructors":4,
|
||||||
|
"PSSM-Senior-Instructors":1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":218,
|
||||||
|
"ECOWAS":1.0,
|
||||||
|
"RECSA":0.0,
|
||||||
|
"Trained-Participants":0,
|
||||||
|
"PSSM-Instructors":0,
|
||||||
|
"PSSM-Senior-Instructors":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":230,
|
||||||
|
"ECOWAS":0.0,
|
||||||
|
"RECSA":1.0,
|
||||||
|
"Trained-Participants":24,
|
||||||
|
"PSSM-Instructors":5,
|
||||||
|
"PSSM-Senior-Instructors":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":231,
|
||||||
|
"ECOWAS":0.0,
|
||||||
|
"RECSA":1.0,
|
||||||
|
"Trained-Participants":63,
|
||||||
|
"PSSM-Instructors":6,
|
||||||
|
"PSSM-Senior-Instructors":2
|
||||||
|
}
|
||||||
|
]
|
1
salw_client/src/Icons/icon1.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 29.36 29.36"><defs><style>.cls-1{fill:none;stroke:#000;stroke-miterlimit:10;}</style></defs><title>Element 5</title><g id="Ebene_2" data-name="Ebene 2"><g id="Ebene_1-2" data-name="Ebene 1"><path class="cls-1" d="M4.65,4.65A14.18,14.18,0,0,1,24.71,24.71,14.18,14.18,0,0,1,4.65,4.65Z"/><line class="cls-1" x1="4.65" y1="4.65" x2="8.29" y2="8.29"/><line class="cls-1" x1="15.81" y1="15.81" x2="24.71" y2="24.71"/><path d="M14.24,13.61v.55a.75.75,0,0,1-.75.71l-1.8.06a.8.8,0,0,1-.77-.76A1.07,1.07,0,0,1,11,13.6a.19.19,0,0,1,.08.13v0a.1.1,0,0,0-.05.08.08.08,0,0,0,.07.08,1.25,1.25,0,0,0,.65,1c.05,0,.08,0,.05-.09v0h.09c.11,0,.06-.17.06-.17l-.27-.82a1.32,1.32,0,0,1,.29-.7l1.57-.17a.71.71,0,0,1,.71.71Zm6.17-4-.28-.32H20l-.18.32c-2.65,0-10.87,0-13.84,0l-.15-.37H5.59l-.17.37H4.93a.23.23,0,0,0-.25.17v1.4l0,.08,0,.4,0,.05s-.14,0-.14.28a.2.2,0,0,0,.17.21,3.2,3.2,0,0,1,.62.14c.58.17.68.78.53,1.67a4.91,4.91,0,0,1-.59,1.58c.05,0,.08,0,.08.05s-.06.07-.14.07l0,.07s.08,0,.08.06-.06.06-.14.06l0,.08s.08,0,.08.06-.07.06-.14.06L5,16.21s.07,0,.07.05-.06.06-.14.06l-.05.09s.06,0,.06.05,0,.06-.13.06l-.06.11s.06,0,.06.05-.06.06-.13.06l-.05.08s0,0,0,.05,0,0-.09.05L4.47,17s0,0,0,0,0,0-.09.05l-.06.12s0,0,0,0,0,0-.08,0l-.06.12s0,0,0,0,0,0-.07.05l-.07.12,0,0s0,0-.07.05L4,17.86s0,0,0,0,0,0,0,0L4,18.05l0,0s0,0-.05,0l-.06.16a0,0,0,0,0,0,0s0,0,0,0,0,.09-.05.13l0,0s0,0,0,0,0,.1,0,.14,0,0,0,0,0,0-.05,0l0,.13s0,0,0,0,0,0,0,0a1.13,1.13,0,0,1,0,.12l0,0,0,.08,0,.14a1.06,1.06,0,0,0,.07.64,1.37,1.37,0,0,0,.64.48h.53v0a.8.8,0,0,0-.25.45c0,.23.38.23.38.23s2.1,0,2.69,0,.54-.38.54-.38l0-.38a2.44,2.44,0,0,0,.34-.21.54.54,0,0,0,.14-.38,3.87,3.87,0,0,0,0-.45A4.55,4.55,0,0,1,9,18.53a.73.73,0,0,1,.4-.42c.1-.06.08-.13.08-.13a.67.67,0,0,1,0-.73.91.91,0,0,1,.41-.51c.21-.1.15-.18.15-.18s-.23-.27.08-.95c.19-.4.41-.52.64-.54a1.61,1.61,0,0,1,.67.23,3.6,3.6,0,0,0,.8.06l2.61-.11.08-.13,0-.15a1.88,1.88,0,0,1-.16-.89,2.46,2.46,0,0,1,.1-.88c.11-.22.55-.39.55-.39s4.34-.15,4.8-.18.47-.3.47-.3.09-.48.1-.63,0-.13,0-.13l0-.06,0,0,.09,0v-.37l0,0,0-.1a3.38,3.38,0,0,0,.07-.48A1.05,1.05,0,0,0,20.9,10a.63.63,0,0,1,0-.11c0-.06-.05,0-.05-.1a.16.16,0,0,0-.15-.16Z"/><path d="M22.94,9a.77.77,0,0,0-1.14-.18l-.06,0a.73.73,0,0,0-.16.89,2.46,2.46,0,0,1,0,2.46.73.73,0,0,0,.16.89l.06,0a.74.74,0,0,0,1.14-.18,4.12,4.12,0,0,0,.52-2A4.19,4.19,0,0,0,22.94,9Z"/><path d="M24.84,7.16A.75.75,0,0,0,23.74,7l0,0a.75.75,0,0,0-.11,1A5,5,0,0,1,24.5,11a5.14,5.14,0,0,1-.91,2.9.74.74,0,0,0,.11,1l0,0a.74.74,0,0,0,1.1-.13,6.57,6.57,0,0,0,0-7.57Z"/></g></g></svg>
|
After Width: | Height: | Size: 2.5 KiB |
1
salw_client/src/Icons/icon10.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 19.09 16.27"><defs><style>.cls-1{fill:none;stroke:#000;stroke-miterlimit:10;}</style></defs><title>Element 14</title><g id="Ebene_2" data-name="Ebene 2"><g id="Ebene_1-2" data-name="Ebene 1"><path class="cls-1" d="M.5.62H7.9V3.93H3.59v2.8H7.65V10H3.59v5.76H.5Z"/><path class="cls-1" d="M9.82.83A18.27,18.27,0,0,1,13.62.5a4.88,4.88,0,0,1,3.66,1.21,5.1,5.1,0,0,1,1.31,3.64,5.81,5.81,0,0,1-1.12,3.74,4.81,4.81,0,0,1-3.84,1.59c-.3,0-.56,0-.75,0v5.14H9.82Zm3.06,6.68a3,3,0,0,0,.7.06,1.9,1.9,0,0,0,2-2.12,1.66,1.66,0,0,0-1.75-1.89,3.38,3.38,0,0,0-.91.09Z"/></g></g></svg>
|
After Width: | Height: | Size: 618 B |
1
salw_client/src/Icons/icon11.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16.45 15.27"><title>Element 15</title><g id="Ebene_2" data-name="Ebene 2"><g id="Ebene_1-2" data-name="Ebene 1"><path d="M0,.12H6.67V2.39H2.11V6.57H6.35V8.83H2.11v6.44H0Z"/><path d="M8.71.31A14.79,14.79,0,0,1,11.93,0a4.34,4.34,0,0,1,3.4,1.24,5,5,0,0,1,1.12,3.35,5.49,5.49,0,0,1-1,3.43,4.39,4.39,0,0,1-3.64,1.64,3.87,3.87,0,0,1-1-.11v5.72H8.71ZM10.8,7.37a3,3,0,0,0,1,.13c1.57,0,2.53-1,2.53-2.81S13.47,2.13,12,2.13a4.47,4.47,0,0,0-1.22.13Z"/></g></g></svg>
|
After Width: | Height: | Size: 507 B |
1
salw_client/src/Icons/icon12.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 14.3 15.27"><title>Element 16</title><g id="Ebene_2" data-name="Ebene 2"><g id="Ebene_1-2" data-name="Ebene 1"><path d="M0,.12H5.7V1H.81V7H5.29v.9H.81v7.33H0Z"/><path d="M7.9.29A10.59,10.59,0,0,1,10.37,0a3.68,3.68,0,0,1,3,1.28,4.69,4.69,0,0,1,.89,3,5.19,5.19,0,0,1-.8,3A3.94,3.94,0,0,1,10.11,9a3.93,3.93,0,0,1-1.4-.18v6.48H7.9Zm.81,7.56a4.1,4.1,0,0,0,1.47.22c2.06,0,3.3-1.32,3.3-3.72S12.17.9,10.34.9a6.29,6.29,0,0,0-1.63.18Z"/></g></g></svg>
|
After Width: | Height: | Size: 494 B |
1
salw_client/src/Icons/icon13.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 29.24 16.42"><defs><style>.cls-1{fill:none;stroke:#000;stroke-miterlimit:10;}</style></defs><title>Element 17</title><g id="Ebene_2" data-name="Ebene 2"><g id="Ebene_1-2" data-name="Ebene 1"><path class="cls-1" d="M2.43,15.78.57.63H3.32L3.7,6.12c.12,1.66.18,3.42.32,5.26h0c.17-1.84.41-3.51.63-5.26L5.41.63H7.53l.63,5.49c.19,1.66.36,3.33.5,5.26h0c.12-1.89.24-3.51.36-5.26L9.44.63H12L10.09,15.78H7.32l-.49-3.91c-.18-1.32-.33-3-.48-5h0c-.22,1.89-.41,3.6-.63,5l-.62,3.91Z"/><path class="cls-1" d="M13.4,12.79l-.4,3H10.44L12.88.63H16.1l2.1,15.15H15.64l-.38-3Zm1.65-2.67-.29-2.88c-.08-.85-.24-2.49-.34-3.44h0c-.12,1-.29,2.63-.4,3.44l-.34,2.88Z"/><path class="cls-1" d="M17.42,12.32a3.73,3.73,0,0,0,2,.59,1.27,1.27,0,0,0,1.43-1.35c0-1-.47-1.37-1.48-2.16a5.16,5.16,0,0,1-2.18-4.25c0-2.49,1.24-4.65,3.9-4.65A3.46,3.46,0,0,1,23,1l-.37,3a2.41,2.41,0,0,0-1.51-.52,1.23,1.23,0,0,0-1.32,1.31c0,.65.24,1.07,1.54,2a5.13,5.13,0,0,1,2.12,4.32c0,2.85-1.62,4.74-4.05,4.74a4.43,4.43,0,0,1-2.33-.59Z"/><path class="cls-1" d="M22.7,12.32a3.78,3.78,0,0,0,2,.59,1.28,1.28,0,0,0,1.44-1.35c0-1-.48-1.37-1.49-2.16a5.18,5.18,0,0,1-2.17-4.25c0-2.49,1.23-4.65,3.9-4.65a3.46,3.46,0,0,1,1.9.54L27.9,4a2.38,2.38,0,0,0-1.5-.52,1.23,1.23,0,0,0-1.32,1.31c0,.65.24,1.07,1.54,2a5.13,5.13,0,0,1,2.12,4.32c0,2.85-1.62,4.74-4,4.74a4.4,4.4,0,0,1-2.33-.59Z"/></g></g></svg>
|
After Width: | Height: | Size: 1.3 KiB |
1
salw_client/src/Icons/icon14.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 25.76 15.42"><title>Element 18</title><g id="Ebene_2" data-name="Ebene 2"><g id="Ebene_1-2" data-name="Ebene 1"><path d="M2.08,15.28,0,.13H1.89l.75,6.61c.2,1.81.33,3.54.48,5.39h0c.15-1.89.41-3.54.66-5.41L4.77.13h1.5l.9,6.51c.23,1.74.45,3.44.6,5.49h.05c.16-2.07.33-3.71.51-5.45L9.07.13h1.79L8.73,15.28H6.87L6,9.24c-.21-1.5-.4-3.21-.54-5h0C5.24,6,5,7.7,4.79,9.28l-.94,6Z"/><path d="M11.59,11.34,11,15.28H9.2L11.76.13h2.13l2.39,15.15H14.49l-.61-3.94Zm2.1-1.88L13.21,6c-.14-1-.3-2.39-.42-3.45h0C12.61,3.6,12.44,5,12.3,6l-.5,3.47Z"/><path d="M15.66,12.72a3.15,3.15,0,0,0,1.78.61c1.13,0,1.74-.87,1.74-2.11a3.48,3.48,0,0,0-1.51-2.76A5.69,5.69,0,0,1,15.5,4.24C15.5,1.87,16.72,0,18.88,0A2.89,2.89,0,0,1,20.6.55l-.34,2.06a2.17,2.17,0,0,0-1.43-.52A1.65,1.65,0,0,0,17.3,3.93c0,1.17.46,1.71,1.64,2.7A5.47,5.47,0,0,1,21,11c0,2.71-1.49,4.44-3.55,4.44a3.6,3.6,0,0,1-2.09-.63Z"/><path d="M20.43,12.72a3.2,3.2,0,0,0,1.78.61c1.13,0,1.74-.87,1.74-2.11a3.45,3.45,0,0,0-1.51-2.76,5.69,5.69,0,0,1-2.17-4.22C20.27,1.87,21.5,0,23.65,0a2.89,2.89,0,0,1,1.72.55L25,2.61a2.16,2.16,0,0,0-1.42-.52,1.64,1.64,0,0,0-1.53,1.84c0,1.17.46,1.71,1.63,2.7A5.44,5.44,0,0,1,25.76,11c0,2.71-1.49,4.44-3.55,4.44a3.62,3.62,0,0,1-2.09-.63Z"/></g></g></svg>
|
After Width: | Height: | Size: 1.2 KiB |
1
salw_client/src/Icons/icon15.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 29.68 15.56"><title>Element 19</title><g id="Ebene_2" data-name="Ebene 2"><g id="Ebene_1-2" data-name="Ebene 1"><path d="M2.84,15.35,0,.21H.81L2.35,8.62c.36,2,.68,3.74.88,5.3h0c.17-1.58.54-3.33,1-5.33L5.92.21h.75L8.25,8.49c.34,1.84.69,3.69.88,5.43h0c.25-1.84.58-3.5.95-5.36L11.8.21h.81L9.48,15.35H8.74L7.11,6.59C6.72,4.52,6.45,3,6.3,1.51h0c-.17,1.47-.46,3-.91,5.1L3.57,15.35Z"/><path d="M12.67,10.08l-1.28,5.27h-.8L14.33.21h.76l3.74,15.14H18l-1.29-5.27Zm3.82-.88-1.2-4.82c-.26-1.09-.41-1.94-.58-2.91h-.05c-.15,1-.33,1.88-.56,2.88L12.89,9.2Z"/><path d="M18.5,13.77a3.43,3.43,0,0,0,2.21.89c1.6,0,2.59-1.27,2.59-3.14A3.81,3.81,0,0,0,21.2,8a4.59,4.59,0,0,1-2.73-4.18C18.47,1.58,19.81,0,21.63,0a3.15,3.15,0,0,1,2.05.67l-.31.88A2.76,2.76,0,0,0,21.55.89a2.42,2.42,0,0,0-2.29,2.69c0,1.74.74,2.54,2.2,3.45a4.78,4.78,0,0,1,2.63,4.4c0,2.29-1.23,4.13-3.42,4.13a3.85,3.85,0,0,1-2.47-.92Z"/><path d="M24.09,13.77a3.46,3.46,0,0,0,2.21.89c1.6,0,2.59-1.27,2.59-3.14A3.79,3.79,0,0,0,26.79,8a4.6,4.6,0,0,1-2.72-4.18C24.07,1.58,25.41,0,27.22,0a3.15,3.15,0,0,1,2.05.67L29,1.55A2.76,2.76,0,0,0,27.14.89a2.42,2.42,0,0,0-2.29,2.69c0,1.74.75,2.54,2.21,3.45a4.77,4.77,0,0,1,2.62,4.4c0,2.29-1.23,4.13-3.42,4.13a3.81,3.81,0,0,1-2.46-.92Z"/></g></g></svg>
|
After Width: | Height: | Size: 1.2 KiB |
1
salw_client/src/Icons/icon16.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 18.05 15.15"><title>Element 20</title><g id="Ebene_2" data-name="Ebene 2"><g id="Ebene_1-2" data-name="Ebene 1"><path d="M3.09,0V15.15H0V0Z"/><path d="M7.45,3.41H4.52V0h9V3.41h-3V15.15H7.45Z"/><path d="M18.05,0V15.15H15V0Z"/></g></g></svg>
|
After Width: | Height: | Size: 292 B |
1
salw_client/src/Icons/icon17.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26.93 16.15"><defs><style>.cls-1{fill:none;stroke:#000;stroke-miterlimit:10;}</style></defs><title>Element 21</title><g id="Ebene_2" data-name="Ebene 2"><g id="Ebene_1-2" data-name="Ebene 1"><path class="cls-1" d="M4.47,12.14l-.65,3.51H.62L4,.5H8.08l3.44,15.15H8.18l-.73-3.51ZM7,9.14,6.49,6.42c-.18-.86-.39-2.09-.57-3h0c-.17.9-.34,2.14-.51,3L4.88,9.14Z"/><path class="cls-1" d="M12.05,3.91H9.11V.5h9V3.91h-3V15.65H12.05Z"/><path class="cls-1" d="M20.34,3.91H17.41V.5h9V3.91h-3V15.65H20.34Z"/></g></g></svg>
|
After Width: | Height: | Size: 559 B |
1
salw_client/src/Icons/icon18.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24.04 15.15"><title>Element 22</title><g id="Ebene_2" data-name="Ebene 2"><g id="Ebene_1-2" data-name="Ebene 1"><path d="M3.16,10.87l-1,4.28H0L3.7,0H6.38l3.75,15.15H7.87l-1-4.28ZM6.48,8.78,5.57,5c-.22-.94-.42-2-.59-2.84h0C4.78,3.08,4.6,4.13,4.4,5L3.5,8.78Z"/><path d="M10.85,2.33H7.55V0h8.73V2.33H13V15.15h-2.1Z"/><path d="M18.61,2.33H15.32V0H24V2.33H20.72V15.15H18.61Z"/></g></g></svg>
|
After Width: | Height: | Size: 439 B |
1
salw_client/src/Icons/icon19.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 21.73 15.15"><title>Element 23</title><g id="Ebene_2" data-name="Ebene 2"><g id="Ebene_1-2" data-name="Ebene 1"><path d="M2.26,9.85.83,15.15H0L4.17,0H5L9.11,15.15H8.27L6.82,9.85ZM6.57,9,5.17,3.89c-.28-1.05-.44-1.81-.6-2.67H4.52c-.16.88-.34,1.67-.59,2.62L2.51,9Z"/><path d="M10.11.9H6.35V0h8.33V.9H10.93V15.15h-.82Z"/><path d="M17.16.9H13.4V0h8.33V.9H18V15.15h-.81Z"/></g></g></svg>
|
After Width: | Height: | Size: 434 B |
1
salw_client/src/Icons/icon2.svg
Normal file
After Width: | Height: | Size: 13 KiB |
1
salw_client/src/Icons/icon20.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 33.76 15.4"><title>Element 24</title><g id="Ebene_2" data-name="Ebene 2"><g id="Ebene_1-2" data-name="Ebene 1"><path d="M2.65.07V9.78c0,2,.41,2.58.89,2.58s.89-.45.89-2.58V.07H7.08V9.15C7.08,13,6,15.4,3.56,15.4.85,15.4,0,12.9,0,9.1v-9Z"/><path d="M7.23,15.22V.07H9.65l1.62,5.44c.29,1,.84,2.87,1.13,4h0c-.06-1.23-.25-4.18-.25-7V.07h2.31V15.22H12.08l-1.56-5.11C10.16,9,9.63,7,9.42,5.82h0c0,1.31.15,3.82.15,6.79v2.61Z"/><path d="M14.73.29A10.54,10.54,0,0,1,17.26,0a4,4,0,0,1,3.38,1.19,5.21,5.21,0,0,1,1.05,3.4,6.21,6.21,0,0,1-1.1,3.88,3.75,3.75,0,0,1-2.84,1.35h-.39v5.4H14.73ZM17.36,7a1.09,1.09,0,0,0,.31,0c1.06,0,1.4-1,1.4-2.14s-.38-2.11-1.23-2.11a1,1,0,0,0-.48.11Z"/><path d="M27.21,9.64c0,4.74-2.12,5.76-3.38,5.76-2.23,0-3.43-2.21-3.43-5.67C20.4,5.8,22.08,4,23.84,4,26,4,27.21,6.32,27.21,9.64ZM23,9.67c0,1.91.22,3.12.86,3.12s.72-1.55.72-3.12-.18-3.08-.76-3.08S23,8.2,23,9.67Z"/><path d="M29,12.23l-.4,3H26L28.44.07h3.22l2.1,15.15H31.2l-.38-3Zm1.66-2.68-.29-2.87c-.09-.86-.24-2.5-.35-3.44h0c-.12.94-.29,2.63-.39,3.44l-.35,2.87Z"/></g></g></svg>
|
After Width: | Height: | Size: 1.1 KiB |
1
salw_client/src/Icons/icon21.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 29.36 29.36"><defs><style>.cls-1{fill:none;stroke:#000;stroke-miterlimit:10;}</style></defs><title>Element 25</title><g id="Ebene_2" data-name="Ebene 2"><g id="Ebene_1-2" data-name="Ebene 1"><path d="M25.48,9.85h-2v-2a.55.55,0,0,0-.55-.55H20.86v-2a.55.55,0,0,0-.55-.55H6.45a.55.55,0,0,0-.55.55V20.47a.55.55,0,0,0,.55.55h2v2a.55.55,0,0,0,.55.55h2.05v2a.56.56,0,0,0,.55.56h9.15a.55.55,0,0,0,.37-.16l4.68-4.22a.51.51,0,0,0,.18-.43v-11A.51.51,0,0,0,25.48,9.85ZM7,5.78H19.76V17.41l-2.85,2.44H7ZM9.6,21h7.47a.75.75,0,0,0,.36-.13l3.22-2.75a.57.57,0,0,0,.18-.43V8.38H22.3V19.27l-3.58,3.18H9.6Zm15.3.15-4.31,3.91H12.2V23.59h6.73a.57.57,0,0,0,.37-.16L23.25,20a.58.58,0,0,0,.18-.43V11H24.9Z"/><path d="M9.39,9h8A.54.54,0,0,0,18,8.47a.55.55,0,0,0-.55-.55h-8a.55.55,0,0,0-.55.55A.52.52,0,0,0,9.39,9Z"/><path d="M9.39,11.69h8a.56.56,0,0,0,0-1.11h-8a.55.55,0,0,0-.55.56A.51.51,0,0,0,9.39,11.69Z"/><path d="M17.37,13.25H15.23a.55.55,0,0,0-.55.55.55.55,0,0,0,.55.55h2.14a.55.55,0,0,0,.55-.55A.52.52,0,0,0,17.37,13.25Z"/><path d="M17.37,15.91H15.23a.55.55,0,0,0-.55.55.55.55,0,0,0,.55.55h2.14a.55.55,0,0,0,.55-.55A.52.52,0,0,0,17.37,15.91Z"/><path d="M13.3,18.42a.56.56,0,0,0,.56-.55v-4a.55.55,0,0,0-.56-.55h-4a.54.54,0,0,0-.55.55v4a.55.55,0,0,0,.55.55Zm-3.45-4h2.87v2.9H9.85Z"/><path class="cls-1" d="M24.71,4.65A14.18,14.18,0,0,0,4.65,24.71,14.18,14.18,0,0,0,24.71,4.65Z"/></g></g></svg>
|
After Width: | Height: | Size: 1.4 KiB |
1
salw_client/src/Icons/icon22.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 29.36 29.36"><defs><style>.cls-1{fill:none;stroke:#000;stroke-miterlimit:10;}</style></defs><title>Element 26</title><g id="Ebene_2" data-name="Ebene 2"><g id="Ebene_1-2" data-name="Ebene 1"><path d="M21.3,23.19a2.18,2.18,0,0,1-1.51-.64.57.57,0,1,1,.8-.8h0a1.3,1.3,0,0,0,.47.27,1,1,0,0,0,1.15-1.14,1.24,1.24,0,0,0-.28-.48.57.57,0,1,1,.8-.8,2.12,2.12,0,0,1-1.43,3.59Z"/><path d="M18.08,24.26a2.22,2.22,0,0,1-1.52-.64.57.57,0,0,1,.8-.8h0a1.4,1.4,0,0,0,.48.28A1,1,0,0,0,19,22a1.4,1.4,0,0,0-.28-.48.57.57,0,1,1,.8-.8,2,2,0,0,1,0,2.95A2,2,0,0,1,18.08,24.26Z"/><path d="M14.87,25.32a2.29,2.29,0,0,1-1.51-.61h0l-1.08-1.08a.57.57,0,0,1,0-.8h0a1.25,1.25,0,0,0,.28-.47.81.81,0,0,0-.28-.88.8.8,0,0,0-.87-.27,1.34,1.34,0,0,0-.48.28.57.57,0,0,1-.8,0,.58.58,0,0,1,0-.81,2,2,0,0,1,2.94,0,2,2,0,0,1,.35,2.5l.72.71a1.26,1.26,0,0,0,.5.27.83.83,0,0,0,.86-.25.81.81,0,0,0,.24-.89,1.48,1.48,0,0,0-.26-.48.57.57,0,1,1,.84-.76,2.08,2.08,0,0,1,0,2.93A2,2,0,0,1,14.87,25.32Z"/><path d="M11.55,24.26a2,2,0,0,1-1.43-.64,1.91,1.91,0,0,1-.54-2.05,2.43,2.43,0,0,1,.54-.9.57.57,0,0,1,.8.8h0a1.34,1.34,0,0,0-.28.48.81.81,0,0,0,.28.87.81.81,0,0,0,.87.28,1.53,1.53,0,0,0,.48-.28.57.57,0,0,1,.8,0,.56.56,0,0,1,0,.8A2.18,2.18,0,0,1,11.55,24.26Z"/><path d="M23.45,21a2.22,2.22,0,0,1-1.52-.64.57.57,0,1,1,.8-.8,1.35,1.35,0,0,0,.48.27.8.8,0,0,0,.87-.27.81.81,0,0,0,.28-.87,1.4,1.4,0,0,0-.28-.48L23,17.19l0,0L17.8,12H14l-.91.91C12,14,11,14.44,10,14.25a4.22,4.22,0,0,1-2-1.37.56.56,0,0,1-.17-.4.54.54,0,0,1,.17-.4L11.2,8.86c2.05-2,6.51-1.49,7.72-1.29l1.94-1.94a.58.58,0,0,1,.8,0L27,11a.57.57,0,0,1,0,.8L25,13.86l-.92,2.76.82.83a2.44,2.44,0,0,1,.54.89,1.92,1.92,0,0,1-.54,2.06A2,2,0,0,1,23.45,21Zm-9.71-10.2H18a.59.59,0,0,1,.4.16l4.72,4.73L24,13.37a.56.56,0,0,1,.13-.22l1.75-1.75L21.26,6.83,19.51,8.58a.59.59,0,0,1-.51.16c-.05,0-5.1-1-7,.92L9.17,12.48a2.42,2.42,0,0,0,1.06.66c.55.11,1.21-.24,2-1.06L13.34,11A.59.59,0,0,1,13.74,10.84Z"/><path d="M6.18,21a2,2,0,0,1-1.44-.64,2,2,0,0,1,0-2.95L6.89,15.3a2.09,2.09,0,1,1,3,2.95.57.57,0,1,1-.8-.8H9A1.4,1.4,0,0,0,9.32,17,.81.81,0,0,0,9,16.1a.8.8,0,0,0-.87-.27,1.12,1.12,0,0,0-.48.28L5.54,18.25h0a1.29,1.29,0,0,0-.27.48.8.8,0,0,0,.27.87.81.81,0,0,0,.88.27,1.54,1.54,0,0,0,.48-.27.56.56,0,0,1,.79.8A2.18,2.18,0,0,1,6.18,21Z"/><path d="M8.33,23.19a2,2,0,0,1-1.44-.64,2,2,0,0,1-.54-2.06,2.6,2.6,0,0,1,.54-.89L9,17.45a2.36,2.36,0,0,1,1.52-.64A2.12,2.12,0,0,1,12,20.4L9.84,22.55A2.32,2.32,0,0,1,8.33,23.19ZM7.69,20.4a1.29,1.29,0,0,0-.27.48.8.8,0,0,0,.27.87.9.9,0,0,0,.64.31A1.2,1.2,0,0,0,9,21.75l2.15-2.15h0a1.4,1.4,0,0,0,.28-.48.83.83,0,0,0-.28-.87.9.9,0,0,0-.63-.31,1.25,1.25,0,0,0-.72.31L7.69,20.4Z"/><path d="M17,23.79a.58.58,0,0,1-.4-.17l-2.15-2.15a.57.57,0,0,1,.8-.8l2.15,2.15a.57.57,0,0,1,0,.8A.56.56,0,0,1,17,23.79Z"/><path d="M20.19,22.71a.55.55,0,0,1-.4-.16l-3.23-3.22a.57.57,0,0,1,0-.8.55.55,0,0,1,.8,0l3.23,3.22a.56.56,0,0,1-.4,1Z"/><path d="M22.33,20.57a.6.6,0,0,1-.4-.17l-3.22-3.22a.57.57,0,0,1,.8-.8l3.22,3.22a.55.55,0,0,1,0,.8A.56.56,0,0,1,22.33,20.57Z"/><path d="M6.22,17.34A.57.57,0,0,1,5.68,17l-1-3.1L2.59,11.8a.58.58,0,0,1-.16-.4A.56.56,0,0,1,2.6,11L8,5.63a.57.57,0,0,1,.8,0l1.94,1.94a16.83,16.83,0,0,1,4.15-.16.57.57,0,0,1,.5.63.56.56,0,0,1-.62.5,15.08,15.08,0,0,0-4.11.2.61.61,0,0,1-.51-.16L8.37,6.83,3.79,11.4l1.75,1.75a.59.59,0,0,1,.14.22L6.75,16.6a.56.56,0,0,1-.53.74Z"/><path class="cls-1" d="M24.71,4.65A14.18,14.18,0,0,0,4.65,24.71,14.18,14.18,0,0,0,24.71,4.65Z"/></g></g></svg>
|
After Width: | Height: | Size: 3.4 KiB |
1
salw_client/src/Icons/icon23.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 28.36 28.36"><defs><style>.cls-1{fill:#d7dfe4;}</style></defs><title>Element 27</title><g id="Ebene_2" data-name="Ebene 2"><g id="Ebene_1-2" data-name="Ebene 1"><path class="cls-1" d="M24.21,4.15A14.18,14.18,0,0,0,4.15,24.21a14.2,14.2,0,0,0,20.06,0,14.2,14.2,0,0,0,0-20.06Z"/><path d="M24.76,9.59h-2v-2A.55.55,0,0,0,22.19,7H20.14V5a.55.55,0,0,0-.55-.55H5.73A.55.55,0,0,0,5.18,5V20.21a.55.55,0,0,0,.55.55h2v2a.55.55,0,0,0,.55.55h2v2a.55.55,0,0,0,.55.55h9.15a.49.49,0,0,0,.37-.16l4.68-4.22a.5.5,0,0,0,.18-.42v-11A.51.51,0,0,0,24.76,9.59ZM6.32,5.52H19V17.15L16.2,19.6H6.32ZM8.89,20.73h7.46a.81.81,0,0,0,.37-.12l3.21-2.76a.55.55,0,0,0,.18-.43V8.12h1.47V19L18,22.2H8.89Zm15.29.15L19.87,24.8H11.49V23.33h6.73a.55.55,0,0,0,.36-.15l4-3.49a.57.57,0,0,0,.18-.43V10.69h1.47Z"/><path d="M8.67,8.77h8a.55.55,0,0,0,.55-.55.55.55,0,0,0-.55-.55h-8a.55.55,0,0,0-.55.55A.53.53,0,0,0,8.67,8.77Z"/><path d="M8.67,11.43h8a.55.55,0,0,0,.55-.55.55.55,0,0,0-.55-.55h-8a.55.55,0,0,0-.55.55A.51.51,0,0,0,8.67,11.43Z"/><path d="M16.66,13H14.51a.55.55,0,0,0,0,1.1h2.15a.55.55,0,0,0,.55-.55A.53.53,0,0,0,16.66,13Z"/><path d="M16.66,15.65H14.51a.55.55,0,0,0,0,1.1h2.15a.55.55,0,0,0,.55-.55A.53.53,0,0,0,16.66,15.65Z"/><path d="M12.59,18.16a.55.55,0,0,0,.55-.55v-4a.55.55,0,0,0-.55-.55h-4a.54.54,0,0,0-.55.55v4a.55.55,0,0,0,.55.55Zm-3.46-4H12V17H9.13Z"/></g></g></svg>
|
After Width: | Height: | Size: 1.4 KiB |
BIN
salw_client/src/Icons/icon24.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
1
salw_client/src/Icons/icon24.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 28.36 28.36"><defs><style>.cls-1{fill:#d7dfe4;}</style></defs><title>Element 28</title><g id="Ebene_2" data-name="Ebene 2"><g id="Ebene_1-2" data-name="Ebene 1"><path class="cls-1" d="M24.21,4.15A14.18,14.18,0,0,0,4.15,24.21a14.2,14.2,0,0,0,20.06,0,14.2,14.2,0,0,0,0-20.06Z"/><path d="M6.33,3.29A2.09,2.09,0,0,0,4.25,5.37v1a.38.38,0,0,0,.38.37H18.24a.37.37,0,0,0,.37-.37v-1a1.33,1.33,0,0,1,2.65,0V21.24a2.08,2.08,0,0,0,4.16,0,.38.38,0,0,0-.38-.38H22.77a.38.38,0,1,0,0,.76H24.6A1.32,1.32,0,0,1,22,21.24V5.37a2.09,2.09,0,0,0-2.08-2.08Zm0,.76h12a2,2,0,0,0-.48,1.32v.56H5V5.37A1.31,1.31,0,0,1,6.33,4.05Z"/><path d="M6.94,6.32V21.24A2.08,2.08,0,0,0,9,23.32h2.41v-.75H9A1.32,1.32,0,0,1,7.7,21.24V6.32Z"/><path d="M16.16,8.59a.37.37,0,0,0-.38.37.38.38,0,0,0,.37.38H19A.37.37,0,0,0,19.37,9,.37.37,0,0,0,19,8.59H16.16Z"/><path d="M9.93,8.59A.37.37,0,0,0,9.55,9a.38.38,0,0,0,.37.38h1.14A.37.37,0,0,0,11.44,9a.38.38,0,0,0-.37-.38H9.93Z"/><path d="M12.39,8.59a.38.38,0,1,0,0,.75h2.45a.38.38,0,1,0,0-.75H12.39Z"/><path d="M13.9,11.61a.39.39,0,0,0-.39.37.4.4,0,0,0,.38.39H19a.38.38,0,0,0,.38-.38.37.37,0,0,0-.37-.38H13.9Z"/><path d="M9.93,11.61a.37.37,0,0,0-.38.37.38.38,0,0,0,.37.39h2.64A.4.4,0,0,0,13,12a.38.38,0,0,0-.38-.38H9.93Z"/><path d="M14.46,14.6a3.59,3.59,0,1,0,3.59,3.59A3.6,3.6,0,0,0,14.46,14.6Zm0,.76a2.84,2.84,0,1,1-2.84,2.83A2.82,2.82,0,0,1,14.46,15.36Z"/><path d="M12.23,20.68v4.91a.38.38,0,0,0,.38.38.35.35,0,0,0,.19-.06l1.7-1,1.69,1a.38.38,0,0,0,.52-.13.32.32,0,0,0,.05-.19V20.68H16v4.24l-1.32-.79a.39.39,0,0,0-.39,0L13,24.92V20.68Z"/><path d="M17.48,22.57v.76h5.86v-.76Z"/></g></g></svg>
|
After Width: | Height: | Size: 1.6 KiB |
1
salw_client/src/Icons/icon25.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 28.36 28.36"><defs><style>.cls-1{fill:#d7dfe4;}</style></defs><title>Element 29</title><g id="Ebene_2" data-name="Ebene 2"><g id="Ebene_1-2" data-name="Ebene 1"><path class="cls-1" d="M24.21,4.15A14.18,14.18,0,0,0,4.15,24.21a14.2,14.2,0,0,0,20.06,0,14.2,14.2,0,0,0,0-20.06Z"/><path d="M21.23,23.05a2.24,2.24,0,0,1-1.51-.64.57.57,0,1,1,.8-.8h0a1.29,1.29,0,0,0,.48.27,1,1,0,0,0,1.14-1.14,1.28,1.28,0,0,0-.28-.49.55.55,0,0,1,0-.79.57.57,0,0,1,.8,0,2.12,2.12,0,0,1-1.44,3.59Z"/><path d="M18,24.12a2.18,2.18,0,0,1-1.51-.64.55.55,0,0,1,0-.8.57.57,0,0,1,.8,0h0a1.42,1.42,0,0,0,.47.28.81.81,0,0,0,.87-.28.79.79,0,0,0,.28-.87,1.24,1.24,0,0,0-.28-.48.57.57,0,1,1,.8-.8,2,2,0,0,1,0,2.95A2,2,0,0,1,18,24.12Z"/><path d="M14.81,25.17a2.33,2.33,0,0,1-1.52-.6h0L12.2,23.48a.57.57,0,0,1,0-.8h0a1.29,1.29,0,0,0,.27-.48.8.8,0,0,0-.27-.87.8.8,0,0,0-.87-.27,1.12,1.12,0,0,0-.48.28.56.56,0,0,1-.8,0,.57.57,0,0,1,0-.8,2,2,0,0,1,2.95,0,2,2,0,0,1,.34,2.5l.72.71a1.4,1.4,0,0,0,.5.27.82.82,0,0,0,.86-.25.84.84,0,0,0,.25-.89,1.29,1.29,0,0,0-.27-.48.57.57,0,1,1,.84-.76,2.08,2.08,0,0,1,0,2.93A1.94,1.94,0,0,1,14.81,25.17Z"/><path d="M11.49,24.12a2,2,0,0,1-1.44-.64,1.92,1.92,0,0,1-.54-2.05,2.43,2.43,0,0,1,.54-.9.57.57,0,0,1,.8.8h0a1.4,1.4,0,0,0-.28.48.81.81,0,0,0,.28.87.81.81,0,0,0,.87.28,1.4,1.4,0,0,0,.48-.28.57.57,0,1,1,.8.8A2.22,2.22,0,0,1,11.49,24.12Z"/><path d="M23.38,20.9a2.18,2.18,0,0,1-1.51-.64.57.57,0,0,1,0-.8.56.56,0,0,1,.79,0,1.35,1.35,0,0,0,.48.27.81.81,0,0,0,.88-.27.8.8,0,0,0,.27-.87,1.24,1.24,0,0,0-.28-.48L23,17h0l-5.19-5.2H13.91l-.91.91c-1.11,1.11-2.11,1.55-3.06,1.37a4.22,4.22,0,0,1-2-1.37.56.56,0,0,1-.17-.4.54.54,0,0,1,.17-.4s1.1-1.1,3.23-3.22,6.51-1.49,7.72-1.29l1.94-1.94a.55.55,0,0,1,.4-.16.54.54,0,0,1,.4.16L27,10.86a.57.57,0,0,1,0,.8l-2.06,2.06L24,16.48l.83.83a2.78,2.78,0,0,1,.54.89,2,2,0,0,1-.54,2.06A2,2,0,0,1,23.38,20.9ZM13.67,10.7H18a.59.59,0,0,1,.4.16l4.72,4.73.79-2.36A.52.52,0,0,1,24,13l1.75-1.75L21.19,6.69,19.44,8.44a.56.56,0,0,1-.51.15c-.05,0-5.09-1-7,.93L9.11,12.33a2.28,2.28,0,0,0,1.05.67c.55.11,1.22-.24,2-1.06l1.07-1.08A.59.59,0,0,1,13.67,10.7Z"/><path d="M6.11,20.9a2,2,0,0,1-1.43-.64,2,2,0,0,1,0-3l2.15-2.15a2,2,0,0,1,2.94,0,2,2,0,0,1,0,2.95.57.57,0,1,1-.8-.8H9a1.24,1.24,0,0,0,.28-.48A.81.81,0,0,0,9,16a.8.8,0,0,0-.87-.27,1.4,1.4,0,0,0-.48.27L5.48,18.11h0a1.24,1.24,0,0,0-.28.48.81.81,0,0,0,.28.87.8.8,0,0,0,.87.27,1.29,1.29,0,0,0,.48-.27.56.56,0,0,1,.8,0,.57.57,0,0,1,0,.8A2.22,2.22,0,0,1,6.11,20.9Z"/><path d="M8.26,23.05a2,2,0,0,1-1.43-.64,1.93,1.93,0,0,1-.54-2.06,2.44,2.44,0,0,1,.54-.89L9,17.31a2.31,2.31,0,0,1,1.52-.64,2.12,2.12,0,0,1,1.43,3.59L9.77,22.41A2.29,2.29,0,0,1,8.26,23.05Zm-.63-2.79a1.24,1.24,0,0,0-.28.48.79.79,0,0,0,.28.87.88.88,0,0,0,.63.31A1.2,1.2,0,0,0,9,21.61l2.15-2.15h0A1.4,1.4,0,0,0,11.4,19a.81.81,0,0,0-.28-.87.88.88,0,0,0-.63-.31,1.29,1.29,0,0,0-.72.31L7.63,20.26Z"/><path d="M16.9,23.65a.56.56,0,0,1-.4-.17l-2.15-2.15a.57.57,0,0,1,.8-.8l2.15,2.15a.57.57,0,0,1,0,.8A.6.6,0,0,1,16.9,23.65Z"/><path d="M20.12,22.57a.55.55,0,0,1-.4-.16L16.5,19.18a.55.55,0,0,1,0-.8.57.57,0,0,1,.8,0l3.22,3.23a.56.56,0,0,1-.4,1Z"/><path d="M22.27,20.42a.55.55,0,0,1-.4-.16L18.64,17a.57.57,0,0,1,.8-.8l3.23,3.22a.56.56,0,0,1-.4,1Z"/><path d="M6.15,17.2a.57.57,0,0,1-.54-.39l-1-3.09L2.53,11.66a.54.54,0,0,1-.17-.4.56.56,0,0,1,.17-.4L7.91,5.49a.57.57,0,0,1,.8,0l1.94,1.94a16.74,16.74,0,0,1,4.14-.16.56.56,0,0,1,.5.62.57.57,0,0,1-.62.51,15.68,15.68,0,0,0-4.1.19.58.58,0,0,1-.52-.15L8.3,6.69,3.73,11.26,5.48,13a.5.5,0,0,1,.13.22l1.08,3.23a.56.56,0,0,1-.36.71A.57.57,0,0,1,6.15,17.2Z"/></g></g></svg>
|
After Width: | Height: | Size: 3.5 KiB |
1
salw_client/src/Icons/icon26.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 29.36 29.36"><defs><style>.cls-1{fill:none;stroke:#000;stroke-miterlimit:10;}</style></defs><title>Element 30</title><g id="Ebene_2" data-name="Ebene 2"><g id="Ebene_1-2" data-name="Ebene 1"><path class="cls-1" d="M24.71,4.65A14.18,14.18,0,0,0,4.65,24.71,14.18,14.18,0,0,0,24.71,4.65Z"/><path d="M6.7,4.12A2.08,2.08,0,0,0,4.62,6.2v.94A.38.38,0,0,0,5,7.52H18.6A.38.38,0,0,0,19,7.14V6.2a1.33,1.33,0,1,1,2.65,0V22.07a2.08,2.08,0,1,0,4.16,0,.39.39,0,0,0-.38-.38H23.14a.38.38,0,1,0,0,.76H25a1.32,1.32,0,0,1-2.59-.38V6.2a2.08,2.08,0,0,0-2.07-2.08Zm0,.75h12a2,2,0,0,0-.48,1.32v.57H5.38V6.19A1.32,1.32,0,0,1,6.7,4.87Z"/><path d="M7.31,7.14V22.07a2.09,2.09,0,0,0,2.08,2.08H11.8v-.76H9.39a1.31,1.31,0,0,1-1.32-1.32V7.14Z"/><path d="M16.53,9.41a.38.38,0,0,0,0,.76h2.83a.38.38,0,1,0,0-.76H16.53Z"/><path d="M10.3,9.41a.38.38,0,0,0,0,.76h1.13a.38.38,0,1,0,0-.76H10.3Z"/><path d="M12.75,9.41a.38.38,0,0,0,0,.76H15.2a.38.38,0,0,0,.38-.37.39.39,0,0,0-.37-.39H12.75Z"/><path d="M14.26,12.44a.37.37,0,0,0-.38.37.38.38,0,0,0,.38.38h5.09a.39.39,0,0,0,.39-.37.38.38,0,0,0-.38-.38h-5.1Z"/><path d="M10.3,12.44a.38.38,0,1,0,0,.75h2.64a.37.37,0,0,0,.38-.37.37.37,0,0,0-.37-.38H10.3Z"/><path d="M14.83,15.43A3.59,3.59,0,1,0,18.42,19,3.59,3.59,0,0,0,14.83,15.43Zm0,.76A2.83,2.83,0,1,1,12,19,2.82,2.82,0,0,1,14.83,16.19Z"/><path d="M12.59,21.5v4.91a.38.38,0,0,0,.38.38.46.46,0,0,0,.2-.05l1.69-1,1.7,1a.38.38,0,0,0,.52-.13.46.46,0,0,0,.05-.2V21.5h-.76v4.25L15.06,25a.35.35,0,0,0-.39,0l-1.32.79V21.5Z"/><path d="M17.85,23.4v.75h5.86V23.4Z"/></g></g></svg>
|
After Width: | Height: | Size: 1.5 KiB |
1
salw_client/src/Icons/icon3.svg
Normal file
After Width: | Height: | Size: 6.8 KiB |
1
salw_client/src/Icons/icon4.svg
Normal file
After Width: | Height: | Size: 12 KiB |
1
salw_client/src/Icons/icon5.svg
Normal file
After Width: | Height: | Size: 7.0 KiB |
1
salw_client/src/Icons/icon6.svg
Normal file
After Width: | Height: | Size: 5.6 KiB |
1
salw_client/src/Icons/icon7.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 28.36 28.36"><defs><style>.cls-1{fill:#d7dfe4;}.cls-2{fill:none;stroke:#000;stroke-miterlimit:10;}</style></defs><title>Element 11</title><g id="Ebene_2" data-name="Ebene 2"><g id="Ebene_1-2" data-name="Ebene 1"><path class="cls-1" d="M4.15,4.15A14.18,14.18,0,0,1,24.21,24.21,14.18,14.18,0,0,1,4.15,4.15Z"/><path d="M17.31,13.65v.7a1,1,0,0,1-1,.92L14,15.34a1,1,0,0,1-1-1,1.51,1.51,0,0,1,.1-.75.28.28,0,0,1,.11.18v0a.1.1,0,0,0-.07.1.11.11,0,0,0,.09.1,1.64,1.64,0,0,0,.84,1.24c.06,0,.11-.06.07-.12l0,0a.24.24,0,0,0,.12,0c.13,0,.08-.22.08-.22L14,13.85a1.62,1.62,0,0,1,.39-.9l2-.22a.92.92,0,0,1,.92.92Zm8-5.14L24.9,8.1h-.15l-.22.41H6.69L6.5,8H6.16L6,8.51H5.32A.32.32,0,0,0,5,8.74v1.8l.06.11,0,.51,0,.06s-.18,0-.18.37a.24.24,0,0,0,.21.26,4,4,0,0,1,.81.19c.74.21.87,1,.67,2.14a6.24,6.24,0,0,1-.75,2c.06,0,.1,0,.1.07s-.08.08-.18.08l-.06.1c.06,0,.1,0,.1.07s-.08.09-.18.09l-.07.09c.06,0,.1.05.1.08s-.08.08-.18.08L5.37,17s.08,0,.08.07-.07.07-.17.07l-.07.12s.08,0,.08.07-.07.07-.16.07L5,17.54s.08,0,.08.06-.07.08-.16.08l-.06.1s0,0,0,.06-.06.06-.13.07l-.09.16s0,0,0,0,0,.06-.12.06l-.08.16s0,0,0,0,0,.05-.1.06l-.08.16,0,0s0,.05-.1.06l-.08.16s0,0,0,0,0,.05-.09.06l-.08.16a.05.05,0,0,1,0,0s0,0-.07.05l-.08.17a0,0,0,0,1,0,0s0,0-.06.05l-.09.2,0,0s0,0-.05,0l-.06.18s0,0,0,0,0,0,0,0l-.06.18s0,0,0,0,0,0-.06,0,0,.12,0,.16a.05.05,0,0,1,0,0s0,0,0,0l0,.14,0,.06,0,.1,0,.18a1.4,1.4,0,0,0,.09.83,1.81,1.81,0,0,0,.83.61H5.2v0a1,1,0,0,0-.31.58c0,.3.48.29.48.29s2.71,0,3.47,0,.69-.48.69-.48l.06-.5a3.23,3.23,0,0,0,.45-.26.78.78,0,0,0,.18-.5c0-.18,0-.45,0-.57a6.11,6.11,0,0,1,.36-1,1,1,0,0,1,.51-.54c.13-.08.11-.17.11-.17a.83.83,0,0,1,0-.93,1.21,1.21,0,0,1,.53-.67c.27-.12.19-.22.19-.22s-.3-.35.1-1.23c.25-.52.53-.67.83-.69a1.94,1.94,0,0,1,.86.29,4.43,4.43,0,0,0,1,.07l3.36-.14.11-.16-.08-.19A2.49,2.49,0,0,1,18,14.25a3.16,3.16,0,0,1,.12-1.13c.14-.29.71-.51.71-.51s5.59-.19,6.19-.23.6-.39.6-.39.11-.61.13-.8,0-.18,0-.18l0-.07,0,0,.12,0v-.48l0,0,0-.12A3.55,3.55,0,0,0,26,9.61,1.26,1.26,0,0,0,25.89,9a.49.49,0,0,1,0-.14c0-.07-.06,0-.06-.13a.2.2,0,0,0-.2-.2Z"/><line class="cls-2" x1="4.3" y1="4.01" x2="7.64" y2="7.35"/><line class="cls-2" x1="17.18" y1="16.88" x2="24.35" y2="24.06"/></g></g></svg>
|
After Width: | Height: | Size: 2.2 KiB |
1
salw_client/src/Icons/icon8.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 29.36 29.36"><defs><style>.cls-1,.cls-2{fill:none;stroke:#000;stroke-miterlimit:10;}.cls-2{stroke-width:0.75px;}</style></defs><title>Element 12</title><g id="Ebene_2" data-name="Ebene 2"><g id="Ebene_1-2" data-name="Ebene 1"><path class="cls-1" d="M4.65,4.65A14.18,14.18,0,0,1,24.71,24.71,14.18,14.18,0,0,1,4.65,4.65Z"/><path class="cls-2" d="M17.81,14.15v.7a1,1,0,0,1-1,.92l-2.32.07a1,1,0,0,1-1-1,1.51,1.51,0,0,1,.1-.75.28.28,0,0,1,.11.18v0a.1.1,0,0,0-.07.1.11.11,0,0,0,.09.1,1.64,1.64,0,0,0,.84,1.24c.06,0,.11-.06.07-.12l0,0a.24.24,0,0,0,.12,0c.13,0,.08-.22.08-.22l-.36-1.05a1.62,1.62,0,0,1,.39-.9l2-.22a.92.92,0,0,1,.92.92Zm8-5.14L25.4,8.6h-.15L25,9H7.19L7,8.53H6.66L6.45,9H5.82a.32.32,0,0,0-.33.23V11l.06.11,0,.51,0,.06s-.18,0-.18.37a.24.24,0,0,0,.21.26,4,4,0,0,1,.81.19c.74.21.87,1,.67,2.14a6.24,6.24,0,0,1-.75,2c.06,0,.1,0,.1.07s-.08.08-.18.08l-.06.1c.06,0,.1,0,.1.07s-.08.09-.18.09L6,17.22c.06,0,.1.05.1.08s-.08.08-.18.08l-.07.11s.08,0,.08.07-.07.07-.17.07l-.07.12s.08,0,.08.07-.07.07-.16.07L5.54,18s.08,0,.08.06-.07.08-.16.08l-.06.1s0,0,0,.06-.06.06-.13.07l-.09.16s0,0,0,0,0,.06-.12.06l-.08.16s0,0,0,0,0,.05-.1.06l-.08.16,0,0s0,.05-.1.06l-.08.16s0,0,0,0,0,.05-.09.06l-.08.16a.05.05,0,0,1,0,0s0,0-.07.05l-.08.17a0,0,0,0,1,0,0s0,0-.06.05l-.09.2,0,0s0,0,0,0l-.06.18s0,0,0,0,0,0-.05,0l-.06.18s0,0,0,0,0,0-.06,0,0,.12,0,.16a.05.05,0,0,1,0,0s0,0,0,0l0,.14,0,.06,0,.1,0,.18a1.4,1.4,0,0,0,.09.83,1.81,1.81,0,0,0,.83.61H5.7v0a1,1,0,0,0-.31.58c0,.3.48.29.48.29s2.71,0,3.47,0,.69-.48.69-.48l.06-.5a3.23,3.23,0,0,0,.45-.26.78.78,0,0,0,.18-.5c0-.18,0-.45,0-.57a6.11,6.11,0,0,1,.36-1,1,1,0,0,1,.51-.54c.13-.08.11-.17.11-.17a.83.83,0,0,1,0-.93,1.21,1.21,0,0,1,.53-.67c.27-.12.19-.22.19-.22s-.3-.35.1-1.23c.25-.52.53-.67.83-.69a1.94,1.94,0,0,1,.86.29,4.43,4.43,0,0,0,1,.07l3.36-.14.11-.16-.08-.19a2.49,2.49,0,0,1-.19-1.15,3.16,3.16,0,0,1,.12-1.13c.14-.29.71-.51.71-.51s5.59-.19,6.19-.23.6-.39.6-.39.11-.61.13-.8,0-.18,0-.18l0-.07,0,0,.12,0v-.48l0,0,0-.12a3.55,3.55,0,0,0,.09-.62,1.26,1.26,0,0,0-.14-.63.49.49,0,0,1,0-.14c0-.07-.06,0-.06-.13a.2.2,0,0,0-.2-.2Z"/><path class="cls-1" d="M4.65,4.65A14.18,14.18,0,0,1,24.71,24.71,14.18,14.18,0,0,1,4.65,4.65Zm0,0L7.22,7.22M18.14,18.14l6.57,6.57"/></g></g></svg>
|
After Width: | Height: | Size: 2.2 KiB |
1
salw_client/src/Icons/icon9.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 28.36 28.36"><defs><style>.cls-1{fill:#fff;}.cls-2{fill:none;stroke:#fff;stroke-miterlimit:10;}</style></defs><title>Element 13</title><g id="Ebene_2" data-name="Ebene 2"><g id="Ebene_1-2" data-name="Ebene 1"><path d="M4.15,4.15A14.18,14.18,0,0,1,24.21,24.21,14.18,14.18,0,0,1,4.15,4.15Z"/><path class="cls-1" d="M17.31,13.65v.7a1,1,0,0,1-1,.92L14,15.34a1,1,0,0,1-1-1,1.51,1.51,0,0,1,.1-.75.28.28,0,0,1,.11.18v0a.1.1,0,0,0-.07.1.11.11,0,0,0,.09.1,1.64,1.64,0,0,0,.84,1.24c.06,0,.11-.06.07-.12l0,0a.24.24,0,0,0,.12,0c.13,0,.08-.22.08-.22L14,13.85a1.62,1.62,0,0,1,.39-.9l2-.22a.92.92,0,0,1,.92.92Zm8-5.14L24.9,8.1h-.15l-.22.41H6.69L6.5,8H6.16L6,8.51H5.32A.32.32,0,0,0,5,8.74v1.8l.06.11,0,.51,0,.06s-.18,0-.18.37a.24.24,0,0,0,.21.26,4,4,0,0,1,.81.19c.74.21.87,1,.67,2.14a6.24,6.24,0,0,1-.75,2c.06,0,.1,0,.1.07s-.08.08-.18.08l-.06.1c.06,0,.1,0,.1.07s-.08.09-.18.09l-.07.09c.06,0,.1.05.1.08s-.08.08-.18.08L5.37,17s.08,0,.08.07-.07.07-.17.07l-.07.12s.08,0,.08.07-.07.07-.16.07L5,17.54s.08,0,.08.06-.07.08-.16.08l-.06.1s0,0,0,.06-.06.06-.13.07l-.09.16s0,0,0,0,0,.06-.12.06l-.08.16s0,0,0,0,0,.05-.1.06l-.08.16,0,0s0,.05-.1.06l-.08.16s0,0,0,0,0,.05-.09.06l-.08.16a.05.05,0,0,1,0,0s0,0-.07.05l-.08.17a0,0,0,0,1,0,0s0,0-.06.05l-.09.2,0,0s0,0-.05,0l-.06.18s0,0,0,0,0,0,0,0l-.06.18s0,0,0,0,0,0-.06,0,0,.12,0,.16a.05.05,0,0,1,0,0s0,0,0,0l0,.14,0,.06,0,.1,0,.18a1.4,1.4,0,0,0,.09.83,1.81,1.81,0,0,0,.83.61H5.2v0a1,1,0,0,0-.31.58c0,.3.48.29.48.29s2.71,0,3.47,0,.69-.48.69-.48l.06-.5a3.23,3.23,0,0,0,.45-.26.78.78,0,0,0,.18-.5c0-.18,0-.45,0-.57a6.11,6.11,0,0,1,.36-1,1,1,0,0,1,.51-.54c.13-.08.11-.17.11-.17a.83.83,0,0,1,0-.93,1.21,1.21,0,0,1,.53-.67c.27-.12.19-.22.19-.22s-.3-.35.1-1.23c.25-.52.53-.67.83-.69a1.94,1.94,0,0,1,.86.29,4.43,4.43,0,0,0,1,.07l3.36-.14.11-.16-.08-.19A2.49,2.49,0,0,1,18,14.25a3.16,3.16,0,0,1,.12-1.13c.14-.29.71-.51.71-.51s5.59-.19,6.19-.23.6-.39.6-.39.11-.61.13-.8,0-.18,0-.18l0-.07,0,0,.12,0v-.48l0,0,0-.12A3.55,3.55,0,0,0,26,9.61,1.26,1.26,0,0,0,25.89,9a.49.49,0,0,1,0-.14c0-.07-.06,0-.06-.13a.2.2,0,0,0-.2-.2Z"/><line class="cls-2" x1="16.79" y1="16.79" x2="24.21" y2="24.21"/><line class="cls-2" x1="4.15" y1="4.15" x2="7.44" y2="7.44"/></g></g></svg>
|
After Width: | Height: | Size: 2.2 KiB |
23
salw_client/src/Icons/person.svg
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="1080" height="1080" viewBox="0 0 1080 1080" xml:space="preserve">
|
||||||
|
<desc>Created with Fabric.js 5.2.4</desc>
|
||||||
|
<defs>
|
||||||
|
</defs>
|
||||||
|
<rect x="0" y="0" width="100%" height="100%" fill="transparent"></rect>
|
||||||
|
<g transform="matrix(1 0 0 1 540 540)" id="92f8c780-682d-410e-9305-55f6c76b821a" >
|
||||||
|
<rect style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(255,255,255); fill-rule: nonzero; opacity: 1; visibility: hidden;" vector-effect="non-scaling-stroke" x="-540" y="-540" rx="0" ry="0" width="1080" height="1080" />
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(1 0 0 1 540 540)" id="2902fc72-5f87-4d9a-a213-49b43b827461" >
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(1 0 0 1 174.64 508.98)" >
|
||||||
|
<g style="" vector-effect="non-scaling-stroke" >
|
||||||
|
<g transform="matrix(33.33 0 0 33.33 -0.01 1.63)" >
|
||||||
|
<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(0,0,0); fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke" transform=" translate(-12, -12.05)" d="M 13.9 2.999 C 13.900404510128258 3.767569137253463 13.437740927005041 4.4606849303964715 12.727791698439338 4.755083937232331 C 12.017842469873635 5.04948294406819 11.200454630665819 4.88717393579122 10.656851071891348 4.343856484152948 C 10.113247513116876 3.800539032514675 9.950508209994716 2.9832367548523684 10.244533420214 2.273132637048167 C 10.538558630433283 1.5630285192439657 11.231430756296502 1.1000001064500415 12 1.1 C 13.048950624407942 1.09999985471597 13.899447920724006 1.9500495208760782 13.9 2.9990000000000006 z M 13.544 6 L 10.456 6 C 9.604684814488484 5.999811949956359 8.862518492883558 6.579113995431316 8.655999999999999 7.405000000000001 L 6.993999999999999 14.057 C 6.949087749408432 14.259377888455008 7.00082563788415 14.471133674859198 7.133999999999999 14.63 C 7.29552492159201 14.833465444933692 7.539274387351227 14.954423826438266 7.798999999999999 14.96 C 8.086057992331412 14.955557715508808 8.34287529667128 14.780544391724366 8.451999999999998 14.515 L 10 9.1 L 10 13 L 9.078 22.219 C 9.057924474646427 22.41874832997887 9.123349536101328 22.61765922173752 9.258078407025312 22.76648984152766 C 9.392807277949297 22.915320461317805 9.584245430761463 23.000158042462385 9.785 23 L 9.859 23 C 10.19101964547464 22.999898168622497 10.475889150458729 22.763347237492642 10.537 22.437 L 12 14.583 L 13.463000000000001 22.437 C 13.524110849541275 22.763347237492642 13.808980354525362 22.999898168622497 14.141000000000002 23 L 14.215000000000002 23 C 14.415754569238539 23.000158042462385 14.607192722050703 22.915320461317805 14.74192159297469 22.76648984152766 C 14.876650463898674 22.61765922173752 14.942075525353575 22.41874832997887 14.922000000000002 22.219 L 14 13 L 14 9.1 L 15.548 14.515 C 15.65743368223532 14.780152409969652 15.914184251847452 14.954727069859064 16.201 14.959000000000001 C 16.460559067140714 14.953667969304108 16.704279363027823 14.83309055975996 16.866 14.63 C 16.99917436211585 14.471133674859198 17.05091225059157 14.259377888455008 17.006 14.057 L 15.344000000000001 7.405 C 15.137481507116442 6.579113995431316 14.395315185511514 5.999811949956358 13.544 6 z" stroke-linecap="round" />
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(33.33 0 0 33.33 -0.04 -0.04)" >
|
||||||
|
<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: none; fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke" transform=" translate(-12, -12)" d="M 0 0 L 24 0 L 24 24 L 0 24 z" stroke-linecap="round" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 3.9 KiB |
33
salw_client/src/Icons/person2.svg
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="1080" height="1080" viewBox="0 0 1080 1080" xml:space="preserve">
|
||||||
|
<desc>Created with Fabric.js 5.2.4</desc>
|
||||||
|
<defs>
|
||||||
|
</defs>
|
||||||
|
<rect x="0" y="0" width="100%" height="100%" fill="transparent"></rect>
|
||||||
|
<g transform="matrix(1 0 0 1 540 540)" id="92f8c780-682d-410e-9305-55f6c76b821a" >
|
||||||
|
<rect style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(255,255,255); fill-rule: nonzero; opacity: 1; visibility: hidden;" vector-effect="non-scaling-stroke" x="-540" y="-540" rx="0" ry="0" width="1080" height="1080" />
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(1 0 0 1 540 540)" id="2902fc72-5f87-4d9a-a213-49b43b827461" >
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(1 0 0 1 174.64 508.98)" >
|
||||||
|
<g style="" vector-effect="non-scaling-stroke" >
|
||||||
|
<g transform="matrix(33.33 0 0 33.33 -0.01 1.63)" >
|
||||||
|
<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(0,0,0); fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke" transform=" translate(-12, -12.05)" d="M 13.9 2.999 C 13.900404510128258 3.767569137253463 13.437740927005041 4.4606849303964715 12.727791698439338 4.755083937232331 C 12.017842469873635 5.04948294406819 11.200454630665819 4.88717393579122 10.656851071891348 4.343856484152948 C 10.113247513116876 3.800539032514675 9.950508209994716 2.9832367548523684 10.244533420214 2.273132637048167 C 10.538558630433283 1.5630285192439657 11.231430756296502 1.1000001064500415 12 1.1 C 13.048950624407942 1.09999985471597 13.899447920724006 1.9500495208760782 13.9 2.9990000000000006 z M 13.544 6 L 10.456 6 C 9.604684814488484 5.999811949956359 8.862518492883558 6.579113995431316 8.655999999999999 7.405000000000001 L 6.993999999999999 14.057 C 6.949087749408432 14.259377888455008 7.00082563788415 14.471133674859198 7.133999999999999 14.63 C 7.29552492159201 14.833465444933692 7.539274387351227 14.954423826438266 7.798999999999999 14.96 C 8.086057992331412 14.955557715508808 8.34287529667128 14.780544391724366 8.451999999999998 14.515 L 10 9.1 L 10 13 L 9.078 22.219 C 9.057924474646427 22.41874832997887 9.123349536101328 22.61765922173752 9.258078407025312 22.76648984152766 C 9.392807277949297 22.915320461317805 9.584245430761463 23.000158042462385 9.785 23 L 9.859 23 C 10.19101964547464 22.999898168622497 10.475889150458729 22.763347237492642 10.537 22.437 L 12 14.583 L 13.463000000000001 22.437 C 13.524110849541275 22.763347237492642 13.808980354525362 22.999898168622497 14.141000000000002 23 L 14.215000000000002 23 C 14.415754569238539 23.000158042462385 14.607192722050703 22.915320461317805 14.74192159297469 22.76648984152766 C 14.876650463898674 22.61765922173752 14.942075525353575 22.41874832997887 14.922000000000002 22.219 L 14 13 L 14 9.1 L 15.548 14.515 C 15.65743368223532 14.780152409969652 15.914184251847452 14.954727069859064 16.201 14.959000000000001 C 16.460559067140714 14.953667969304108 16.704279363027823 14.83309055975996 16.866 14.63 C 16.99917436211585 14.471133674859198 17.05091225059157 14.259377888455008 17.006 14.057 L 15.344000000000001 7.405 C 15.137481507116442 6.579113995431316 14.395315185511514 5.999811949956358 13.544 6 z" stroke-linecap="round" />
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(33.33 0 0 33.33 -0.04 -0.04)" >
|
||||||
|
<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: none; fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke" transform=" translate(-12, -12)" d="M 0 0 L 24 0 L 24 24 L 0 24 z" stroke-linecap="round" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(1 0 0 1 508.64 510.94)" >
|
||||||
|
<g style="" vector-effect="non-scaling-stroke" >
|
||||||
|
<g transform="matrix(33.33 0 0 33.33 -0.01 1.63)" >
|
||||||
|
<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(0,0,0); fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke" transform=" translate(-12, -12.05)" d="M 13.9 2.999 C 13.900404510128258 3.767569137253463 13.437740927005041 4.4606849303964715 12.727791698439338 4.755083937232331 C 12.017842469873635 5.04948294406819 11.200454630665819 4.88717393579122 10.656851071891348 4.343856484152948 C 10.113247513116876 3.800539032514675 9.950508209994716 2.9832367548523684 10.244533420214 2.273132637048167 C 10.538558630433283 1.5630285192439657 11.231430756296502 1.1000001064500415 12 1.1 C 13.048950624407942 1.09999985471597 13.899447920724006 1.9500495208760782 13.9 2.9990000000000006 z M 13.544 6 L 10.456 6 C 9.604684814488484 5.999811949956359 8.862518492883558 6.579113995431316 8.655999999999999 7.405000000000001 L 6.993999999999999 14.057 C 6.949087749408432 14.259377888455008 7.00082563788415 14.471133674859198 7.133999999999999 14.63 C 7.29552492159201 14.833465444933692 7.539274387351227 14.954423826438266 7.798999999999999 14.96 C 8.086057992331412 14.955557715508808 8.34287529667128 14.780544391724366 8.451999999999998 14.515 L 10 9.1 L 10 13 L 9.078 22.219 C 9.057924474646427 22.41874832997887 9.123349536101328 22.61765922173752 9.258078407025312 22.76648984152766 C 9.392807277949297 22.915320461317805 9.584245430761463 23.000158042462385 9.785 23 L 9.859 23 C 10.19101964547464 22.999898168622497 10.475889150458729 22.763347237492642 10.537 22.437 L 12 14.583 L 13.463000000000001 22.437 C 13.524110849541275 22.763347237492642 13.808980354525362 22.999898168622497 14.141000000000002 23 L 14.215000000000002 23 C 14.415754569238539 23.000158042462385 14.607192722050703 22.915320461317805 14.74192159297469 22.76648984152766 C 14.876650463898674 22.61765922173752 14.942075525353575 22.41874832997887 14.922000000000002 22.219 L 14 13 L 14 9.1 L 15.548 14.515 C 15.65743368223532 14.780152409969652 15.914184251847452 14.954727069859064 16.201 14.959000000000001 C 16.460559067140714 14.953667969304108 16.704279363027823 14.83309055975996 16.866 14.63 C 16.99917436211585 14.471133674859198 17.05091225059157 14.259377888455008 17.006 14.057 L 15.344000000000001 7.405 C 15.137481507116442 6.579113995431316 14.395315185511514 5.999811949956358 13.544 6 z" stroke-linecap="round" />
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(33.33 0 0 33.33 -0.04 -0.04)" >
|
||||||
|
<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: none; fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke" transform=" translate(-12, -12)" d="M 0 0 L 24 0 L 24 24 L 0 24 z" stroke-linecap="round" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 6.8 KiB |
42
salw_client/src/Icons/person3.svg
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="1080" height="1080" viewBox="0 0 1080 1080" xml:space="preserve">
|
||||||
|
<desc>Created with Fabric.js 5.2.4</desc>
|
||||||
|
<defs>
|
||||||
|
</defs>
|
||||||
|
<g transform="matrix(1 0 0 1 540 540)" id="92f8c780-682d-410e-9305-55f6c76b821a" >
|
||||||
|
<rect style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(255,255,255); fill-rule: nonzero; opacity: 1; visibility: hidden;" vector-effect="non-scaling-stroke" x="-540" y="-540" rx="0" ry="0" width="1080" height="1080" />
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(1 0 0 1 540 540)" id="2902fc72-5f87-4d9a-a213-49b43b827461" >
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(1 0 0 1 174.64 508.98)" >
|
||||||
|
<g style="" vector-effect="non-scaling-stroke" >
|
||||||
|
<g transform="matrix(33.33 0 0 33.33 -0.01 1.63)" >
|
||||||
|
<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(0,0,0); fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke" transform=" translate(-12, -12.05)" d="M 13.9 2.999 C 13.900404510128258 3.767569137253463 13.437740927005041 4.4606849303964715 12.727791698439338 4.755083937232331 C 12.017842469873635 5.04948294406819 11.200454630665819 4.88717393579122 10.656851071891348 4.343856484152948 C 10.113247513116876 3.800539032514675 9.950508209994716 2.9832367548523684 10.244533420214 2.273132637048167 C 10.538558630433283 1.5630285192439657 11.231430756296502 1.1000001064500415 12 1.1 C 13.048950624407942 1.09999985471597 13.899447920724006 1.9500495208760782 13.9 2.9990000000000006 z M 13.544 6 L 10.456 6 C 9.604684814488484 5.999811949956359 8.862518492883558 6.579113995431316 8.655999999999999 7.405000000000001 L 6.993999999999999 14.057 C 6.949087749408432 14.259377888455008 7.00082563788415 14.471133674859198 7.133999999999999 14.63 C 7.29552492159201 14.833465444933692 7.539274387351227 14.954423826438266 7.798999999999999 14.96 C 8.086057992331412 14.955557715508808 8.34287529667128 14.780544391724366 8.451999999999998 14.515 L 10 9.1 L 10 13 L 9.078 22.219 C 9.057924474646427 22.41874832997887 9.123349536101328 22.61765922173752 9.258078407025312 22.76648984152766 C 9.392807277949297 22.915320461317805 9.584245430761463 23.000158042462385 9.785 23 L 9.859 23 C 10.19101964547464 22.999898168622497 10.475889150458729 22.763347237492642 10.537 22.437 L 12 14.583 L 13.463000000000001 22.437 C 13.524110849541275 22.763347237492642 13.808980354525362 22.999898168622497 14.141000000000002 23 L 14.215000000000002 23 C 14.415754569238539 23.000158042462385 14.607192722050703 22.915320461317805 14.74192159297469 22.76648984152766 C 14.876650463898674 22.61765922173752 14.942075525353575 22.41874832997887 14.922000000000002 22.219 L 14 13 L 14 9.1 L 15.548 14.515 C 15.65743368223532 14.780152409969652 15.914184251847452 14.954727069859064 16.201 14.959000000000001 C 16.460559067140714 14.953667969304108 16.704279363027823 14.83309055975996 16.866 14.63 C 16.99917436211585 14.471133674859198 17.05091225059157 14.259377888455008 17.006 14.057 L 15.344000000000001 7.405 C 15.137481507116442 6.579113995431316 14.395315185511514 5.999811949956358 13.544 6 z" stroke-linecap="round" />
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(33.33 0 0 33.33 -0.04 -0.04)" >
|
||||||
|
<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: none; fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke" transform=" translate(-12, -12)" d="M 0 0 L 24 0 L 24 24 L 0 24 z" stroke-linecap="round" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(1 0 0 1 508.64 510.94)" >
|
||||||
|
<g style="" vector-effect="non-scaling-stroke" >
|
||||||
|
<g transform="matrix(33.33 0 0 33.33 -0.01 1.63)" >
|
||||||
|
<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(0,0,0); fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke" transform=" translate(-12, -12.05)" d="M 13.9 2.999 C 13.900404510128258 3.767569137253463 13.437740927005041 4.4606849303964715 12.727791698439338 4.755083937232331 C 12.017842469873635 5.04948294406819 11.200454630665819 4.88717393579122 10.656851071891348 4.343856484152948 C 10.113247513116876 3.800539032514675 9.950508209994716 2.9832367548523684 10.244533420214 2.273132637048167 C 10.538558630433283 1.5630285192439657 11.231430756296502 1.1000001064500415 12 1.1 C 13.048950624407942 1.09999985471597 13.899447920724006 1.9500495208760782 13.9 2.9990000000000006 z M 13.544 6 L 10.456 6 C 9.604684814488484 5.999811949956359 8.862518492883558 6.579113995431316 8.655999999999999 7.405000000000001 L 6.993999999999999 14.057 C 6.949087749408432 14.259377888455008 7.00082563788415 14.471133674859198 7.133999999999999 14.63 C 7.29552492159201 14.833465444933692 7.539274387351227 14.954423826438266 7.798999999999999 14.96 C 8.086057992331412 14.955557715508808 8.34287529667128 14.780544391724366 8.451999999999998 14.515 L 10 9.1 L 10 13 L 9.078 22.219 C 9.057924474646427 22.41874832997887 9.123349536101328 22.61765922173752 9.258078407025312 22.76648984152766 C 9.392807277949297 22.915320461317805 9.584245430761463 23.000158042462385 9.785 23 L 9.859 23 C 10.19101964547464 22.999898168622497 10.475889150458729 22.763347237492642 10.537 22.437 L 12 14.583 L 13.463000000000001 22.437 C 13.524110849541275 22.763347237492642 13.808980354525362 22.999898168622497 14.141000000000002 23 L 14.215000000000002 23 C 14.415754569238539 23.000158042462385 14.607192722050703 22.915320461317805 14.74192159297469 22.76648984152766 C 14.876650463898674 22.61765922173752 14.942075525353575 22.41874832997887 14.922000000000002 22.219 L 14 13 L 14 9.1 L 15.548 14.515 C 15.65743368223532 14.780152409969652 15.914184251847452 14.954727069859064 16.201 14.959000000000001 C 16.460559067140714 14.953667969304108 16.704279363027823 14.83309055975996 16.866 14.63 C 16.99917436211585 14.471133674859198 17.05091225059157 14.259377888455008 17.006 14.057 L 15.344000000000001 7.405 C 15.137481507116442 6.579113995431316 14.395315185511514 5.999811949956358 13.544 6 z" stroke-linecap="round" />
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(33.33 0 0 33.33 -0.04 -0.04)" >
|
||||||
|
<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: none; fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke" transform=" translate(-12, -12)" d="M 0 0 L 24 0 L 24 24 L 0 24 z" stroke-linecap="round" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(1 0 0 1 844.94 511.75)" >
|
||||||
|
<g style="" vector-effect="non-scaling-stroke" >
|
||||||
|
<g transform="matrix(33.33 0 0 33.33 -0.01 1.63)" >
|
||||||
|
<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(0,0,0); fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke" transform=" translate(-12, -12.05)" d="M 13.9 2.999 C 13.900404510128258 3.767569137253463 13.437740927005041 4.4606849303964715 12.727791698439338 4.755083937232331 C 12.017842469873635 5.04948294406819 11.200454630665819 4.88717393579122 10.656851071891348 4.343856484152948 C 10.113247513116876 3.800539032514675 9.950508209994716 2.9832367548523684 10.244533420214 2.273132637048167 C 10.538558630433283 1.5630285192439657 11.231430756296502 1.1000001064500415 12 1.1 C 13.048950624407942 1.09999985471597 13.899447920724006 1.9500495208760782 13.9 2.9990000000000006 z M 13.544 6 L 10.456 6 C 9.604684814488484 5.999811949956359 8.862518492883558 6.579113995431316 8.655999999999999 7.405000000000001 L 6.993999999999999 14.057 C 6.949087749408432 14.259377888455008 7.00082563788415 14.471133674859198 7.133999999999999 14.63 C 7.29552492159201 14.833465444933692 7.539274387351227 14.954423826438266 7.798999999999999 14.96 C 8.086057992331412 14.955557715508808 8.34287529667128 14.780544391724366 8.451999999999998 14.515 L 10 9.1 L 10 13 L 9.078 22.219 C 9.057924474646427 22.41874832997887 9.123349536101328 22.61765922173752 9.258078407025312 22.76648984152766 C 9.392807277949297 22.915320461317805 9.584245430761463 23.000158042462385 9.785 23 L 9.859 23 C 10.19101964547464 22.999898168622497 10.475889150458729 22.763347237492642 10.537 22.437 L 12 14.583 L 13.463000000000001 22.437 C 13.524110849541275 22.763347237492642 13.808980354525362 22.999898168622497 14.141000000000002 23 L 14.215000000000002 23 C 14.415754569238539 23.000158042462385 14.607192722050703 22.915320461317805 14.74192159297469 22.76648984152766 C 14.876650463898674 22.61765922173752 14.942075525353575 22.41874832997887 14.922000000000002 22.219 L 14 13 L 14 9.1 L 15.548 14.515 C 15.65743368223532 14.780152409969652 15.914184251847452 14.954727069859064 16.201 14.959000000000001 C 16.460559067140714 14.953667969304108 16.704279363027823 14.83309055975996 16.866 14.63 C 16.99917436211585 14.471133674859198 17.05091225059157 14.259377888455008 17.006 14.057 L 15.344000000000001 7.405 C 15.137481507116442 6.579113995431316 14.395315185511514 5.999811949956358 13.544 6 z" stroke-linecap="round" />
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(33.33 0 0 33.33 -0.04 -0.04)" >
|
||||||
|
<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: none; fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke" transform=" translate(-12, -12)" d="M 0 0 L 24 0 L 24 24 L 0 24 z" stroke-linecap="round" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 9.7 KiB |
6
salw_client/src/Styles/Base/_base.scss
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
// _base.scss
|
||||||
|
* {
|
||||||
|
box-sizing: border-box;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
0
salw_client/src/Styles/Base/_sreset.scss
Normal file
0
salw_client/src/Styles/Components/_buttons.scss
Normal file
5
salw_client/src/Styles/Components/_cards.scss
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
.card{
|
||||||
|
// background-color: red;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.26);
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
0
salw_client/src/Styles/Components/_forms.scss
Normal file
38
salw_client/src/Styles/Components/_zoom_control.scss
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/* Styles for custom zoom control buttons */
|
||||||
|
.custom-zoom-control {
|
||||||
|
position: absolute;
|
||||||
|
top: 10px;
|
||||||
|
right: 10px;
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-zoom-control button {
|
||||||
|
background-color: #fff;
|
||||||
|
border: 2px solid #bbb;
|
||||||
|
border-radius: 2px;
|
||||||
|
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
|
||||||
|
color: #333;
|
||||||
|
cursor: pointer;
|
||||||
|
display: block;
|
||||||
|
font-size: 18px;
|
||||||
|
line-height: 18px;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
outline: none;
|
||||||
|
padding: 5px;
|
||||||
|
text-align: center;
|
||||||
|
text-decoration: none;
|
||||||
|
transition: background-color 0.2s ease;
|
||||||
|
width: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-zoom-control button:hover {
|
||||||
|
background-color: #f4f4f4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-zoom-control button:active {
|
||||||
|
background-color: #e6e6e6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-zoom-control button:first-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|