PSSM Pictures Gallery
@ -1,10 +1,9 @@
|
||||
import React from "react";
|
||||
import { BrowserRouter as Router, Route, Link, Switch, Routes } from "react-router-dom";
|
||||
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 NavDropdown from "react-bootstrap/NavDropdown";
|
||||
import Home from "../../Pages/Home";
|
||||
import About from "../../Pages/About";
|
||||
import ControlInAfrica from "../../Pages/ControlInAfrica";
|
||||
@ -14,16 +13,17 @@ const NavBarSalw = () => {
|
||||
return (
|
||||
<>
|
||||
<Router>
|
||||
<Navbar expand="lg" className="bg-body-tertiary">
|
||||
<Container>
|
||||
<Navbar.Brand href="#home">SALW Guide</Navbar.Brand>
|
||||
<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 href="home">Home</Nav.Link>
|
||||
<Nav.Link href="ControlInAfrica">SALW Control in Africa</Nav.Link>
|
||||
<Nav.Link href="pssm">PSSM</Nav.Link>
|
||||
<Nav.Link href="about">About</Nav.Link>
|
||||
<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>
|
||||
|
@ -2,7 +2,6 @@ import React, { useState } from "react";
|
||||
import Card_ from "../../UI/Card_/Card_";
|
||||
import DOMPurify from "dompurify";
|
||||
import parse from "html-react-parser";
|
||||
import TruncateContent from "../../Helpers/TruncateContent/TruncateContent";
|
||||
import Collapse from "react-bootstrap/Collapse";
|
||||
|
||||
const Blurb = () => {
|
||||
@ -30,14 +29,14 @@ const Blurb = () => {
|
||||
]);
|
||||
|
||||
return (
|
||||
<Card_ className="p-3">
|
||||
<Card_ className="blurb p-3">
|
||||
<MainText footnotes={footnotes} />
|
||||
</Card_>
|
||||
);
|
||||
};
|
||||
|
||||
const MainText = ({ footnotes }) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
const [open, setOpen] = useState(true);
|
||||
const [isHidden, setIsHidden] = useState(true);
|
||||
return (
|
||||
<div>
|
||||
@ -157,14 +156,17 @@ const MainText = ({ footnotes }) => {
|
||||
</div>
|
||||
</div>
|
||||
</Collapse>
|
||||
<a
|
||||
{/* <a
|
||||
href="#"
|
||||
onClick={() => {setOpen(!open); setIsHidden(!isHidden);}}
|
||||
onClick={() => {
|
||||
setOpen(!open);
|
||||
setIsHidden(!isHidden);
|
||||
}}
|
||||
aria-controls="example-collapse-text"
|
||||
aria-expanded={open}
|
||||
>
|
||||
{isHidden ? "Read more" : "Read less"}
|
||||
</a>
|
||||
</a> */}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
53
src/Components/Layout/PSSM/ImageGallery.jsx
Normal file
@ -0,0 +1,53 @@
|
||||
import React, { useState } from "react";
|
||||
import images 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(images).map((key, index) => (
|
||||
<img
|
||||
key={index}
|
||||
src={images[key]}
|
||||
alt={key}
|
||||
className="thumbnail"
|
||||
onClick={() => handleThumbnailClick(images[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
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
|
12
src/Components/Layout/PSSM/ImportImages.js
Normal file
@ -0,0 +1,12 @@
|
||||
// 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)$/));
|
||||
|
||||
export default images;
|
@ -1,4 +1,4 @@
|
||||
import React, { useEffect } from "react";
|
||||
import React, { useEffect, createRef } from "react";
|
||||
|
||||
import { MapContainer, GeoJSON, useMap } from "react-leaflet";
|
||||
import L from "leaflet";
|
||||
@ -16,7 +16,7 @@ const CustomZoomControl = React.memo(() => {
|
||||
|
||||
useEffect(() => {
|
||||
const zoomControl = L.control.zoom({
|
||||
position: 'topright' // Change the position to bottom right
|
||||
position: "topright", // Change the position to bottom right
|
||||
});
|
||||
map.addControl(zoomControl);
|
||||
|
||||
@ -33,6 +33,8 @@ class PSSM extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.mapRef = createRef(); // Create a ref to store the MapContainer instance
|
||||
|
||||
this.state = {
|
||||
africaCountries: null,
|
||||
countriesNames: [],
|
||||
@ -93,6 +95,22 @@ class PSSM extends React.Component {
|
||||
});
|
||||
};
|
||||
|
||||
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: [],
|
||||
@ -135,8 +153,9 @@ class PSSM extends React.Component {
|
||||
}
|
||||
|
||||
return (
|
||||
<Card_ id="map" className="map-container mt-3">
|
||||
<Card_ id="map" className="map-container">
|
||||
<MapContainer
|
||||
ref={this.mapRef}
|
||||
center={this.state.center}
|
||||
zoom={this.state.zoom}
|
||||
style={{ width: "100%", height: "100%" }}
|
||||
@ -182,14 +201,19 @@ class PSSM extends React.Component {
|
||||
}
|
||||
})}
|
||||
|
||||
<CustomZoomControl />
|
||||
<SelectMenu
|
||||
ecowasCountries={ecowasCountries}
|
||||
recsaCountries={recsaCountries}
|
||||
selectedCountry={selectedCountry}
|
||||
handleCountryChange={this.handleCountryChange}
|
||||
></SelectMenu>
|
||||
{/* <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>
|
||||
|
10
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
|
@ -1,12 +1,28 @@
|
||||
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 className="p-5">
|
||||
<Blurb></Blurb>
|
||||
<PSSM></PSSM>
|
||||
<Container fluid className="p-5">
|
||||
<Row>
|
||||
<Col sm={7}>
|
||||
<Blurb></Blurb>
|
||||
<ImpactStories className="mt-3 p-3"></ImpactStories>
|
||||
<PssmResources className="mt-3 p-3"></PssmResources>
|
||||
</Col>
|
||||
<Col sm={5}>
|
||||
<PSSM></PSSM>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<ImageGallery className="mt-3"></ImageGallery>
|
||||
</Row>
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
|
8
src/Styles/Layout/_blurb.scss
Normal file
@ -0,0 +1,8 @@
|
||||
.blurb {
|
||||
width: 100%; /* Adjust the width as needed */
|
||||
height: 50%; /* Adjust the height as needed */
|
||||
overflow-y: auto;
|
||||
border: 1px solid #ccc; /* Optional: Add a border for better visibility */
|
||||
padding: 10px; /* Optional: Add some padding */
|
||||
box-sizing: border-box; /* Ensure padding is included in the element's total width and height */
|
||||
}
|
13
src/Styles/Layout/_nav_bar.scss
Normal file
@ -0,0 +1,13 @@
|
||||
.nav-bar{
|
||||
background-color: $primary-accent-color !important;
|
||||
}
|
||||
|
||||
.nav-bar-title{
|
||||
font-size: 26px;
|
||||
}
|
||||
|
||||
.nav-bar-item{
|
||||
font-size: 26px;
|
||||
color: $primary-text-color;
|
||||
margin-right: 10px;
|
||||
}
|
49
src/Styles/Layout/_pssm_image_gallery.scss
Normal file
@ -0,0 +1,49 @@
|
||||
.image-gallery {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.thumbnail {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
object-fit: cover;
|
||||
cursor: pointer;
|
||||
transition: transform 0.2s;
|
||||
}
|
||||
|
||||
.thumbnail:hover {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
.modal {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.8);
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
position: relative;
|
||||
max-width: 90%;
|
||||
max-height: 90%;
|
||||
}
|
||||
|
||||
.close {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
color: white;
|
||||
font-size: 30px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.full-size-image {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
@ -17,6 +17,9 @@
|
||||
@import 'Layout/_map_info_box';
|
||||
@import 'Layout/_map_info_box2';
|
||||
@import 'Layout/_legend';
|
||||
@import 'Layout/_blurb';
|
||||
@import 'Layout/_pssm_image_gallery';
|
||||
@import 'Layout/_nav_bar';
|
||||
|
||||
// Import other layout partials...
|
||||
|
||||
|
BIN
src/img/pssm/1000013063.jpg
Normal file
After Width: | Height: | Size: 476 KiB |
BIN
src/img/pssm/1000013066.jpg
Normal file
After Width: | Height: | Size: 549 KiB |
BIN
src/img/pssm/1000013069.jpg
Normal file
After Width: | Height: | Size: 488 KiB |
BIN
src/img/pssm/1000013072.jpg
Normal file
After Width: | Height: | Size: 520 KiB |
BIN
src/img/pssm/1000013075.jpg
Normal file
After Width: | Height: | Size: 455 KiB |
BIN
src/img/pssm/1000013078.jpg
Normal file
After Width: | Height: | Size: 495 KiB |
BIN
src/img/pssm/Bild1_Nikhil.jpg
Normal file
After Width: | Height: | Size: 70 KiB |
BIN
src/img/pssm/Bild2_Nikhil.jpg
Normal file
After Width: | Height: | Size: 95 KiB |
BIN
src/img/pssm/Group of Senior Instructors and Instructors.jpg
Normal file
After Width: | Height: | Size: 14 MiB |
BIN
src/img/pssm/Image 1.jpg
Normal file
After Width: | Height: | Size: 117 KiB |
BIN
src/img/pssm/Opening 2.jpg
Normal file
After Width: | Height: | Size: 141 KiB |
BIN
src/img/pssm/Storekeeper and Policewoman.jpg
Normal file
After Width: | Height: | Size: 240 KiB |
BIN
src/img/pssm/bild.jpg
Normal file
After Width: | Height: | Size: 1.5 MiB |