repair realtime conection with realtime firebase + togle button

This commit is contained in:
Vckynando12 2025-02-19 05:15:04 +07:00
parent 193d4a04c2
commit 9d3be56527
7 changed files with 296 additions and 55 deletions

2
.gitignore vendored
View File

@ -16,3 +16,5 @@ yarn-error.log
/.fleet
/.idea
/.vscode
!storage/app/*.json

View File

@ -1,4 +1,4 @@
#include <ESP8266WiFi.h>
#include <ESP8266WiFi.h>
#include <FirebaseESP8266.h>
#include <DHT.h>

View File

@ -0,0 +1,51 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Storage;
class ProfileController extends Controller
{
public function index()
{
return view('profile', [
'user' => Auth::user()
]);
}
public function update(Request $request)
{
$request->validate([
'email' => 'required|email',
'current_password' => 'required_with:new_password',
'new_password' => 'nullable|min:8|confirmed',
'profile_photo' => 'nullable|image|mimes:jpeg,png,jpg|max:2048'
]);
$user = Auth::user();
$user->email = $request->email;
// Handle password change
if ($request->new_password) {
if (!Hash::check($request->current_password, $user->password)) {
return back()->withErrors(['current_password' => 'Current password is incorrect']);
}
$user->password = Hash::make($request->new_password);
}
// Handle profile photo
if ($request->hasFile('profile_photo')) {
$photo = $request->file('profile_photo');
// Replace existing foto.jpg
$photo->move(public_path('asset'), 'foto.jpg');
}
$user->save();
return redirect()->back()->with('success', 'Profile updated successfully');
}
}

View File

@ -13,16 +13,16 @@ public function register()
{
$this->app->singleton(FirebaseAuth::class, function ($app) {
$factory = (new Factory)
->withServiceAccount(json_decode(env('FIREBASE_CREDENTIALS'), true))
->withDatabaseUri(env('FIREBASE_DATABASE_URL'));
->withServiceAccount(storage_path('app/smartcab-8bb42-firebase-adminsdk-fbsvc-de33a8e45b.json'))
->withDatabaseUri(env('FIREBASE_DATABASE_URL'));
return $factory->createAuth();
});
$this->app->singleton(Database::class, function ($app) {
$factory = (new Factory)
->withServiceAccount(config('firebase.credentials'))
->withDatabaseUri(config('firebase.database_url'));
->withServiceAccount(storage_path('app/smartcab-8bb42-firebase-adminsdk-fbsvc-de33a8e45b.json'))
->withDatabaseUri(env('FIREBASE_DATABASE_URL'));
return $factory->createDatabase();
});

View File

@ -0,0 +1,119 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Profile - SmartCab</title>
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="bg-gray-100 dark:bg-gray-900">
<div class="min-h-screen p-6">
<div class="max-w-3xl mx-auto">
<!-- Header -->
<div class="flex justify-between items-center mb-6">
<h1 class="text-2xl font-bold text-gray-800 dark:text-white">Your Profile</h1>
<a href="{{ route('welcome') }}" class="px-4 py-2 bg-gray-200 text-gray-700 rounded-lg hover:bg-gray-300 dark:bg-gray-700 dark:text-white dark:hover:bg-gray-600">
Back to Dashboard
</a>
</div>
@if(session('success'))
<div class="mb-4 p-4 bg-green-100 border border-green-400 text-green-700 rounded">
{{ session('success') }}
</div>
@endif
@if($errors->any())
<div class="mb-4 p-4 bg-red-100 border border-red-400 text-red-700 rounded">
<ul>
@foreach($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<form action="{{ route('profile.update') }}" method="POST" enctype="multipart/form-data" class="bg-white dark:bg-gray-800 rounded-lg shadow-lg p-6">
@csrf
<!-- Profile Photo -->
<div class="mb-6">
<label class="block text-gray-700 dark:text-gray-200 text-sm font-bold mb-2">Profile Photo</label>
<div class="flex items-center space-x-6">
<div class="shrink-0">
<img id="preview" class="h-32 w-32 object-cover rounded-full" src="{{ asset('asset/foto.jpg') }}" alt="Current profile photo">
</div>
<label class="block">
<span class="sr-only">Choose profile photo</span>
<input type="file" name="profile_photo" id="profile_photo"
class="block w-full text-sm text-gray-500 dark:text-gray-300
file:mr-4 file:py-2 file:px-4
file:rounded-full file:border-0
file:text-sm file:font-semibold
file:bg-blue-50 file:text-blue-700
hover:file:bg-blue-100
dark:file:bg-gray-700 dark:file:text-white"
accept="image/*"
onchange="updatePreview(this)"/>
</label>
</div>
</div>
<!-- Email -->
<div class="mb-6">
<label for="email" class="block text-gray-700 dark:text-gray-200 text-sm font-bold mb-2">Email Address</label>
<input type="email" name="email" id="email" value="{{ Auth::user()->email }}"
class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 dark:text-gray-300 dark:bg-gray-700 leading-tight focus:outline-none focus:shadow-outline">
</div>
<!-- Password Change Section -->
<div class="mb-6">
<h3 class="text-lg font-semibold text-gray-700 dark:text-gray-200 mb-4">Change Password</h3>
<div class="space-y-4">
<div>
<label for="current_password" class="block text-gray-700 dark:text-gray-200 text-sm font-bold mb-2">Current Password</label>
<input type="password" name="current_password" id="current_password"
class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 dark:text-gray-300 dark:bg-gray-700 leading-tight focus:outline-none focus:shadow-outline">
</div>
<div>
<label for="new_password" class="block text-gray-700 dark:text-gray-200 text-sm font-bold mb-2">New Password</label>
<input type="password" name="new_password" id="new_password"
class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 dark:text-gray-300 dark:bg-gray-700 leading-tight focus:outline-none focus:shadow-outline">
</div>
<div>
<label for="new_password_confirmation" class="block text-gray-700 dark:text-gray-200 text-sm font-bold mb-2">Confirm New Password</label>
<input type="password" name="new_password_confirmation" id="new_password_confirmation"
class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 dark:text-gray-300 dark:bg-gray-700 leading-tight focus:outline-none focus:shadow-outline">
</div>
</div>
</div>
<!-- Submit Button -->
<div class="flex justify-end">
<button type="submit" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline">
Save Changes
</button>
</div>
</form>
</div>
</div>
<script>
function updatePreview(input) {
const file = input.files[0];
const preview = document.getElementById('preview');
if (file) {
const reader = new FileReader();
reader.onload = function(e) {
preview.src = e.target.result;
}
reader.readAsDataURL(file);
}
}
</script>
</body>
</html>

View File

@ -301,21 +301,130 @@ class="fixed inset-y-0 left-0 w-full max-w-xs bg-white dark:bg-gray-800 overflow
</div>
</div>
<!-- Firebase App (the core Firebase SDK) -->
<script src="https://www.gstatic.com/firebasejs/8.10.1/firebase-app.js"></script>
<!-- Firebase Database -->
<script src="https://www.gstatic.com/firebasejs/8.10.1/firebase-database.js"></script>
<!-- Firebase SDK v8 -->
<script src="https://www.gstatic.com/firebasejs/8.10.0/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.10.0/firebase-database.js"></script>
<script>
// Your web app's Firebase configuration
// Firebase configuration
const firebaseConfig = {
apiKey: "AIzaSyCr8xNQIsPpIUMGIR9wEGmG7hgMDKf2H5I",
authDomain: "smartcab-8bb42.firebaseapp.com",
databaseURL: "https://smartcab-8bb42-default-rtdb.firebaseio.com",
projectId: "smartcab-8bb42",
storageBucket: "smartcab-8bb42.firebasestorage.app",
messagingSenderId: "539751617121",
appId: "1:539751617121:web:3a899309fdb5e29efa9020",
measurementId: "G-BQPQLLCJTR"
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
const database = firebase.database();
let isUserAction = false;
// Function to update UI elements
function updateUIElement(elementId, value, suffix = '') {
const element = document.getElementById(elementId);
if (element) {
element.textContent = `${value}${suffix}`;
console.log(`Updated ${elementId} with value: ${value}${suffix}`);
} else {
console.error(`Element ${elementId} not found`);
}
}
// Function to update UI with new data
function updateUI(data) {
console.log('Updating UI with data:', data);
if (data.dht11) {
updateUIElement('temp-value', data.dht11.temperature, '°C');
updateUIElement('humidity-value', data.dht11.humidity, '%');
// Update chart if it exists
if (typeof sensorChart !== 'undefined') {
updateChart(Date.now(), data.dht11.temperature, data.dht11.humidity);
}
}
if (data.security) {
updateUIElement('motion-value', data.security.motion);
updateUIElement('status-value', data.security.status);
const toggle = document.getElementById('securityToggle');
if (toggle) {
toggle.checked = data.security.status === 'on';
}
}
}
// Function to fetch and update data
function fetchAndUpdateData() {
fetch('https://smartcab-8bb42-default-rtdb.firebaseio.com/.json')
.then(response => response.json())
.then(data => {
console.log('Data fetched successfully:', data);
updateUI(data);
})
.catch(error => {
console.error('Fetch error:', error);
});
}
// Function to toggle security status
function toggleSecurity(checkbox) {
isUserAction = true;
console.log('Toggle security called with state:', checkbox.checked);
const securityRef = database.ref('security/status');
const newStatus = checkbox.checked ? 'on' : 'off';
checkbox.disabled = true;
securityRef.set(newStatus)
.then(() => {
console.log('Security status updated successfully to:', newStatus);
updateUIElement('status-value', newStatus);
})
.catch((error) => {
console.error('Error updating security status:', error);
checkbox.checked = !checkbox.checked;
alert('Failed to update security status. Please try again.');
})
.finally(() => {
checkbox.disabled = false;
setTimeout(() => {
isUserAction = false;
}, 1000);
});
}
// Listen for security status changes
database.ref('security/status').on('value', (snapshot) => {
const status = snapshot.val();
if (status && !isUserAction) {
console.log('Security status updated:', status);
updateUIElement('status-value', status);
const securityToggle = document.getElementById('securityToggle');
if (securityToggle && !securityToggle.disabled) {
securityToggle.checked = status === 'on';
}
}
});
// Initialize when document is ready
document.addEventListener('DOMContentLoaded', () => {
console.log('Document ready, initializing...');
fetchAndUpdateData();
setInterval(fetchAndUpdateData, 1000);
// Initialize charts
initializeCharts();
});
// Initialize the chart with empty data
const ctx = document.getElementById('sensorChart').getContext('2d');
const sensorChart = new Chart(ctx, {
@ -394,13 +503,6 @@ function updateChart(timestamp, temperature, humidity) {
sensorChart.update();
}
// Listen for real-time updates
database.ref('dht11').on('value', (snapshot) => {
const data = snapshot.val();
const timestamp = Date.now();
updateChart(timestamp, data.temperature, data.humidity);
});
// Mobile Menu Toggle
const mobileMenuBtn = document.getElementById('mobileMenuBtn');
const mobileMenu = document.getElementById('mobileMenu');
@ -556,29 +658,6 @@ function initializeCharts() {
});
}
initializeCharts();
// Real-time listeners for sensor data
const dbRef = firebase.database();
// DHT11 Sensor listener
dbRef.ref('dht11').on('value', (snapshot) => {
const data = snapshot.val();
if (data) {
document.getElementById('temp-value').textContent = `${data.temperature}°C`;
document.getElementById('humidity-value').textContent = `${data.humidity}%`;
}
});
// Security listener
dbRef.ref('security').on('value', (snapshot) => {
const data = snapshot.val();
if (data) {
document.getElementById('motion-value').textContent = data.motion;
document.getElementById('status-value').textContent = data.status;
}
});
// Add these functions to your existing script
function toggleModal() {
const modal = document.getElementById('controlModal');
@ -586,26 +665,12 @@ function toggleModal() {
// Update toggle state when modal opens
if (!modal.classList.contains('hidden')) {
dbRef.ref('security/status').once('value', (snapshot) => {
database.ref('security/status').once('value', (snapshot) => {
const status = snapshot.val();
document.getElementById('securityToggle').checked = status === 'on';
});
}
}
function toggleSecurity(checkbox) {
const newStatus = checkbox.checked ? 'on' : 'off';
dbRef.ref('security').update({
status: newStatus
});
}
// Listen for security status changes
dbRef.ref('security/status').on('value', (snapshot) => {
const status = snapshot.val();
document.getElementById('securityToggle').checked = status === 'on';
document.getElementById('status-value').textContent = status;
});
</script>
</body>
</html>

View File

@ -4,6 +4,7 @@
use App\Http\Controllers\Auth\FirebaseAuthController;
use App\Http\Controllers\AIChatController;
use App\Http\Controllers\WelcomeController;
use App\Http\Controllers\ProfileController;
Route::get('/login', [FirebaseAuthController::class, 'showLogin'])
->name('login')
@ -30,3 +31,6 @@
}
return view('auth.login');
});
Route::get('/profile', [ProfileController::class, 'index'])->name('profile');
Route::post('/profile/update', [ProfileController::class, 'update'])->name('profile.update');