Skip to content

Commit

Permalink
updated endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
ctkqiang committed Nov 3, 2024
1 parent 1aa5be4 commit b3c10e5
Show file tree
Hide file tree
Showing 6 changed files with 276 additions and 4 deletions.
9 changes: 8 additions & 1 deletion public/index.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@
<li class="nav-item">
<a class="nav-link" href="#features">Features</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/public/how-to-use-aed">How To Use AED</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#about">About</a>
</li>
Expand All @@ -70,7 +73,11 @@
<div class="col-lg-6 animate__animated animate__fadeInLeft">
<h1 class="display-4 fw-bold mb-4">Find AED Locations in Penang</h1>
<p class="lead mb-4">Quick access to life-saving Automated External Defibrillators (AED) locations across Penang. Every second counts in an emergency.</p>
<button class="btn btn-light btn-lg pulse">Find Nearest AED</button>

<a href="/public/locate-aed">
<button class="btn btn-light btn-lg pulse">Find Nearest AED</button>
</a>

</div>
<div class="col-lg-6 animate__animated animate__fadeInRight">
<img src="/assets/screenshot.png" alt="AED Location Map" class="img-fluid rounded shadow">
Expand Down
72 changes: 72 additions & 0 deletions public/pages/aed.ejs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><%= title %> - AED Locations</title>
<!-- Leaflet CSS -->
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css">
<style>
#map {
height: 80vh;
width: 100%;
}
.container {
padding: 20px;
}
.popup-content img {
max-width: 200px;
margin-top: 10px;
}
</style>
</head>
<body>
<div class="container">
<h1>AED Locations in Penang</h1>
<div id="map"></div>
</div>

<!-- Leaflet JS -->
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
<script>
// Initialize the map
const map = L.map('map').setView([5.4164, 100.3327], 12); // Penang coordinates
// Add OpenStreetMap tiles
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
// Fetch AED data from your API
fetch('/api/aed/all')
.then(response => response.json())
.then(data => {
data.forEach(aed => {
// Convert coordinates from strings to numbers
const lat = parseFloat(aed.coordinates[0]);
const lng = parseFloat(aed.coordinates[1]);
// Create popup content including images if available
let popupContent = `
<div class="popup-content">
<strong>${aed.name}</strong><br>
Address: ${aed.address}<br>
`;
// Add images if available
if (aed.images_url && aed.images_url.length > 0) {
popupContent += `<img src="${aed.images_url[0]}" alt="Location image">`;
}
popupContent += '</div>';
// Create marker for each AED location
L.marker([lat, lng])
.bindPopup(popupContent)
.addTo(map);
});
})
.catch(error => console.error('Error loading AED data:', error));
</script>
</body>
</html>
136 changes: 136 additions & 0 deletions public/pages/how-to-use-aed.ejs
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title><%= title %> - How to Use an AED</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
<style>
.hero-section {
background: linear-gradient(135deg, #1e88e5, #1565c0);
color: white;
padding: 80px 0 20px 0;
}
.content-section {
padding: 40px 0;
}
.step-card {
border-left: 4px solid #1e88e5;
margin-bottom: 20px;
padding: 20px;
background: #fff;
border-radius: 5px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.step-number {
color: #1e88e5;
font-size: 1.2rem;
font-weight: bold;
margin-bottom: 10px;
}
.important-tips {
background: #f8f9fa;
padding: 20px;
border-radius: 5px;
margin-top: 30px;
}
.icon-large {
font-size: 2rem;
color: #1e88e5;
margin-bottom: 1rem;
}
</style>
</head>
<body>
<!-- Navigation -->
<nav class="navbar navbar-expand-lg navbar-dark bg-dark fixed-top">
<div class="container">
<a class="navbar-brand" href="/"><i class="bi bi-heart-pulse"></i> <%= title %></a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav ms-auto">
<li class="nav-item">
<a class="nav-link" href="/public/main">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/public/pages/contact">Contact</a>
</li>
</ul>
</div>
</div>
</nav>

<!-- Hero Section -->
<section class="hero-section">
<div class="container">
<div class="row">
<div class="col-lg-12 text-center animate__animated animate__fadeInDown">
<h1 class="display-4 fw-bold mb-4">How to Use an AED</h1>
<p class="lead">A Step-by-Step Guide for Emergency Situations</p>
</div>
</div>
</div>
</section>

<!-- Content Section -->
<section class="content-section">
<div class="container">
<div class="row justify-content-center">
<div class="col-lg-8 animate__animated animate__fadeIn">
<!-- Step 1 -->
<div class="step-card">
<div class="step-number"><i class="bi bi-telephone-fill"></i> Step 1: Call Emergency Services</div>
<p>Before using the AED, ensure someone has called emergency services or do it yourself if you are alone.</p>
</div>

<!-- Step 2 -->
<div class="step-card">
<div class="step-number"><i class="bi bi-shield-check"></i> Step 2: Check the Scene</div>
<p>Ensure the environment is safe for both you and the victim. Make sure the area is free of hazards (e.g., water, traffic).</p>
</div>

<!-- Step 3 -->
<div class="step-card">
<div class="step-number"><i class="bi bi-person-check"></i> Step 3: Check the Victim</div>
<ul>
<li>Assess the victim's responsiveness by tapping them and shouting, "Are you okay?"</li>
<li>If the victim is unresponsive and not breathing or only gasping, proceed to the next steps.</li>
</ul>
</div>

<!-- Additional steps continue with the same pattern -->

<!-- Important Tips Section -->
<div class="important-tips">
<h4 class="mb-4"><i class="bi bi-exclamation-triangle"></i> Important Tips</h4>
<ul>
<li>Do not use the AED in water or while the victim is in water.</li>
<li>Make sure the pads do not touch each other.</li>
<li>If there are signs of life, place the victim in the recovery position and monitor them.</li>
</ul>
</div>

<!-- Training Section -->
<div class="step-card mt-4">
<h4><i class="bi bi-mortarboard"></i> Training</h4>
<p>While AEDs are designed for public use, taking a CPR and AED training course can greatly enhance your confidence and effectiveness in an emergency situation. Organizations such as the American Heart Association or Red Cross offer classes that teach these skills.</p>
</div>
</div>
</div>
</div>
</section>

<!-- Footer -->
<footer class="bg-dark text-white py-4 mt-5">
<div class="container text-center">
<p class="mb-0">&copy; 2024 <%= title %>. All rights reserved.</p>
</div>
</footer>

<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
50 changes: 50 additions & 0 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import cors from 'cors';
import aed from './routes/aed';
import helmet from 'helmet';
import * as path from 'path';
import { GetAED } from './controllers/get_data';
import { AED } from './models/aed_model';


/**
* @description 主应用程序实例配置文件
Expand All @@ -22,6 +25,40 @@ app.use(bodyParser.json()); // 解析 JSON 格
app.disable('x-powered-by'); // 移除 X-Powered-By 标头,提高安全性
app.use(cors()); // 允许跨域请求,支持前后端分离
app.use(helmet()); // 添加安全相关的 HTTP 头,增强应用安全性
app.use(
helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
scriptSrc: [
"'self'",
"'unsafe-inline'",
"'unsafe-eval'",
"cdn.jsdelivr.net",
"unpkg.com",
"*.bootstrap.com",
],
styleSrc: [
"'self'",
"'unsafe-inline'",
"cdn.jsdelivr.net",
"*.bootstrap.com",
"cdnjs.cloudflare.com",
"*.bootstrapcdn.com",
],
imgSrc: ["'self'", "data:", "https:", "blob:"],
connectSrc: ["'self'", "https:"],
fontSrc: ["'self'", "https:", "data:", "cdnjs.cloudflare.com"],
objectSrc: ["'none'"],
mediaSrc: ["'self'"],
frameSrc: ["'self'"],
tileSrc: ["'self'", "https://*.tile.openstreetmap.org"],
},
},
crossOriginEmbedderPolicy: false,
crossOriginResourcePolicy: false,
})
);

/**
* 配置应用程序路由
Expand Down Expand Up @@ -58,6 +95,19 @@ app.get('/public/main', (req, res) => {
res.render('index', { title: APP_NAME });
});

app.get('/public/locate-aed', (req, res) => {
const aedData = GetAED<AED[]>();

res.render('pages/aed', {
title: APP_NAME,
aedData: aedData || []
});
});

app.get('/public/how-to-use-aed', (req, res) => {
res.render('pages/how-to-use-aed', { title: APP_NAME });
});

app.get('/public/pages/contact', (req, res) => {
res.render('pages/contact', { title: APP_NAME });
});
Expand Down
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@ if (PORT === "443")
}

app.listen(PORT, () => {
console.log(`AED Server is running on http://localhost:${PORT}`);
console.log(`AED 服务器正在运行,访问地址: http://localhost:${PORT}`);
});
11 changes: 9 additions & 2 deletions src/routes/aed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,15 @@ const aed = Router();
aed.get('/all', (req, res) => {
const data = GetAED<AED>();

console.info(`GET::[/aed/all]`); // 记录请求日志
res.send(data); // 发送响应数据
if (data)
{
console.info(`GET::[/aed/all]`); // 记录请求日志
res.send(data); // 发送响应数据
}
else
{
res.status(404).json({ error: 'No AED data found' });
}
});

export default aed;

0 comments on commit b3c10e5

Please sign in to comment.