feat: implement CreateOrphanage and Orphanage pages with map integration and styling
This commit is contained in:
6
web/src/images/map_marker.svg
Normal file
6
web/src/images/map_marker.svg
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<svg width="64" height="72" viewBox="0 0 64 72" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M64 18.271V43.694C64 53.7844 55.5565 61.9651 45.1421 61.9651H43.2347L33.4941 71.3963C33.1127 71.7659 32.5849 72 32 72C31.4596 72 30.97 71.809 30.5949 71.4887L30.4296 71.3285L30.4232 71.3224L20.7653 61.9651H18.8516C8.44347 61.9651 0 53.7844 0 43.694V18.271C0 8.1807 8.44347 0 18.8579 0H45.1421C55.5565 0 64 8.1807 64 18.271Z" fill="#FFD666"/>
|
||||||
|
<path d="M14.2697 35.219C12.4132 35.219 11.355 37.2687 12.4322 38.7487C16.6205 44.5139 23.5462 48.2728 31.3717 48.2728C39.1972 48.2728 46.1166 44.5077 50.3049 38.7487C51.3821 37.2687 50.324 35.219 48.4674 35.219H14.2697Z" fill="white"/>
|
||||||
|
<path d="M25.1432 26.4937H13.9405V21.0196C13.9405 17.9976 16.4497 15.5454 19.5419 15.5454C22.634 15.5454 25.1432 17.9976 25.1432 21.0196V26.4937Z" fill="white"/>
|
||||||
|
<path d="M48.803 26.4937H37.6002V21.0196C37.6002 17.9976 40.1094 15.5454 43.2016 15.5454C46.2938 15.5454 48.803 17.9976 48.803 21.0196V26.4937Z" fill="white"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1013 B |
210
web/src/pages/CreateOrphanage.tsx
Normal file
210
web/src/pages/CreateOrphanage.tsx
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
import React, { useState, FormEvent, ChangeEvent } from "react";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import { FiPlus } from "react-icons/fi";
|
||||||
|
import { GoogleMap, useJsApiLoader, Marker } from '@react-google-maps/api';
|
||||||
|
import { toast } from 'react-toastify';
|
||||||
|
|
||||||
|
import mapMarkerImg from '../images/map_marker.svg';
|
||||||
|
import '../styles/create-orphanage.css';
|
||||||
|
import Sidebar from "../components/Sidebar";
|
||||||
|
import api from "../services/api";
|
||||||
|
|
||||||
|
export default function CreateOrphanage() {
|
||||||
|
const { isLoaded } = useJsApiLoader({
|
||||||
|
id: 'google-map-script',
|
||||||
|
googleMapsApiKey: process.env.REACT_APP_MAPS_API_KEY!
|
||||||
|
});
|
||||||
|
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
const [position, setPosition] = useState({ lat: 0, lng: 0 });
|
||||||
|
const [name, setName] = useState('');
|
||||||
|
const [about, setAbout] = useState('');
|
||||||
|
const [instructions, setInstructions] = useState('');
|
||||||
|
const [opening_hours, setOpeningHours] = useState('');
|
||||||
|
const [open_on_weekends, setOpenOnWeekends] = useState(true);
|
||||||
|
const [phone, setPhone] = useState('');
|
||||||
|
const [images, setImages] = useState<File[]>([]);
|
||||||
|
const [previewImages, setPreviewImages] = useState<string[]>([]);
|
||||||
|
|
||||||
|
function handleMapClick(event: google.maps.MapMouseEvent) {
|
||||||
|
const { latLng } = event;
|
||||||
|
if (latLng) {
|
||||||
|
setPosition({
|
||||||
|
lat: latLng.lat(),
|
||||||
|
lng: latLng.lng(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleSelectImages(event: ChangeEvent<HTMLInputElement>) {
|
||||||
|
if (!event.target.files) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const selectedImages = Array.from(event.target.files);
|
||||||
|
setImages(selectedImages);
|
||||||
|
|
||||||
|
const selectedImagesPreview = selectedImages.map(image => {
|
||||||
|
return URL.createObjectURL(image);
|
||||||
|
});
|
||||||
|
|
||||||
|
setPreviewImages(selectedImagesPreview);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleSubmit(event: FormEvent) {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
if (!name.trim()) {
|
||||||
|
toast.error('O campo "Nome" é obrigatório.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!about.trim()) {
|
||||||
|
toast.error('O campo "Sobre" é obrigatório.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!opening_hours.trim()) {
|
||||||
|
toast.error('O campo "Horário de funcionamento" é obrigatório.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (position.lat === 0) {
|
||||||
|
toast.error('Por favor, selecione a localização do orfanato no mapa.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (images.length === 0) {
|
||||||
|
toast.error('Por favor, adicione pelo menos uma foto do orfanato.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!phone.trim()) {
|
||||||
|
toast.error('O campo "Número de Whatsapp" é obrigatório.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { lat, lng } = position;
|
||||||
|
|
||||||
|
const data = new FormData();
|
||||||
|
data.append('name', name);
|
||||||
|
data.append('about', about);
|
||||||
|
data.append('latitude', String(lat));
|
||||||
|
data.append('longitude', String(lng));
|
||||||
|
data.append('instructions', instructions);
|
||||||
|
data.append('opening_hours', opening_hours);
|
||||||
|
data.append('open_on_weekends', String(open_on_weekends));
|
||||||
|
data.append('phone', phone);
|
||||||
|
|
||||||
|
images.forEach(image => {
|
||||||
|
data.append('images', image);
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
await api.post('orphanages', data);
|
||||||
|
toast.success('Cadastro realizado com sucesso!');
|
||||||
|
navigate('/app');
|
||||||
|
} catch (error) {
|
||||||
|
toast.error('Erro ao realizar o cadastro. Tente novamente.');
|
||||||
|
console.error('Failed to create orphanage:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isLoaded) {
|
||||||
|
return <div>Loading Map...</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div id="page-create-orphanage">
|
||||||
|
<Sidebar />
|
||||||
|
<main>
|
||||||
|
<form onSubmit={handleSubmit} className="create-orphanage-form">
|
||||||
|
<fieldset>
|
||||||
|
<legend>Dados</legend>
|
||||||
|
|
||||||
|
<GoogleMap
|
||||||
|
mapContainerStyle={{ width: '100%', height: 280 }}
|
||||||
|
center={{ lat: -23.9550537, lng: -46.3204442 }}
|
||||||
|
zoom={12}
|
||||||
|
onClick={handleMapClick}
|
||||||
|
>
|
||||||
|
{position.lat !== 0 && (
|
||||||
|
<Marker
|
||||||
|
position={{ lat: position.lat, lng: position.lng }}
|
||||||
|
icon={{
|
||||||
|
url: mapMarkerImg,
|
||||||
|
scaledSize: new window.google.maps.Size(58, 68),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</GoogleMap>
|
||||||
|
|
||||||
|
<div className="input-block">
|
||||||
|
<label htmlFor="name">Nome</label>
|
||||||
|
<input id="name" value={name} maxLength={50} onChange={e => setName(e.target.value)} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="input-block">
|
||||||
|
<label htmlFor="about">Sobre <span>Máximo de 300 caracteres</span></label>
|
||||||
|
<textarea id="about" maxLength={300} value={about} onChange={e => setAbout(e.target.value)} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="input-block">
|
||||||
|
<label htmlFor="phone">Número de Whatsapp</label>
|
||||||
|
<input
|
||||||
|
id="phone"
|
||||||
|
value={phone}
|
||||||
|
onChange={e => setPhone(e.target.value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="input-block">
|
||||||
|
<label htmlFor="images">Fotos</label>
|
||||||
|
<div className="images-container">
|
||||||
|
{previewImages.map(image => (
|
||||||
|
<img key={image} src={image} alt={name}/>
|
||||||
|
))}
|
||||||
|
<label htmlFor="image[]" className="new-image">
|
||||||
|
<FiPlus size={24} color="#15b6d6" />
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<input multiple onChange={handleSelectImages} type="file" id="image[]" />
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<legend>Visitação</legend>
|
||||||
|
<div className="input-block">
|
||||||
|
<label htmlFor="instructions">Instruções</label>
|
||||||
|
<textarea id="instructions" maxLength={300} value={instructions} onChange={e => setInstructions(e.target.value)} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="input-block">
|
||||||
|
<label htmlFor="opening_hours">Horário de funcionamento</label>
|
||||||
|
<input id="opening_hours" maxLength={20} value={opening_hours} onChange={e => setOpeningHours(e.target.value)} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="input-block">
|
||||||
|
<label htmlFor="open_on_weekends">Atende fim de semana</label>
|
||||||
|
<div className="button-select">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={open_on_weekends ? 'active' : ''}
|
||||||
|
onClick={() => setOpenOnWeekends(true)}
|
||||||
|
>
|
||||||
|
Sim
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={!open_on_weekends ? 'active' : ''}
|
||||||
|
onClick={() => setOpenOnWeekends(false)}
|
||||||
|
>
|
||||||
|
Não
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<button className="confirm-button" type="submit">
|
||||||
|
Confirmar
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
150
web/src/pages/Orphanage.tsx
Normal file
150
web/src/pages/Orphanage.tsx
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { FaWhatsapp } from "react-icons/fa";
|
||||||
|
import { FiClock, FiInfo } from "react-icons/fi";
|
||||||
|
import { useParams } from 'react-router-dom';
|
||||||
|
import { GoogleMap, useJsApiLoader, Marker } from "@react-google-maps/api";
|
||||||
|
|
||||||
|
import mapMarkerImg from '../images/map_marker.svg';
|
||||||
|
import '../styles/orphanage.css';
|
||||||
|
import Sidebar from '../components/Sidebar';
|
||||||
|
import api from "../services/api";
|
||||||
|
|
||||||
|
interface Orphanage {
|
||||||
|
latitude: number;
|
||||||
|
longitude: number;
|
||||||
|
name: string;
|
||||||
|
about: string;
|
||||||
|
instructions: string;
|
||||||
|
opening_hours: string;
|
||||||
|
open_on_weekends: boolean;
|
||||||
|
phone: string;
|
||||||
|
images: Array<{
|
||||||
|
id: number;
|
||||||
|
url: string;
|
||||||
|
}>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Orphanage() {
|
||||||
|
const { isLoaded } = useJsApiLoader({
|
||||||
|
id: 'google-map-script',
|
||||||
|
googleMapsApiKey: process.env.REACT_APP_MAPS_API_KEY!
|
||||||
|
});
|
||||||
|
|
||||||
|
const { id } = useParams();
|
||||||
|
const [orphanage, setOrphanage] = useState<Orphanage>();
|
||||||
|
const [activeImageIndex, setActiveImageIndex] = useState(0);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
api.get(`orphanages/${id}`).then(response => {
|
||||||
|
setOrphanage(response.data);
|
||||||
|
});
|
||||||
|
}, [id]);
|
||||||
|
|
||||||
|
if (!orphanage || !isLoaded) {
|
||||||
|
return <p>Carregando...</p>;
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatPhoneNumberForWhatsApp(phoneNumber: string) {
|
||||||
|
const digitsOnly = phoneNumber.replace(/\D/g, '');
|
||||||
|
return `55${digitsOnly}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div id="page-orphanage">
|
||||||
|
<Sidebar />
|
||||||
|
<main>
|
||||||
|
<div className="orphanage-details">
|
||||||
|
<img src={orphanage.images[activeImageIndex].url} alt={orphanage.name} />
|
||||||
|
|
||||||
|
<div className="images">
|
||||||
|
{orphanage.images.map((image, index) => (
|
||||||
|
<button
|
||||||
|
key={image.id}
|
||||||
|
className={activeImageIndex === index ? 'active' : ''}
|
||||||
|
type="button"
|
||||||
|
onClick={() => setActiveImageIndex(index)}
|
||||||
|
>
|
||||||
|
<img src={image.url} alt={orphanage.name} />
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="orphanage-details-content">
|
||||||
|
<h1>{orphanage.name}</h1>
|
||||||
|
<p>{orphanage.about}</p>
|
||||||
|
|
||||||
|
<div className="map-container">
|
||||||
|
<GoogleMap
|
||||||
|
mapContainerStyle={{ width: '100%', height: 280, borderRadius: '20px' }}
|
||||||
|
center={{ lat: orphanage.latitude, lng: orphanage.longitude }}
|
||||||
|
zoom={16}
|
||||||
|
options={{
|
||||||
|
draggable: false,
|
||||||
|
zoomControl: false,
|
||||||
|
scrollwheel: false,
|
||||||
|
disableDoubleClickZoom: true,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Marker
|
||||||
|
position={{ lat: orphanage.latitude, lng: orphanage.longitude }}
|
||||||
|
icon={{
|
||||||
|
url: mapMarkerImg,
|
||||||
|
scaledSize: new window.google.maps.Size(58, 68),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</GoogleMap>
|
||||||
|
<footer>
|
||||||
|
<a
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
href={`https://www.google.com/maps/dir/?api=1&destination=$...${orphanage.latitude},${orphanage.longitude}`}
|
||||||
|
>
|
||||||
|
Ver rotas no Google Maps
|
||||||
|
</a>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<h2>Instruções para visita</h2>
|
||||||
|
<p>{orphanage.instructions}</p>
|
||||||
|
|
||||||
|
<div className="open-details">
|
||||||
|
<div className="hour">
|
||||||
|
<FiClock size={32} color="#15B6D6" />
|
||||||
|
Segunda à Sexta <br />
|
||||||
|
{orphanage.opening_hours}
|
||||||
|
</div>
|
||||||
|
{orphanage.open_on_weekends ? (
|
||||||
|
<div className="open-on-weekends">
|
||||||
|
<FiInfo size={32} color="#39CC83" />
|
||||||
|
Atendemos <br />
|
||||||
|
fim de semana
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="open-on-weekends dont-open">
|
||||||
|
<FiInfo size={32} color="#FF669D" />
|
||||||
|
Não atendemos <br />
|
||||||
|
fim de semana
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<a
|
||||||
|
href={`https://wa.me/${formatPhoneNumberForWhatsApp(orphanage.phone)}`}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
style={{ textDecoration: 'none' }}
|
||||||
|
>
|
||||||
|
<button className="contact-button">
|
||||||
|
<FaWhatsapp size={20} color="#FFF" />
|
||||||
|
Entrar em contato
|
||||||
|
</button>
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
175
web/src/styles/create-orphanage.css
Normal file
175
web/src/styles/create-orphanage.css
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
#page-create-orphanage {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
#page-create-orphanage main {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
form.create-orphanage-form {
|
||||||
|
width: 700px;
|
||||||
|
margin: 64px auto;
|
||||||
|
|
||||||
|
background: #FFFFFF;
|
||||||
|
border: 1px solid #D3E2E5;
|
||||||
|
border-radius: 20px;
|
||||||
|
|
||||||
|
padding: 64px 80px;
|
||||||
|
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
form.create-orphanage-form .leaflet-container {
|
||||||
|
border-radius: 20px;
|
||||||
|
border: 1px solid #D3E2E5;
|
||||||
|
margin-bottom: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
form.create-orphanage-form fieldset {
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
form.create-orphanage-form fieldset + fieldset {
|
||||||
|
margin-top: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
form.create-orphanage-form fieldset legend {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
font-size: 32px;
|
||||||
|
line-height: 34px;
|
||||||
|
color: #5C8599;
|
||||||
|
font-weight: 700;
|
||||||
|
|
||||||
|
border-bottom: 1px solid #D3E2E5;
|
||||||
|
margin-bottom: 40px;
|
||||||
|
padding-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
form.create-orphanage-form .input-block {
|
||||||
|
margin-top: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
form.create-orphanage-form .input-block label {
|
||||||
|
display: flex;
|
||||||
|
color: #8FA7B3;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
line-height: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
form.create-orphanage-form .input-block label span {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #8FA7B3;
|
||||||
|
margin-left: 24px;
|
||||||
|
line-height: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
form.create-orphanage-form .input-block input,
|
||||||
|
form.create-orphanage-form .input-block textarea {
|
||||||
|
width: 100%;
|
||||||
|
background: #F5F8FA;
|
||||||
|
border: 1px solid #D3E2E5;
|
||||||
|
border-radius: 20px;
|
||||||
|
outline: none;
|
||||||
|
color: #5C8599;
|
||||||
|
}
|
||||||
|
|
||||||
|
form.create-orphanage-form .input-block input {
|
||||||
|
height: 64px;
|
||||||
|
padding: 0 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
form.create-orphanage-form .input-block textarea {
|
||||||
|
min-height: 120px;
|
||||||
|
max-height: 240px;
|
||||||
|
resize: vertical;
|
||||||
|
padding: 16px;
|
||||||
|
line-height: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- NEW STYLES FOR IMAGE UPLOAD --- */
|
||||||
|
form.create-orphanage-form .input-block input[type="file"] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
form.create-orphanage-form .input-block .images-container {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(5, 1fr);
|
||||||
|
grid-gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
form.create-orphanage-form .input-block .images-container img {
|
||||||
|
width: 100%;
|
||||||
|
height: 96px;
|
||||||
|
object-fit: cover;
|
||||||
|
border-radius: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
form.create-orphanage-form .input-block .images-container .new-image {
|
||||||
|
height: 96px;
|
||||||
|
background: #F5F8FA;
|
||||||
|
border: 1px dashed #96D2F0;
|
||||||
|
border-radius: 20px;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
/* --- END NEW STYLES --- */
|
||||||
|
|
||||||
|
|
||||||
|
form.create-orphanage-form .input-block .button-select {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
form.create-orphanage-form .input-block .button-select button {
|
||||||
|
height: 64px;
|
||||||
|
background: #F5F8FA;
|
||||||
|
border: 1px solid #D3E2E5;
|
||||||
|
color: #5C8599;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
form.create-orphanage-form .input-block .button-select button.active {
|
||||||
|
background: #EDFFF6;
|
||||||
|
border: 1px solid #A1E9C5;
|
||||||
|
color: #37C77F;
|
||||||
|
}
|
||||||
|
|
||||||
|
form.create-orphanage-form .input-block .button-select button:first-child {
|
||||||
|
border-radius: 20px 0px 0px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
form.create-orphanage-form .input-block .button-select button:last-child {
|
||||||
|
border-radius: 0 20px 20px 0;
|
||||||
|
border-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
form.create-orphanage-form button.confirm-button {
|
||||||
|
margin-top: 64px;
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
height: 64px;
|
||||||
|
border: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
background: #3CDC8C;
|
||||||
|
border-radius: 20px;
|
||||||
|
color: #FFFFFF;
|
||||||
|
font-weight: 800;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
form.create-orphanage-form button.confirm-button svg {
|
||||||
|
margin-right: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
form.create-orphanage-form button.confirm-button:hover {
|
||||||
|
background: #36CF82;
|
||||||
|
}
|
||||||
168
web/src/styles/orphanage.css
Normal file
168
web/src/styles/orphanage.css
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
#page-orphanage {
|
||||||
|
display: flex;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
#page-orphanage main {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.orphanage-details {
|
||||||
|
width: 700px;
|
||||||
|
margin: 64px auto;
|
||||||
|
|
||||||
|
background: #FFFFFF;
|
||||||
|
border: 1px solid #D3E2E5;
|
||||||
|
border-radius: 20px;
|
||||||
|
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.orphanage-details > img {
|
||||||
|
width: 100%;
|
||||||
|
height: 300px;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.orphanage-details .images {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(6 ,1fr);
|
||||||
|
column-gap: 16px;
|
||||||
|
|
||||||
|
margin: 16px 40px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.orphanage-details .images button {
|
||||||
|
border: 0;
|
||||||
|
height: 88px;
|
||||||
|
background: none;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 20px;
|
||||||
|
overflow: hidden;
|
||||||
|
outline: none;
|
||||||
|
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.orphanage-details .images button.active {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.orphanage-details .images button img {
|
||||||
|
width: 100%;
|
||||||
|
height: 88px;
|
||||||
|
object-fit: cover;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.orphanage-details .orphanage-details-content {
|
||||||
|
padding: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.orphanage-details .orphanage-details-content h1 {
|
||||||
|
color: #4D6F80;
|
||||||
|
font-size: 54px;
|
||||||
|
line-height: 54px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.orphanage-details .orphanage-details-content p {
|
||||||
|
line-height: 28px;
|
||||||
|
color: #5C8599;
|
||||||
|
margin-top: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.orphanage-details .orphanage-details-content .map-container {
|
||||||
|
margin-top: 64px;
|
||||||
|
background: #E6F7FB;
|
||||||
|
border: 1px solid #B3DAE2;
|
||||||
|
border-radius: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.orphanage-details .orphanage-details-content .map-container footer {
|
||||||
|
padding: 20px 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.orphanage-details .orphanage-details-content .map-container footer a {
|
||||||
|
line-height: 24px;
|
||||||
|
color: #0089A5;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.orphanage-details .orphanage-details-content .map-container .leaflet-container {
|
||||||
|
border-bottom: 1px solid #DDE3F0;
|
||||||
|
border-radius: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.orphanage-details .orphanage-details-content hr {
|
||||||
|
width: 100%;
|
||||||
|
height: 1px;
|
||||||
|
border: 0;
|
||||||
|
background: #D3E2E6;
|
||||||
|
margin: 64px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.orphanage-details .orphanage-details-content h2 {
|
||||||
|
font-size: 36px;
|
||||||
|
line-height: 46px;
|
||||||
|
color: #4D6F80;
|
||||||
|
}
|
||||||
|
|
||||||
|
.orphanage-details .orphanage-details-content .open-details {
|
||||||
|
margin-top: 24px;
|
||||||
|
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
column-gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.orphanage-details .orphanage-details-content .open-details div {
|
||||||
|
padding: 32px 24px;
|
||||||
|
border-radius: 20px;
|
||||||
|
line-height: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.orphanage-details .orphanage-details-content .open-details div svg {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.orphanage-details .orphanage-details-content .open-details div.hour {
|
||||||
|
background: linear-gradient(149.97deg, #E6F7FB 8.13%, #FFFFFF 92.67%);
|
||||||
|
border: 1px solid #B3DAE2;
|
||||||
|
color: #5C8599;
|
||||||
|
}
|
||||||
|
|
||||||
|
.orphanage-details .orphanage-details-content .open-details div.open-on-weekends {
|
||||||
|
background: linear-gradient(154.16deg, #EDFFF6 7.85%, #FFFFFF 91.03%);
|
||||||
|
border: 1px solid #A1E9C5;
|
||||||
|
color: #37C77F;
|
||||||
|
}
|
||||||
|
|
||||||
|
.orphanage-details .orphanage-details-content button.contact-button {
|
||||||
|
margin-top: 64px;
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
height: 64px;
|
||||||
|
border: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
background: #3CDC8C;
|
||||||
|
border-radius: 20px;
|
||||||
|
color: #FFFFFF;
|
||||||
|
font-weight: 800;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.orphanage-details .orphanage-details-content button.contact-button svg {
|
||||||
|
margin-right: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.orphanage-details .orphanage-details-content button.contact-button:hover {
|
||||||
|
background: #36CF82;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user