The user wants me to create a web application based on the detailed specification provided. The app should:
- Include a landing homepage accessible via QR code (the QR code itself can be generated later; I will make the main page available)
- Display a welcome message and instructions
- Provide a form for personal information input (name, age, gender, and possibly others)
- Include an ergonomic assessment using ROSA (using the existing ergonomic assessment form we created)
- Show recommendations based on ROSA scores and personal info
- Allow saving or displaying a summary of assessments.
I will create a single HTML
file with
:
- A landing homepage with welcome/instruction section
- A personal info form
- The ROSA ergonomic assessment form (from previous version with images)
- After assessment, show recommendations and summary
- Simple JS navigation between sections/pages
- Save data in localStorage for session persistence (client-side only)
- All inline CSS and JavaScript; no backend
- Add instructions/manual section as per requirements
I will now create this full single-page ergonomic assessment web app with the required features.
`rosa_ergonomic_assessment_app.html`
```html
<!DOCTYPE html>
<html lang="th">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>โปรแกรมประเมินท่าทางการยศาสตร์ด้วย ROSA</title>
<style>
body {
font-family: "Kanit", Arial, sans-serif;
margin: 20px;
background-color: #f5f7fa;
color: #333;
}
h1, h2 {
color: #005a9c;
text-align: center;
}
h3 {
color: #004477;
}
.container {
max-width: 700px;
margin: 0 auto;
background: white;
padding: 20px 25px;
border-radius: 8px;
box-shadow: 0 0 12px rgba(0,0,0,0.12);
}
.hidden {
display: none;
}
label {
display: block;
margin: 12px 0 6px;
font-weight: 600;
}
input[type="text"], input[type="number"], select {
width: 100%;
padding: 8px 10px;
border-radius: 4px;
border: 1px solid #ccc;
box-sizing: border-box;
font-size: 1rem;
}
input[type="radio"], input[type="checkbox"] {
margin-right: 8px;
vertical-align: middle;
}
.inline-label {
display: inline-block;
margin-right: 20px;
}
button {
background-color: #005a9c;
color: white;
border: none;
padding: 12px 25px;
border-radius: 4px;
font-size: 16px;
cursor: pointer;
margin: 20px 0;
display: block;
width: 100%;
}
button:hover {
background-color: #004077;
}
nav {
text-align: center;
margin-bottom: 10px;
}
nav button {
margin: 0 5px;
width: auto;
padding: 8px 18px;
font-size: 14px;
}
.section-image {
max-width: 120px;
float: right;
margin-left: 12px;
border: 1px solid #ccc;
border-radius: 6px;
background: #fff;
padding: 5px;
box-shadow: 0 0 5px rgba(0,0,0,0.1);
}
fieldset {
border: 1px solid #ddd;
margin-bottom: 25px;
padding: 15px 15px 25px 15px;
border-radius: 6px;
position: relative;
overflow: auto;
clear: both;
}
legend {
font-weight: bold;
padding: 0 10px;
color: #005a9c;
}
.summary {
background: #e0f0ff;
padding: 15px;
border-radius: 6px;
border: 1px solid #005a9c;
margin-top: 20px;
white-space: pre-line;
}
.footer-text {
font-size: 0.9rem;
color: #666;
text-align: center;
margin-top: 35px;
}
</style>
</head>
<body>
<div class="container">
<!-- Navigation -->
<nav>
<button type="button" id="navHome">หน้าแรก</button>
<button type="button" id="navPersonal">ข้อมูลส่วนตัว</button>
<button type="button" id="navAssessment">ประเมิน ROSA</button>
<button type="button" id="navManual">คู่มือการใช้งาน</button>
</nav>
<!-- Home / Welcome Section -->
<section id="sectionHome">
<h1>ยินดีต้อนรับสู่โปรแกรมประเมินท่าทางการยศาสตร์ด้วย ROSA</h1>
<p>
โปรแกรมนี้ช่วยให้คุณประเมินท่าทางการทำงานและความเสี่ยงทางด้านการยศาสตร์ได้อย่างง่ายดาย เพียงกรอกข้อมูลส่วนตัวและทำแบบประเมินท่าทาง แล้วรับคำแนะนำเพื่อปรับปรุงท่าทางการทำงานให้เหมาะสม
</p>
<p><strong>คำแนะนำเบื้องต้น:</strong></p>
<ul>
<li>กรอกข้อมูลส่วนตัวให้ครบถ้วนเพื่อการประเมินที่แม่นยำ</li>
<li>ทำแบบประเมินท่าทางตามคำแนะนำในหน้าประเมิน</li>
<li>อ่านคำแนะนำหลังการประเมินเพื่อปรับปรุงท่าทางการทำงาน</li>
</ul>
<p>คุณสามารถใช้เมนูด้านบนเพื่อเข้าใช้งานส่วนต่าง ๆ ของโปรแกรมได้</p>
</section>
<!-- Personal Information Section -->
<section id="sectionPersonal" class="hidden">
<h2>กรอกข้อมูลส่วนตัว</h2>
<form id="personalForm">
<label for="name">ชื่อ-นามสกุล</label>
<input type="text" id="name" name="name" placeholder="กรอกชื่อของคุณ" required />
<label for="age">อายุ</label>
<input type
="number" id
="age" name
="age" min="10" max="100" placeholder
="กรอกอายุ (ปี)" required
/>
<label>เพศ</label>
<div>
<label class="inline-label"><input type="radio" name="gender" value="ชาย" required /> ชาย</label>
<label class="inline-label"><input type="radio" name="gender" value="หญิง" /> หญิง</label>
<label class="inline-label"><input type="radio" name="gender" value="อื่นๆ" /> อื่นๆ</label>
</div>
<label for="job">อาชีพ (ถ้ามี)</label>
<input type="text" id="job" name="job" placeholder="例: พนักงานออฟฟิศ, นักศึกษา" />
<label for="additionalInfo">ข้อมูลเพิ่มเติม (ถ้ามี)</label>
<input type="text" id="additionalInfo" name="additionalInfo" placeholder="กรอกข้อมูลเพิ่มเติม เช่น ปัญหาสุขภาพ" />
<button type="submit">บันทึกข้อมูลส่วนตัว</button>
</form>
</section>
<!-- ROSA Assessment Section -->
<section id="sectionAssessment" class="hidden">
<h2>แบบประเมินท่าทางการยศาสตร์ (ROSA)</h2>
<form id="rosaForm">
<fieldset class="chair">
<legend>การประเมินเก้าอี้ (Chair Assessment)</legend>
<img src="https://u...content-available-to-author-only...a.org/wikipedia/commons/thumb/c/cb/Office_chair_icon.svg/120px-Office_chair_icon.svg.png" alt="Chair" class="section-image" />
<label for="seatHeight">ความสูงของที่นั่ง</label>
<select id="seatHeight" name="seatHeight" required>
<option value="">-- เลือก --</option>
<option value="ต่ำ (ต่ำกว่า 40cm)">ต่ำ (ต่ำกว่า 40cm)</option>
<option value="ปานกลาง (40-50 cm)">ปานกลาง (40-50 cm)</option>
<option value="สูง (สูงกว่า 50 cm)">สูง (สูงกว่า 50 cm)</option>
</select>
<label>มีพนักพิงหลังหรือไม่</label>
<div class="inline-label">
<input type="radio" id="backSupportYes" name="backSupport" value="มี" required />
<label for="backSupportYes">มี</label>
</div>
<div class="inline-label">
<input type="radio" id="backSupportNo" name="backSupport" value="ไม่มี" />
<label for="backSupportNo">ไม่มี</label>
</div>
<label>มีที่วางแขนหรือไม่</label>
<div class="inline-label">
<input type="radio" id="armrestsYes" name="armrests" value="มี" required />
<label for="armrestsYes">มี</label>
</div>
<div class="inline-label">
<input type="radio" id="armrestsNo" name="armrests" value="ไม่มี" />
<label for="armrestsNo">ไม่มี</label>
</div>
</fieldset>
<fieldset class="monitor">
<legend>การประเมินจอภาพและโต๊ะทำงาน (Monitor and Desk)</legend>
<img src="https://u...content-available-to-author-only...a.org/wikipedia/commons/thumb/d/df/Desktop_monitor_icon.svg/120px-Desktop_monitor_icon.svg.png" alt="Monitor and Desk" class="section-image" />
<label for="monitorHeight">ระดับความสูงของจอภาพ</label>
<select id="monitorHeight" name="monitorHeight" required>
<option value="">-- เลือก --</option>
<option value="ต่ำกว่าระดับสายตา">ต่ำกว่าระดับสายตา</option>
<option value="ระดับสายตา">ระดับสายตา</option>
<option value="สูงกว่าระดับสายตา">สูงกว่าระดับสายตา</option>
</select>
<label for="monitorDistance">ระยะห่างของจอภาพจากตา</label>
<select id="monitorDistance" name="monitorDistance" required>
<option value="">-- เลือก --</option>
<option value="ใกล้เกินไป (< 40 cm)">ใกล้เกินไป (< 40 cm)</option>
<option value="เหมาะสม (40-75 cm)">เหมาะสม (40-75 cm)</option>
<option value="ห่างเกินไป (> 75 cm)">ห่างเกินไป (> 75 cm)</option>
</select>
<label for="deskHeight">ความสูงของโต๊ะทำงาน</label>
<select id="deskHeight" name="deskHeight" required>
<option value="">-- เลือก --</option>
<option value="ต่ำ (ต่ำกว่า 68 cm)">ต่ำ (ต่ำกว่า 68 cm)</option>
<option value="เหมาะสม (68-75 cm)">เหมาะสม (68-75 cm)</option>
<option value="สูง (สูงกว่า 75 cm)">สูง (สูงกว่า 75 cm)</option>
</select>
</fieldset>
<fieldset class="keyboard">
<legend>การประเมินคีย์บอร์ดและเมาส์ (Keyboard and Mouse)</legend>
<img src="https://u...content-available-to-author-only...a.org/wikipedia/commons/thumb/3/3b/Computer_keyboard_font_awesome.svg/120px-Computer_keyboard_font_awesome.svg.png" alt="Keyboard and Mouse" class="section-image" />
<label>ตำแหน่งคีย์บอร์ด</label>
<div class="inline-label">
<input type="radio" id="keyboardFlat" name="keyboardPosition" value="แบนราบ" required />
<label for="keyboardFlat">แบนราบ</label>
</div>
<div class="inline-label">
<input type="radio" id="keyboardTilted" name="keyboardPosition" value="เอียง" />
<label for="keyboardTilted">เอียง</label>
</div>
<label>การใช้เมาส์</label>
<div class="inline-label">
<input type="radio" id="mouseLow" name="mouseUse" value="ใช้น้อย" required />
<label for="mouseLow">ใช้น้อย</label>
</div>
<div class="inline-label">
<input type="radio" id="mouseMedium" name="mouseUse" value="ใช้ปานกลาง" />
<label for="mouseMedium">ใช้ปานกลาง</label>
</div>
<div class="inline-label">
<input type="radio" id="mouseHigh" name="mouseUse" value="ใช้มาก" />
<label for="mouseHigh">ใช้มาก</label>
</div>
</fieldset>
<fieldset class="posture">
<legend>ท่าทางร่างกาย (Body Posture)</legend>
<img src="https://u...content-available-to-author-only...a.org/wikipedia/commons/thumb/1/12/Ergonomic_seated_posture.svg/120px-Ergonomic_seated_posture.svg.png" alt="Body Posture" class="section-image" />
<label for="neckAngle">มุมของคอ</label>
<select id="neckAngle" name="neckAngle" required>
<option value="">-- เลือก --</option>
<option value="เป็นกลาง (0-10°)">เป็นกลาง (0-10°)</option>
<option value="ปานกลาง (11-20°)">ปานกลาง (11-20°)</option>
<option value="มาก (21° ขึ้นไป)">มาก (21° ขึ้นไป)</option>
</select>
<label for="backAngle">มุมของหลัง</label>
<select id="backAngle" name="backAngle" required>
<option value="">-- เลือก --</option>
<option value="ตรง (75° - 90°)">ตรง (75° - 90°)</option>
<option value="โน้มไปข้างหน้า (45° - 75°)">โน้มไปข้างหน้า (45° - 75°)</option>
<option value="กดหลัง (ต่ำกว่า 45°)">กดหลัง (ต่ำกว่า 45°)</option>
</select>
<label for="armPosition">ตำแหน่งแขน</label>
<select id="armPosition" name="armPosition" required>
<option value="">-- เลือก --</option>
<option value="ชิดลำตัว">ชิดลำตัว</option>
<option value="ยื่นไปข้างหน้า">ยื่นไปข้างหน้า</option>
<option value="ยกขึ้นเหนือโต๊ะ">ยกขึ้นเหนือโต๊ะ</option>
</select>
</fieldset>
<button type="submit">ประเมินผล</button>
</form>
<div id="assessmentSummary" class="summary hidden"></div>
</section>
<!-- User Manual Section -->
<section id="sectionManual" class="hidden">
<h2>คู่มือการใช้งาน</h2>
<p>ในหน้านี้คุณจะพบคำอธิบายขั้นตอนการใช้งานโปรแกรมประเมินท่าทางการยศาสตร์ด้วย ROSA</p>
<ul>
<li><strong>กรอกข้อมูลส่วนตัว:</strong> ให้กรอกข้อมูลพื้นฐาน เช่น ชื่อ อายุ เพศ และข้อมูลอื่นๆ เพื่อใช้ในการประเมินความเสี่ยง</li>
<li><strong>แบบประเมิน ROSA:</strong> ทำแบบประเมินตามคำแนะนำ เช่น ตำแหน่งเก้าอี้ ระดับจอภาพ และท่าทางร่างกาย</li>
<li><strong>การดูผลลัพธ์:</strong> หลังจากส่งแบบประเมิน โปรแกรมจะแสดงผลการประเมินและคำแนะนำด้านการปรับปรุงท่าทาง</li>
<li><strong>ความปลอดภัยข้อมูล:</strong> ข้อมูลของคุณจะถูกเก็บเป็นความลับและไม่ถูกเปิดเผยต่อบุคคลภายนอก</li>
</ul>
<p>หากมีคำถามเพิ่มเติม สามารถติดต่อเจ้าหน้าที่หรือผู้ดูแลระบบเพื่อขอความช่วยเหลือได้</p>
</section>
<div class="footer-text">
© 2024 โปรแกรมประเมินท่าทางการยศาสตร์ ROSA
</div>
</div>
<script>
// Navigation buttons
const navHome = document.getElementById('navHome');
const navPersonal = document.getElementById('navPersonal');
const navAssessment = document.getElementById('navAssessment');
const navManual = document.getElementById('navManual');
// Sections
const sectionHome = document.getElementById('sectionHome');
const sectionPersonal = document.getElementById('sectionPersonal');
const sectionAssessment = document.getElementById('sectionAssessment');
const sectionManual = document.getElementById('sectionManual');
function showSection(section) {
// Hide all
sectionHome.classList.add('hidden');
sectionPersonal.classList.add('hidden');
sectionAssessment.classList.add('hidden');
sectionManual.classList.add('hidden');
// Show chosen
section.classList.remove('hidden');
window.scrollTo(0,0);
}
navHome.addEventListener('click', () => showSection(sectionHome));
navPersonal.addEventListener('click', () => showSection(sectionPersonal));
navAssessment.addEventListener('click', () => {
// Only allow access if personal info saved
if (!localStorage.getItem('personalInfo')) {
alert('กรุณากรอกและบันทึกข้อมูลส่วนตัวก่อนทำแบบประเมินท่าทาง');
showSection(sectionPersonal);
return;
}
showSection(sectionAssessment);
});
navManual.addEventListener('click', () => showSection(sectionManual));
// Personal info form submit
const personalForm = document.getElementById('personalForm');
personalForm.addEventListener('submit', function(event) {
event.preventDefault();
const data = {
name
: personalForm
.name
.value
.trim(), age: personalForm.age.value,
gender: personalForm.gender.value,
job
: personalForm
.job
.value
.trim(), additionalInfo
: personalForm
.additionalInfo
.value
.trim() };
// Simple validation (already required in inputs)
localStorage.setItem('personalInfo', JSON.stringify(data));
alert('บันทึกข้อมูลส่วนตัวเรียบร้อยแล้ว');
showSection(sectionAssessment);
});
// Restore personal info if available
window.addEventListener('load', () => {
let saved = localStorage.getItem('personalInfo');
if (saved) {
let data = JSON.parse(saved);
personalForm.name.value = data.name || '';
personalForm.age.value = data.age || '';
let genderElems = personalForm.gender;
for(let i=0; i<genderElems.length; i++) {
if(genderElems[i].value === data.gender){
genderElems[i].checked = true;
}
}
personalForm.job.value = data.job || '';
personalForm.additionalInfo.value = data.additionalInfo || '';
}
showSection(sectionHome);
});
// ROSA form handling
const rosaForm = document.getElementById('rosaForm');
const summaryDiv = document.getElementById('assessmentSummary');
rosaForm.addEventListener('submit', function(event) {
event.preventDefault();
const form = event.target;
// Collect ROSA data
const data = {
'ความสูงของที่นั่ง': form.seatHeight.value,
'พนักพิงหลัง': form.backSupport.value,
'ที่วางแขน': form.armrests.value,
'ระดับความสูงของจอภาพ': form.monitorHeight.value,
'ระยะห่างของจอภาพจากตา': form.monitorDistance.value,
'ความสูงของโต๊ะทำงาน': form.deskHeight.value,
'ตำแหน่งคีย์บอร์ด': form.keyboardPosition.value,
'การใช้เมาส์': form.mouseUse.value,
'มุมของคอ': form.neckAngle.value,
'มุมของหลัง': form.backAngle.value,
'ตำแหน่งแขน': form.armPosition.value,
};
// Simple ROSA risk score estimation for demo purposes
// Assign numeric scores to options for a rough risk score
function scoreOption(value, mapping) {
return mapping[value] || 0;
}
const scoreMap = {
seatHeight: {
"ต่ำ (ต่ำกว่า 40cm)": 2,
"ปานกลาง (40-50 cm)": 1,
"สูง (สูงกว่า 50 cm)": 3,
},
backSupport: {
"มี": 0,
"ไม่มี": 3,
},
armrests: {
"มี": 0,
"ไม่มี": 2,
},
monitorHeight: {
"ต่ำกว่าระดับสายตา": 2,
"ระดับสายตา": 0,
"สูงกว่าระดับสายตา": 2,
},
monitorDistance: {
"ใกล้เกินไป (< 40 cm)": 3,
"ใกล้เกินไป (< 40 cm)":3,
"เหมาะสม (40-75 cm)": 0,
"ห่างเกินไป (> 75 cm)": 2,
"ห่างเกินไป (> 75 cm)": 2,
"ใกล้เกินไป (< 40 cm)":3,
},
deskHeight: {
"ต่ำ (ต่ำกว่า 68 cm)": 2,
"เหมาะสม (68-75 cm)": 0,
"สูง (สูงกว่า 75 cm)": 2,
},
keyboardPosition: {
"แบนราบ": 0,
"เอียง": 2,
},
mouseUse: {
"ใช้น้อย": 0,
"ใช้ปานกลาง": 1,
"ใช้มาก": 3,
},
neckAngle: {
"เป็นกลาง (0-10°)": 0,
"ปานกลาง (11-20°)": 2,
"มาก (21° ขึ้นไป)": 4,
},
backAngle: {
"ตรง (75° - 90°)": 0,
"โน้มไปข้างหน้า (45° - 75°)": 3,
"กดหลัง (ต่ำกว่า 45°)": 5,
},
armPosition: {
"ชิดลำตัว": 0,
"ยื่นไปข้างหน้า": 2,
"ยกขึ้นเหนือโต๊ะ": 3,
}
};
let totalScore = 0;
for (const key in data
) { // Map keys to scoreMap keys (some keys same but some differ, handle carefully)
let mapKey = "";
case 'ความสูงของที่นั่ง': mapKey = 'seatHeight'; break;
case 'พนักพิงหลัง': mapKey = 'backSupport'; break;
case 'ที่วางแขน': mapKey = 'armrests'; break;
case 'ระดับความสูงของจอภาพ': mapKey = 'monitorHeight'; break;
case 'ระยะห่างของจอภาพจากตา': mapKey = 'monitorDistance'; break;
case 'ความสูงของโต๊ะทำงาน': mapKey = 'deskHeight'; break;
case 'ตำแหน่งคีย์บอร์ด': mapKey = 'keyboardPosition'; break;
case 'การใช้เมาส์': mapKey = 'mouseUse'; break;
case 'มุมของคอ': mapKey = 'neckAngle'; break;
case 'มุมของหลัง': mapKey = 'backAngle'; break;
case 'ตำแหน่งแขน': mapKey = 'armPosition'; break;
}
totalScore
+= scoreOption
(data
[key], scoreMap
[mapKey
]); }
// Risk level based on totalScore
let riskLevel = "";
let recommendations = "";
if (totalScore <= 5) {
riskLevel = "ระดับความเสี่ยงต่ำ";
recommendations = "ท่าทางของคุณอยู่ในเกณฑ์ปลอดภัย แนะนำให้รักษาสภาพการทำงานเดิมไว้และพักผ่อนเมื่อรู้สึกเมื่อยล้า";
} else if (totalScore <= 12) {
riskLevel = "ระดับความเสี่ยงปานกลาง";
recommendations = "แนะนำให้ปรับเปลี่ยนท่าทางบางส่วน เช่น การปรับความสูงของเก้าอี้และจอภาพ รวมถึงพักเบรกบ่อยขึ้น";
} else {
riskLevel = "ระดับความเสี่ยงสูง";
recommendations = "ควรปรับปรุงท่าทางอย่างเร่งด่วน โดยปรึกษาผู้เชี่ยวชาญด้านการยศาสตร์และปรับอุปกรณ์ทำงานให้เหมาะสม";
}
// Show personal info summary
let personalInfo = localStorage.getItem('personalInfo');
personalInfo = personalInfo ? JSON.parse(personalInfo) : null;
let summaryText = "ผลสรุปการประเมินท่าทางการยศาสตร์ด้วย ROSA\n\n";
if(personalInfo){
summaryText += `ชื่อ: ${personalInfo.name}\n`;
summaryText += `อายุ: ${personalInfo.age}\n`;
summaryText += `เพศ: ${personalInfo.gender}\n`;
if(personalInfo.job) summaryText += `อาชีพ: ${personalInfo.job}\n`;
if(personalInfo.additionalInfo) summaryText += `ข้อมูลเพิ่มเติม: ${personalInfo.additionalInfo}\n`;
}
summaryText += "\nข้อมูลแบบประเมิน:\n";
for (const key in data
) { summaryText
+= `
- $
{key}: $
{data
[key]}\n`
; }
summaryText += `\nคะแนนรวมความเสี่ยง: ${totalScore}\n`;
summaryText += `ระดับความเสี่ยง: ${riskLevel}\n\n`;
summaryText += `คำแนะนำ:\n${recommendations}\n\n`;
// Additional recommendations for musculoskeletal health
summaryText += "คำแนะนำเพิ่มเติมสำหรับความผิดปกติของโครงร่างกล้ามเนื้อ:\n";
summaryText += "- นั่งหลังตรง และใช้พนักพิงหลังให้เหมาะสม\n";
summaryText += "- ปรับความสูงโต๊ะและเก้าอี้ให้พอดีกับระดับศีรษะและข้อศอก\n";
summaryText += "- ใช้เมาส์และคีย์บอร์ดในตำแหน่งที่สบายและลดการยกไหล่\n";
summaryText += "- พักสายตาทุก 20 นาที โดยการมองไปไกลประมาณ 20 ฟุต เป็นเวลา 20 วินาที\n";
summaryText += "- ยืดเหยียดกล้ามเนื้อและเปลี่ยนอิริยาบถเป็นระยะเพื่อลดความตึงตัว\n";
summaryDiv.textContent = summaryText;
summaryDiv.classList.remove('hidden');
summaryDiv.scrollIntoView({behavior:'smooth'});
});
</script>
</body>
</html>
```
}