🎉個人情報管理アプリ🎉
😃🎈✨🚀🎨
✏️編集モード✏️
```html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>✨個人情報管理アプリ✨</title>
<style>
@keyframes bounce {
0%, 20%, 50%, 80%, 100% { transform: translateY(0); }
40% { transform: translateY(-10px); }
60% { transform: translateY(-5px); }
}
@keyframes shake {
0% { transform: translate(1px, 1px) rotate(0deg); }
10% { transform: translate(-1px, -2px) rotate(-1deg); }
20% { transform: translate(-3px, 0px) rotate(1deg); }
30% { transform: translate(3px, 2px) rotate(0deg); }
40% { transform: translate(1px, -1px) rotate(1deg); }
50% { transform: translate(-1px, 2px) rotate(-1deg); }
60% { transform: translate(-3px, 1px) rotate(0deg); }
70% { transform: translate(3px, 1px) rotate(-1deg); }
80% { transform: translate(-1px, -1px) rotate(1deg); }
90% { transform: translate(1px, 2px) rotate(0deg); }
100% { transform: translate(1px, -2px) rotate(-1deg); }
}
.animate-bounce {
animation: bounce 1s infinite;
}
.animate-shake {
animation: shake 0.5s;
}
</style>
</head>
<body>
<div style="width: 100%; text-align: center; padding: 10px;">
<h1 style="font-size: 24px;">🎉個人情報管理アプリ🎉</h1>
<div id="emoji-header" style="font-size: 30px;">😃🎈✨🚀🎨</div>
</div>
<div style="padding: 10px;">
<div style="margin-bottom: 10px;">
<input type="number" id="address" placeholder="アドレス(1-255)" style="width: 120px; padding: 5px;">
<input type="text" id="lastName" placeholder="苗字" style="width: 120px; padding: 5px;">
<input type="text" id="firstName" placeholder="名前" style="width: 120px; padding: 5px;">
<button id="addBtn" style="padding: 5px 10px; margin-left: 5px;">➕追加</button>
</div>
<div id="entries" style="max-height: 200px; overflow-y: auto; border: 1px solid #ccc; padding: 10px; border-radius: 5px;">
<!-- 個人情報リスト -->
</div>
<div style="text-align: center; margin-top: 10px;">
<button id="sendBtn" style="padding: 10px 20px; font-size: 16px;">📤送信</button>
</div>
</div>
<div id="editModal" style="display:none; position: fixed; top: 50%; left: 50%;
transform: translate(-50%, -50%); background: #fff; padding: 20px; border: 2px solid #000; border-radius: 10px;">
<h2 style="text-align: center;">✏️編集モード✏️</h2>
<div style="margin-bottom: 10px;">
<input type="number" id="editAddress" placeholder="アドレス(1-255)" style="width: 100%; padding: 5px;">
</div>
<div style="margin-bottom: 10px;">
<input type="text" id="editLastName" placeholder="苗字" style="width: 100%; padding: 5px;">
</div>
<div style="margin-bottom: 10px;">
<input type="text" id="editFirstName" placeholder="名前" style="width: 100%; padding: 5px;">
</div>
<div style="text-align: center;">
<button id="confirmEdit" style="padding: 5px 10px; margin-right: 10px;">✅確定</button>
<button id="cancelEdit" style="padding: 5px 10px;">❌キャンセル</button>
</div>
</div>
<script>
const addBtn = document.getElementById('addBtn');
const entriesDiv = document.getElementById('entries');
const sendBtn = document.getElementById('sendBtn');
const editModal = document.getElementById('editModal');
const confirmEdit = document.getElementById('confirmEdit');
const cancelEdit = document.getElementById('cancelEdit');
let personalInfos = [];
let editIndex = null;
function renderEntries() {
entriesDiv.innerHTML = '';
personalInfos.forEach((info, index) => {
const entryDiv = document.createElement('div');
entryDiv.style.borderBottom = '1px solid #eee';
entryDiv.style.padding = '5px 0';
entryDiv.innerHTML = `
<span style="font-size: 18px;">📇 アドレス: ${info.address}</span><br>
<span style="font-size: 18px;">👤 ${info.lastName} ${info.firstName}</span>
<button style="background:none; border:none; cursor:pointer; float:right; font-size: 18px;" onclick="deleteEntry(${index})">🗑️</button>
<button style="background:none; border:none; cursor:pointer; float:right; font-size: 18px; margin-right:5px;" onclick="editEntry(${index})">✏️</button>
`;
entriesDiv.appendChild(entryDiv);
});
}
function deleteEntry(index) {
personalInfos.splice(index, 1);
renderEntries();
showReaction('🗑️削除されました!');
}
function editEntry(index) {
editIndex = index;
const info = personalInfos[index];
document.getElementById('editAddress').value = info.address;
document.getElementById('editLastName').value = info.lastName;
document.getElementById('editFirstName').value = info.firstName;
editModal.style.display = 'block';
animateElement(editModal, 'animate-bounce');
}
confirmEdit.onclick = function() {
const address = parseInt(document.getElementById('editAddress').value);
const lastName = document.getElementById('editLastName').value.trim();
const firstName = document.getElementById('editFirstName').value.trim();
if (!validateInput(address, lastName, firstName, editIndex)) return;
personalInfos[editIndex] = { address, lastName, firstName };
editModal.style.display = 'none';
renderEntries();
showReaction('✅ 更新されました!');
};
cancelEdit.onclick = function() {
editModal.style.display = 'none';
showReaction('❌ 編集がキャンセルされました!');
};
addBtn.onclick = function() {
const address = parseInt(document.getElementById('address').value);
const lastName = document.getElementById('lastName').value.trim();
const firstName = document.getElementById('firstName').value.trim();
if (!validateInput(address, lastName, firstName)) return;
personalInfos.push({ address, lastName, firstName });
if (personalInfos.length > 3) {
personalInfos.shift();
}
renderEntries();
showReaction('✅ 追加されました!');
};
sendBtn.onclick = function() {
animateElement(sendBtn, 'animate-shake');
alert('📤 データが送信されました!');
};
function validateInput(address, lastName, firstName, editingIndex = null) {
if (isNaN(address) || address < 1 || address > 255) {
alert('⚠️ アドレスは1から255の間で入力してください。');
return false;
}
if (!lastName || !firstName) {
alert('⚠️ 苗字と名前を入力してください。');
return false;
}
const duplicate = personalInfos.some((info, index) => info.address === address && index !== editingIndex);
if (duplicate) {
alert('⚠️ アドレスが重複しています。別の番号を選んでください。');
return false;
}
return true;
}
function showReaction(message) {
const reaction = document.createElement('div');
reaction.innerText = message;
reaction.style.position = 'fixed';
reaction.style.top = '20px';
reaction.style.left = '50%';
reaction.style.transform = 'translateX(-50%)';
reaction.style.background = 'rgba(255, 255, 255, 0.8)';
reaction.style.padding = '10px 20px';
reaction.style.borderRadius = '20px';
reaction.style.boxShadow = '0 0 10px rgba(0,0,0,0.3)';
reaction.style.fontSize = '18px';
reaction.style.animation = 'bounce 1s';
document.body.appendChild(reaction);
setTimeout(() => {
reaction.remove();
}, 1500);
}
function animateElement(element, animationClass) {
element.classList.add(animationClass);
setTimeout(() => {
element.classList.remove(animationClass);
}, 1000);
}
// Make entriesDiv scrollable without overlapping
window.onload = function() {
entriesDiv.style.height = '200px';
}
</script>
</body>
</html>
```