mirror of
https://github.com/th30d4y/OpenLearnX.git
synced 2026-05-26 19:26:33 +00:00
@@ -0,0 +1,603 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>BlockChat</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
|
||||
body {
|
||||
font-family: 'Segoe UI', sans-serif;
|
||||
background: #0e1621;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.chat-container {
|
||||
display: flex;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
/* Sidebar */
|
||||
.sidebar {
|
||||
width: 400px;
|
||||
background: #1e2129;
|
||||
border-right: 1px solid #2e3a59;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.sidebar-header {
|
||||
background: linear-gradient(135deg, #667eea, #764ba2);
|
||||
padding: 25px;
|
||||
color: white;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.user-info h4 {
|
||||
margin: 0;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.user-info small {
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.contacts-list {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
.contact-item {
|
||||
padding: 20px 25px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
transition: all 0.3s;
|
||||
color: #8e959e;
|
||||
border-left: 3px solid transparent;
|
||||
}
|
||||
|
||||
.contact-item:hover {
|
||||
background: #2e3a59;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.contact-item.active {
|
||||
background: #2e3a59;
|
||||
border-left-color: #667eea;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.contact-avatar {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
background: linear-gradient(135deg, #667eea, #764ba2);
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
.contact-info h6 {
|
||||
margin: 0 0 5px 0;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.contact-info small {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
/* Chat Area */
|
||||
.chat-area {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.chat-header {
|
||||
background: #1e2129;
|
||||
padding: 20px 25px;
|
||||
border-bottom: 1px solid #2e3a59;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.chat-avatar {
|
||||
width: 45px;
|
||||
height: 45px;
|
||||
background: linear-gradient(135deg, #667eea, #764ba2);
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 15px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.messages-area {
|
||||
flex: 1;
|
||||
padding: 20px;
|
||||
overflow-y: auto;
|
||||
background: #0e1621;
|
||||
}
|
||||
|
||||
.message {
|
||||
margin-bottom: 15px;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.message.sent {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.message.received {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.message-bubble {
|
||||
max-width: 70%;
|
||||
padding: 12px 16px;
|
||||
border-radius: 18px;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.message.sent .message-bubble {
|
||||
background: linear-gradient(135deg, #667eea, #764ba2);
|
||||
color: white;
|
||||
border-bottom-right-radius: 4px;
|
||||
}
|
||||
|
||||
.message.received .message-bubble {
|
||||
background: #1e2129;
|
||||
color: white;
|
||||
border-bottom-left-radius: 4px;
|
||||
}
|
||||
|
||||
.message-time {
|
||||
font-size: 11px;
|
||||
opacity: 0.7;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.input-area {
|
||||
background: #1e2129;
|
||||
padding: 20px 25px;
|
||||
border-top: 1px solid #2e3a59;
|
||||
display: flex;
|
||||
gap: 15px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.message-input {
|
||||
flex: 1;
|
||||
background: #0e1621;
|
||||
border: 2px solid #2e3a59;
|
||||
border-radius: 25px;
|
||||
padding: 12px 20px;
|
||||
color: white;
|
||||
outline: none;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.message-input:focus {
|
||||
border-color: #667eea;
|
||||
}
|
||||
|
||||
.message-input::placeholder {
|
||||
color: #8e959e;
|
||||
}
|
||||
|
||||
.send-btn {
|
||||
background: linear-gradient(135deg, #667eea, #764ba2);
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 50%;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.send-btn:hover:not(:disabled) {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
.send-btn:disabled {
|
||||
background: #666;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.welcome-screen {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
color: #8e959e;
|
||||
}
|
||||
|
||||
.welcome-screen i {
|
||||
font-size: 80px;
|
||||
margin-bottom: 20px;
|
||||
background: linear-gradient(135deg, #667eea, #764ba2);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
}
|
||||
|
||||
.empty-state {
|
||||
text-align: center;
|
||||
color: #8e959e;
|
||||
padding: 50px 20px;
|
||||
}
|
||||
|
||||
.empty-state i {
|
||||
font-size: 60px;
|
||||
margin-bottom: 15px;
|
||||
background: linear-gradient(135d deg, #667eea, #764ba2);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="chat-container">
|
||||
<!-- Sidebar -->
|
||||
<div class="sidebar">
|
||||
<div class="sidebar-header">
|
||||
<div class="user-info">
|
||||
<h4><i class="fas fa-comments me-2"></i>BlockChat</h4>
|
||||
<small id="myAddress">Loading...</small>
|
||||
</div>
|
||||
<button class="btn btn-outline-light btn-sm" onclick="logout()">
|
||||
<i class="fas fa-sign-out-alt"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="contacts-list" id="contactsList">
|
||||
<div class="text-center p-4">
|
||||
<div class="spinner-border text-primary"></div>
|
||||
<p class="mt-2">Loading contacts...</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Chat Area -->
|
||||
<div class="chat-area">
|
||||
<div class="welcome-screen">
|
||||
<i class="fas fa-comments"></i>
|
||||
<h3>Welcome to BlockChat</h3>
|
||||
<p>Select a contact to start messaging</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/web3/1.7.4/web3.min.js"></script>
|
||||
<script>
|
||||
// Global variables
|
||||
let myAccount = localStorage.getItem('myaddress');
|
||||
let web3, contract;
|
||||
let currentChat = null;
|
||||
let allContacts = [];
|
||||
|
||||
const CONTRACT_ADDRESS = '0xd9145CCE52D386f254917e481eB44e9943F39138';
|
||||
const CONTRACT_ABI = [
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{"indexed": true, "internalType": "address", "name": "from", "type": "address"},
|
||||
{"indexed": false, "internalType": "string", "name": "message", "type": "string"},
|
||||
{"indexed": false, "internalType": "address", "name": "to", "type": "address"},
|
||||
{"indexed": false, "internalType": "string", "name": "timestamp", "type": "string"}
|
||||
],
|
||||
"name": "message",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{"internalType": "address", "name": "_to", "type": "address"},
|
||||
{"internalType": "string", "name": "_message", "type": "string"},
|
||||
{"internalType": "string", "name": "time", "type": "string"}
|
||||
],
|
||||
"name": "sendMessage",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
}
|
||||
];
|
||||
|
||||
// Initialize app
|
||||
window.addEventListener('load', function() {
|
||||
if (!myAccount) {
|
||||
alert('Please login first!');
|
||||
window.location.href = 'index.html';
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('🚀 Starting BlockChat for:', myAccount);
|
||||
initializeApp();
|
||||
});
|
||||
|
||||
async function initializeApp() {
|
||||
try {
|
||||
// Connect to blockchain
|
||||
web3 = new Web3('http://127.0.0.1:8545');
|
||||
contract = new web3.eth.Contract(CONTRACT_ABI, CONTRACT_ADDRESS);
|
||||
|
||||
// Test connection
|
||||
await web3.eth.net.isListening();
|
||||
console.log('✅ Connected to blockchain');
|
||||
|
||||
// Show user address
|
||||
document.getElementById('myAddress').textContent =
|
||||
myAccount.substring(0, 6) + '...' + myAccount.substring(38);
|
||||
|
||||
// Load contacts
|
||||
await loadContacts();
|
||||
|
||||
// Start monitoring for new messages
|
||||
startMessageMonitoring();
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Initialization failed:', error);
|
||||
alert('Failed to connect to blockchain!');
|
||||
}
|
||||
}
|
||||
|
||||
async function loadContacts() {
|
||||
try {
|
||||
const accounts = await web3.eth.getAccounts();
|
||||
allContacts = accounts.filter(acc => acc.toLowerCase() !== myAccount.toLowerCase());
|
||||
|
||||
let html = '';
|
||||
allContacts.forEach((contact, index) => {
|
||||
html += `
|
||||
<div class="contact-item" onclick="openChat('${contact}', ${index})">
|
||||
<div class="contact-avatar">${index + 1}</div>
|
||||
<div class="contact-info">
|
||||
<h6>Contact ${index + 1}</h6>
|
||||
<small>${contact.substring(0, 10)}...${contact.substring(32)}</small>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
|
||||
document.getElementById('contactsList').innerHTML = html;
|
||||
console.log('📞 Loaded', allContacts.length, 'contacts');
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Error loading contacts:', error);
|
||||
}
|
||||
}
|
||||
|
||||
function openChat(contactAddress, index) {
|
||||
currentChat = contactAddress;
|
||||
console.log('💬 Opening chat with:', contactAddress);
|
||||
|
||||
// Update contact selection
|
||||
document.querySelectorAll('.contact-item').forEach(item => item.classList.remove('active'));
|
||||
document.querySelectorAll('.contact-item')[index].classList.add('active');
|
||||
|
||||
// Show chat interface
|
||||
showChatInterface(contactAddress, index + 1);
|
||||
|
||||
// Load messages for this chat
|
||||
loadMessagesForChat(contactAddress);
|
||||
}
|
||||
|
||||
function showChatInterface(contactAddress, contactNumber) {
|
||||
const chatArea = document.querySelector('.chat-area');
|
||||
chatArea.innerHTML = `
|
||||
<div class="chat-header">
|
||||
<div class="chat-avatar">${contactNumber}</div>
|
||||
<div>
|
||||
<h6 style="margin: 0;">Contact ${contactNumber}</h6>
|
||||
<small>${contactAddress.substring(0, 12)}...</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="messages-area" id="messagesArea">
|
||||
<div class="empty-state">
|
||||
<i class="fas fa-comment-dots"></i>
|
||||
<h5>Start Conversation</h5>
|
||||
<p>Send the first message!</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="input-area">
|
||||
<input type="text" class="message-input" id="messageInput"
|
||||
placeholder="Type a message..." onkeypress="handleEnter(event)">
|
||||
<button class="send-btn" onclick="sendMessage()" id="sendBtn">
|
||||
<i class="fas fa-paper-plane"></i>
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
async function loadMessagesForChat(contactAddress) {
|
||||
try {
|
||||
console.log('📨 Loading messages for:', contactAddress);
|
||||
|
||||
const events = await contract.getPastEvents('message', {
|
||||
fromBlock: 0,
|
||||
toBlock: 'latest'
|
||||
});
|
||||
|
||||
console.log(`Found ${events.length} total events on blockchain`);
|
||||
|
||||
// Filter messages for this specific chat
|
||||
const chatMessages = [];
|
||||
const myAddr = myAccount.toLowerCase();
|
||||
const contactAddr = contactAddress.toLowerCase();
|
||||
|
||||
events.forEach(event => {
|
||||
const from = event.returnValues.from.toLowerCase();
|
||||
const to = event.returnValues.to.toLowerCase();
|
||||
|
||||
// Check if this message belongs to our conversation
|
||||
if ((from === myAddr && to === contactAddr) || (from === contactAddr && to === myAddr)) {
|
||||
chatMessages.push({
|
||||
from: from,
|
||||
to: to,
|
||||
message: event.returnValues.message,
|
||||
timestamp: event.returnValues.timestamp,
|
||||
blockNumber: event.blockNumber,
|
||||
isMyMessage: from === myAddr
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Sort by block number
|
||||
chatMessages.sort((a, b) => a.blockNumber - b.blockNumber);
|
||||
|
||||
console.log(`💬 Found ${chatMessages.length} messages in this chat`);
|
||||
|
||||
// Display messages
|
||||
displayMessages(chatMessages);
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Error loading messages:', error);
|
||||
}
|
||||
}
|
||||
|
||||
function displayMessages(messages) {
|
||||
const messagesArea = document.getElementById('messagesArea');
|
||||
if (!messagesArea) return;
|
||||
|
||||
if (messages.length === 0) {
|
||||
messagesArea.innerHTML = `
|
||||
<div class="empty-state">
|
||||
<i class="fas fa-comment-dots"></i>
|
||||
<h5>Start Conversation</h5>
|
||||
<p>Send the first message!</p>
|
||||
</div>
|
||||
`;
|
||||
return;
|
||||
}
|
||||
|
||||
let html = '';
|
||||
messages.forEach(msg => {
|
||||
const messageClass = msg.isMyMessage ? 'sent' : 'received';
|
||||
html += `
|
||||
<div class="message ${messageClass}">
|
||||
<div class="message-bubble">
|
||||
<div>${escapeHtml(msg.message)}</div>
|
||||
<div class="message-time">${msg.timestamp}</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
|
||||
messagesArea.innerHTML = html;
|
||||
|
||||
// Scroll to bottom
|
||||
setTimeout(() => {
|
||||
messagesArea.scrollTop = messagesArea.scrollHeight;
|
||||
}, 100);
|
||||
}
|
||||
|
||||
async function sendMessage() {
|
||||
if (!currentChat) {
|
||||
alert('Please select a chat first!');
|
||||
return;
|
||||
}
|
||||
|
||||
const input = document.getElementById('messageInput');
|
||||
const sendBtn = document.getElementById('sendBtn');
|
||||
const messageText = input.value.trim();
|
||||
|
||||
if (!messageText) {
|
||||
alert('Please enter a message!');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
console.log('📤 Sending message:', messageText, 'to:', currentChat);
|
||||
|
||||
// Disable UI
|
||||
input.disabled = true;
|
||||
sendBtn.disabled = true;
|
||||
sendBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i>';
|
||||
|
||||
// Create timestamp
|
||||
const now = new Date();
|
||||
const timestamp = now.toLocaleDateString("en-IN") + ' ' +
|
||||
now.toLocaleTimeString("en-IN", {
|
||||
hour12: true,
|
||||
hour: '2-digit',
|
||||
minute: '2-digit'
|
||||
});
|
||||
|
||||
// Send to blockchain
|
||||
const receipt = await contract.methods
|
||||
.sendMessage(currentChat, messageText, timestamp)
|
||||
.send({
|
||||
from: myAccount,
|
||||
gas: 300000
|
||||
});
|
||||
|
||||
console.log('✅ Message sent! Transaction:', receipt.transactionHash);
|
||||
|
||||
// Clear input
|
||||
input.value = '';
|
||||
|
||||
// Reload messages to show the new one
|
||||
setTimeout(() => {
|
||||
loadMessagesForChat(currentChat);
|
||||
}, 2000);
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Failed to send message:', error);
|
||||
alert('Failed to send message: ' + error.message);
|
||||
} finally {
|
||||
// Re-enable UI
|
||||
input.disabled = false;
|
||||
sendBtn.disabled = false;
|
||||
sendBtn.innerHTML = '<i class="fas fa-paper-plane"></i>';
|
||||
input.focus();
|
||||
}
|
||||
}
|
||||
|
||||
function handleEnter(event) {
|
||||
if (event.key === 'Enter') {
|
||||
event.preventDefault();
|
||||
sendMessage();
|
||||
}
|
||||
}
|
||||
|
||||
// Monitor for new messages every 5 seconds
|
||||
function startMessageMonitoring() {
|
||||
setInterval(() => {
|
||||
if (currentChat) {
|
||||
console.log('🔄 Checking for new messages...');
|
||||
loadMessagesForChat(currentChat);
|
||||
}
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
function escapeHtml(text) {
|
||||
const div = document.createElement('div');
|
||||
div.textContent = text;
|
||||
return div.innerHTML;
|
||||
}
|
||||
|
||||
function logout() {
|
||||
localStorage.removeItem('myaddress');
|
||||
window.location.href = 'index.html';
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,12 @@
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
contract Payment{
|
||||
event message(address indexed from ,string message ,address to,string timestamp);
|
||||
function sendMessage(address _to,string memory _message,string memory time) public {
|
||||
|
||||
emit message(msg.sender,_message,_to,time);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,284 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>BlockChat Login</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
|
||||
<style>
|
||||
body {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
min-height: 100vh;
|
||||
font-family: 'Segoe UI', sans-serif;
|
||||
}
|
||||
|
||||
.login-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 100vh;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.login-card {
|
||||
background: white;
|
||||
border-radius: 20px;
|
||||
padding: 40px;
|
||||
box-shadow: 0 20px 40px rgba(0,0,0,0.1);
|
||||
max-width: 500px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.app-header {
|
||||
text-align: center;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
.app-logo {
|
||||
font-size: 80px;
|
||||
background: linear-gradient(135deg, #667eea, #764ba2);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.app-title {
|
||||
font-size: 32px;
|
||||
color: #333;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.app-subtitle {
|
||||
color: #666;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.status-box {
|
||||
background: #f8f9fa;
|
||||
border: 1px solid #e9ecef;
|
||||
border-radius: 10px;
|
||||
padding: 15px;
|
||||
margin: 20px 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.status-box.connected {
|
||||
background: #d1ecf1;
|
||||
border-color: #bee5eb;
|
||||
color: #0c5460;
|
||||
}
|
||||
|
||||
.status-box.error {
|
||||
background: #f8d7da;
|
||||
border-color: #f5c6cb;
|
||||
color: #721c24;
|
||||
}
|
||||
|
||||
.accounts-title {
|
||||
font-size: 18px;
|
||||
color: #333;
|
||||
margin: 30px 0 15px 0;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.account-card {
|
||||
background: #f8f9fa;
|
||||
border: 2px solid #e9ecef;
|
||||
border-radius: 15px;
|
||||
padding: 20px;
|
||||
margin: 10px 0;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.account-card:hover {
|
||||
border-color: #667eea;
|
||||
background: #e3f2fd;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.account-card.selected {
|
||||
background: linear-gradient(135deg, #667eea, #764ba2);
|
||||
border-color: #667eea;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.account-name {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.account-address {
|
||||
font-family: 'Courier New', monospace;
|
||||
font-size: 12px;
|
||||
opacity: 0.8;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.login-btn {
|
||||
background: linear-gradient(135deg, #667eea, #764ba2);
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 50px;
|
||||
padding: 15px 30px;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
width: 100%;
|
||||
margin-top: 30px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.login-btn:hover:not(:disabled) {
|
||||
background: linear-gradient(135deg, #5a67d8, #6b46c1);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.login-btn:disabled {
|
||||
background: #ccc;
|
||||
cursor: not-allowed;
|
||||
transform: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="login-container">
|
||||
<div class="login-card">
|
||||
<div class="app-header">
|
||||
<div class="app-logo">
|
||||
<i class="fas fa-comments"></i>
|
||||
</div>
|
||||
<h1 class="app-title">BlockChat</h1>
|
||||
<p class="app-subtitle">Secure blockchain messaging</p>
|
||||
</div>
|
||||
|
||||
<div class="status-box error" id="statusBox">
|
||||
<i class="fas fa-spinner fa-spin me-2"></i>
|
||||
<span>Connecting to blockchain...</span>
|
||||
</div>
|
||||
|
||||
<div id="accountsSection" style="display: none;">
|
||||
<h3 class="accounts-title">Select Your Account</h3>
|
||||
<div id="accountsList"></div>
|
||||
</div>
|
||||
|
||||
<button class="login-btn" id="loginBtn" onclick="startChat()" disabled>
|
||||
<i class="fas fa-rocket me-2"></i>
|
||||
Enter BlockChat
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/web3/1.7.4/web3.min.js"></script>
|
||||
<script>
|
||||
let web3;
|
||||
let selectedAccount = null;
|
||||
let accounts = [];
|
||||
|
||||
// Start when page loads
|
||||
window.addEventListener('load', function() {
|
||||
console.log('🚀 Starting BlockChat login...');
|
||||
connectToBlockchain();
|
||||
});
|
||||
|
||||
async function connectToBlockchain() {
|
||||
try {
|
||||
console.log('🔗 Connecting to Anvil blockchain...');
|
||||
|
||||
// Connect to Anvil
|
||||
web3 = new Web3('http://127.0.0.1:8545');
|
||||
|
||||
// Test connection
|
||||
const isListening = await web3.eth.net.isListening();
|
||||
if (!isListening) {
|
||||
throw new Error('Cannot connect to Anvil');
|
||||
}
|
||||
|
||||
// Get accounts
|
||||
accounts = await web3.eth.getAccounts();
|
||||
console.log('✅ Found', accounts.length, 'accounts');
|
||||
|
||||
if (accounts.length === 0) {
|
||||
throw new Error('No accounts found');
|
||||
}
|
||||
|
||||
// Update status
|
||||
updateStatus(true, `Connected! Found ${accounts.length} accounts`);
|
||||
|
||||
// Show accounts
|
||||
showAccounts();
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Connection failed:', error);
|
||||
updateStatus(false, 'Connection failed - Make sure Anvil is running');
|
||||
}
|
||||
}
|
||||
|
||||
function updateStatus(connected, message) {
|
||||
const statusBox = document.getElementById('statusBox');
|
||||
|
||||
if (connected) {
|
||||
statusBox.className = 'status-box connected';
|
||||
statusBox.innerHTML = `<i class="fas fa-check-circle me-2"></i><span>${message}</span>`;
|
||||
} else {
|
||||
statusBox.className = 'status-box error';
|
||||
statusBox.innerHTML = `<i class="fas fa-exclamation-triangle me-2"></i><span>${message}</span>`;
|
||||
}
|
||||
}
|
||||
|
||||
function showAccounts() {
|
||||
const accountsSection = document.getElementById('accountsSection');
|
||||
const accountsList = document.getElementById('accountsList');
|
||||
|
||||
let html = '';
|
||||
accounts.forEach((account, index) => {
|
||||
html += `
|
||||
<div class="account-card" onclick="selectAccount('${account}', ${index})">
|
||||
<div class="account-name">
|
||||
<i class="fas fa-wallet me-2"></i>
|
||||
Account ${index + 1}
|
||||
</div>
|
||||
<div class="account-address">${account}</div>
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
|
||||
accountsList.innerHTML = html;
|
||||
accountsSection.style.display = 'block';
|
||||
}
|
||||
|
||||
function selectAccount(account, index) {
|
||||
selectedAccount = account;
|
||||
console.log('📝 Selected account:', account);
|
||||
|
||||
// Update visual selection
|
||||
document.querySelectorAll('.account-card').forEach(card => {
|
||||
card.classList.remove('selected');
|
||||
});
|
||||
document.querySelectorAll('.account-card')[index].classList.add('selected');
|
||||
|
||||
// Enable login button
|
||||
document.getElementById('loginBtn').disabled = false;
|
||||
}
|
||||
|
||||
function startChat() {
|
||||
if (!selectedAccount) {
|
||||
alert('Please select an account first!');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('🚀 Starting chat with account:', selectedAccount);
|
||||
|
||||
// Store selected account
|
||||
localStorage.setItem('myaddress', selectedAccount);
|
||||
|
||||
// Navigate to chat
|
||||
window.location.href = 'account.html';
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,46 @@
|
||||
|
||||
#body {
|
||||
font-family: 'Nunito';
|
||||
background-color: #5d8fc9;
|
||||
}
|
||||
#login-card{
|
||||
width:350px;
|
||||
border-radius: 25px;
|
||||
margin:150px auto;
|
||||
|
||||
}
|
||||
|
||||
#email{
|
||||
border-radius:30px;
|
||||
background-color: #ebf0fc;
|
||||
border-color: #ebf0fc;
|
||||
color: #9da3b0;
|
||||
}
|
||||
|
||||
#button{
|
||||
border-radius:30px;
|
||||
|
||||
}
|
||||
|
||||
#btn{
|
||||
position: absolute;
|
||||
bottom: -35px;
|
||||
padding: 5px;
|
||||
margin: 0px 55px;
|
||||
align-items: center;
|
||||
border-radius: 5px"
|
||||
}
|
||||
#container{
|
||||
margin-top:25px;
|
||||
}
|
||||
|
||||
.btn-circle.btn-sm {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
padding: 2px 0px;
|
||||
border-radius: 25px;
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
|
||||
margin: 8px;
|
||||
}
|
||||
@@ -0,0 +1,202 @@
|
||||
/* Google Font */
|
||||
@import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700&family=Poppins:wght@300;500;700&display=swap');
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Poppins', sans-serif;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Header */
|
||||
header {
|
||||
background: linear-gradient(135deg, #ff007f, #6200ff);
|
||||
padding: 20px 0;
|
||||
text-align: center;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 1000;
|
||||
box-shadow: 0 5px 15px rgba(255, 0, 128, 0.5);
|
||||
}
|
||||
|
||||
header h1 {
|
||||
font-family: 'Orbitron', sans-serif;
|
||||
font-size: 2.5em;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 2px;
|
||||
background: linear-gradient(90deg, #ffcc00, #ff007f);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
text-shadow: 0 0 15px rgba(255, 140, 0, 0.8);
|
||||
}
|
||||
|
||||
/* Navigation */
|
||||
nav ul {
|
||||
list-style: none;
|
||||
padding: 10px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
nav ul li {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
nav ul li a {
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
font-size: 1.2em;
|
||||
padding: 10px 20px;
|
||||
border-radius: 5px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
nav ul li a:hover {
|
||||
background: #ff007f;
|
||||
box-shadow: 0 0 10px #ff007f;
|
||||
}
|
||||
|
||||
/* Main Section */
|
||||
#main {
|
||||
text-align: center;
|
||||
padding: 100px 20px;
|
||||
background: linear-gradient(135deg, #1a1a1a, #333333);
|
||||
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.5);
|
||||
border-radius: 10px;
|
||||
margin: 50px auto;
|
||||
max-width: 800px;
|
||||
animation: fadeIn 1.5s ease-in-out;
|
||||
}
|
||||
|
||||
#main h2 {
|
||||
font-size: 2.5em;
|
||||
font-weight: bold;
|
||||
text-transform: uppercase;
|
||||
color: #ffcc00;
|
||||
text-shadow: 0 0 20px rgba(255, 140, 0, 0.7);
|
||||
}
|
||||
|
||||
/* Animations */
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-20px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
from {
|
||||
transform: scale(1);
|
||||
filter: drop-shadow(0px 0px 10px #ffcc00);
|
||||
}
|
||||
to {
|
||||
transform: scale(1.1);
|
||||
filter: drop-shadow(0px 0px 20px #ffcc00);
|
||||
}
|
||||
}
|
||||
|
||||
/* Contact Section */
|
||||
#contact-form {
|
||||
background: url('https://i.gifer.com/Xlcy.gif') center/cover no-repeat; /* Change background to GIF */
|
||||
text-align: center;
|
||||
padding: 100px 20px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
#contact-form h2 {
|
||||
font-size: 2.5em;
|
||||
text-transform: uppercase;
|
||||
color: #ffcc00;
|
||||
text-shadow: 0 0 15px #ffcc00;
|
||||
}
|
||||
|
||||
#contact-form form {
|
||||
background: rgba(0, 0, 0, 0.7);
|
||||
padding: 30px;
|
||||
display: inline-block;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 0 15px #ffcc00;
|
||||
}
|
||||
|
||||
#contact-form input, #contact-form textarea {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
margin-top: 10px;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
background: #222;
|
||||
color: white;
|
||||
}
|
||||
|
||||
#contact-form button {
|
||||
background: #ff007f;
|
||||
color: white;
|
||||
padding: 10px 20px;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
#contact-form button:hover {
|
||||
background: #ffcc00;
|
||||
box-shadow: 0 0 15px #ffcc00;
|
||||
}
|
||||
|
||||
/* 3D Buttons */
|
||||
button, .button_1 {
|
||||
font-family: 'Orbitron', sans-serif;
|
||||
background: linear-gradient(135deg, #ff007f, #6200ff);
|
||||
color: white;
|
||||
padding: 12px 24px;
|
||||
border: none;
|
||||
font-size: 1.1em;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
box-shadow: 0px 4px 10px rgba(255, 0, 128, 0.5);
|
||||
transition: all 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
button:hover, .button_1:hover {
|
||||
transform: scale(1.1);
|
||||
background: linear-gradient(135deg, #ffcc00, #ff007f);
|
||||
box-shadow: 0px 4px 20px rgba(255, 204, 0, 0.8);
|
||||
}
|
||||
|
||||
/* Footer */
|
||||
footer {
|
||||
background: #111;
|
||||
text-align: center;
|
||||
padding: 20px;
|
||||
color: white;
|
||||
margin-top: 50px;
|
||||
}
|
||||
|
||||
/* Responsive */
|
||||
@media (max-width: 768px) {
|
||||
header h1 {
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
nav ul {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
#main h2 {
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
#contact-form form {
|
||||
width: 80%;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user