Skip to content

Registration and login and logout #439

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
VITE_FIREBASE_API_KEY=AIzaSyDs0-gR5PrwDPRpyE6ZE0ua9sALYICwvcI
VITE_FIREBASE_AUTH_DOMAIN=tarbiyah-sms.firebaseapp.com
VITE_FIREBASE_PROJECT_ID=tarbiyah-sms
VITE_FIREBASE_STORAGE_BUCKET=tarbiyah-sms.firebasestorage.app
VITE_FIREBASE_MESSAGING_SENDER_ID=329966751488
VITE_FIREBASE_APP_ID=1:329966751488:web:e4d4fd53397e7c21ccede5
VITE_APP_FIREBASE_MEASUREMENT_ID=G-Y12T1TPW92
7 changes: 7 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
VITE_FIREBASE_API_KEY=AIzaSyDs0-gR5PrwDPRpyE6ZE0ua9sALYICwvcI
VITE_FIREBASE_AUTH_DOMAIN=tarbiyah-sms.firebaseapp.com
VITE_FIREBASE_PROJECT_ID=tarbiyah-sms
VITE_FIREBASE_STORAGE_BUCKET=tarbiyah-sms.firebasestorage.app
VITE_FIREBASE_MESSAGING_SENDER_ID=329966751488
VITE_FIREBASE_APP_ID=1:329966751488:web:e4d4fd53397e7c21ccede5
VITE_APP_FIREBASE_MEASUREMENT_ID=G-Y12T1TPW92
3 changes: 3 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
<!DOCTYPE html>
<<<<<<< Updated upstream
<!--
* CoreUI Free React.js Admin Template
* @version v5.4.0
* @link https://coreui.io/product/free-react-admin-template/
* Copyright (c) 2025 creativeLabs Łukasz Holeczek
* Licensed under MIT (https://github.com/coreui/coreui-free-react-admin-template/blob/main/LICENSE)
-->
=======
>>>>>>> Stashed changes
<html lang="en">
<head>
<meta charset="utf-8">
Expand Down
8 changes: 8 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,15 @@
"@popperjs/core": "^2.11.8",
"chart.js": "^4.4.7",
"classnames": "^2.5.1",
<<<<<<< Updated upstream
"core-js": "^3.40.0",
=======
"core-js": "^3.39.0",
"cors": "^2.8.5",
"express": "^4.21.2",
"firebase": "^11.2.0",
"firebase-admin": "^13.1.0",
>>>>>>> Stashed changes
"prop-types": "^15.8.1",
"react": "^19.0.0",
"react-dom": "^19.0.0",
Expand Down
13 changes: 13 additions & 0 deletions src/Actions/actions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export const loginSuccess = (user) => ({
type: 'LOGIN_SUCCESS',
payload: user,
});

export const logout = () => ({
type: 'LOGOUT',
});

export const setLoading = (loading) => ({
type: 'SET_LOADING',
payload: loading,
});
98 changes: 53 additions & 45 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -1,59 +1,67 @@
import React, { Suspense, useEffect } from 'react'
import { HashRouter, Route, Routes } from 'react-router-dom'
import { useSelector } from 'react-redux'
import React, { Suspense, useEffect } from 'react';
import { HashRouter, Route, Routes, Navigate } from 'react-router-dom';
import { CSpinner, useColorModes } from '@coreui/react';
import useAuth from './Firebase/useAuth';
import './scss/style.scss';
import './scss/examples.scss';

import { CSpinner, useColorModes } from '@coreui/react'
import './scss/style.scss'

// We use those styles to show code examples, you should remove them in your application.
import './scss/examples.scss'

// Containers
const DefaultLayout = React.lazy(() => import('./layout/DefaultLayout'))

// Pages
const Login = React.lazy(() => import('./views/pages/login/Login'))
const Register = React.lazy(() => import('./views/pages/register/Register'))
const Page404 = React.lazy(() => import('./views/pages/page404/Page404'))
const Page500 = React.lazy(() => import('./views/pages/page500/Page500'))
const DefaultLayout = React.lazy(() => import('./layout/DefaultLayout'));
const Login = React.lazy(() => import('./views/pages/login/Login'));
const Register = React.lazy(() => import('./views/pages/register/Register'));
const Page404 = React.lazy(() => import('./views/pages/page404/Page404'));
const Page500 = React.lazy(() => import('./views/pages/page500/Page500'));

const App = () => {
const { isColorModeSet, setColorMode } = useColorModes('coreui-free-react-admin-template-theme')
const storedTheme = useSelector((state) => state.theme)
const { isColorModeSet, setColorMode } = useColorModes('coreui-free-react-admin-template-theme');
const { user, loading } = useAuth();

useEffect(() => {
const urlParams = new URLSearchParams(window.___location.href.split('?')[1])
const theme = urlParams.get('theme') && urlParams.get('theme').match(/^[A-Za-z0-9\s]+/)[0]
if (theme) {
setColorMode(theme)
}
const urlParams = new URLSearchParams(window.___location.href.split('?')[1]);
const theme = urlParams.get('theme')?.match(/^[A-Za-z0-9\s]+/)?.[0];
if (theme) setColorMode(theme);
if (!isColorModeSet()) setColorMode('light');
}, [isColorModeSet, setColorMode]);

if (isColorModeSet()) {
return
}

setColorMode(storedTheme)
}, []) // eslint-disable-line react-hooks/exhaustive-deps
if (loading) {
return (
<div className="pt-3 text-center">
<CSpinner color="primary" variant="grow" />
</div>
);
}

return (
<HashRouter>
<Suspense
fallback={
<div className="pt-3 text-center">
<CSpinner color="primary" variant="grow" />
</div>
}
>
<Suspense fallback={
<div className="pt-3 text-center">
<CSpinner color="primary" variant="grow" />
</div>
}>
<Routes>
<Route exact path="/login" name="Login Page" element={<Login />} />
<Route exact path="/register" name="Register Page" element={<Register />} />
<Route exact path="/404" name="Page 404" element={<Page404 />} />
<Route exact path="/500" name="Page 500" element={<Page500 />} />
<Route path="*" name="Home" element={<DefaultLayout />} />
{/* Public routes */}
<Route
path="/login"
element={user ? <Navigate to="/" replace /> : <Login />}
/>
<Route path="/register" element={<Register />} />
<Route path="/404" element={<Page404 />} />
<Route path="/500" element={<Page500 />} />

{/* Protected routes */}
<Route
path="/*"
element={user ? <DefaultLayout /> : <Navigate to="/login" replace />}
/>

{/* Redirect unmatched routes */}
<Route
path="*"
element={<Navigate to={user ? "/" : "/login"} replace />}
/>
</Routes>
</Suspense>
</HashRouter>
)
}
);
};

export default App
export default App;
19 changes: 19 additions & 0 deletions src/Firebase/firebase.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { initializeApp } from "firebase/app";
import { getAnalytics } from "firebase/analytics";
import { getAuth } from "firebase/auth";
import { getFirestore } from "firebase/firestore";

const firebaseConfig = {
apiKey: import.meta.env.VITE_FIREBASE_API_KEY,
authDomain: import.meta.env.VITE_FIREBASE_AUTH_DOMAIN,
projectId: import.meta.env.VITE_FIREBASE_PROJECT_ID,
storageBucket: import.meta.env.VITE_FIREBASE_STORAGE_BUCKET,
messagingSenderId: import.meta.env.VITE_FIREBASE_MESSAGING_SENDER_ID,
appId: import.meta.env.VITE_FIREBASE_APP_ID,
};
const app = initializeApp(firebaseConfig);
const analytics = getAnalytics(app);
const auth = getAuth(app);
const firestore = getFirestore(app);

export { app, analytics, auth, firestore };
34 changes: 34 additions & 0 deletions src/Firebase/useAuth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { useEffect, useState } from 'react';
import { onAuthStateChanged, signOut as firebaseSignOut } from 'firebase/auth';
import { auth } from './firebase';

const useAuth = () => {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);

useEffect(() => {
const unsubscribe = onAuthStateChanged(auth, (user) => {
if (user) {
setUser(user);
} else {
setUser(null);
}
setLoading(false);
});

return () => unsubscribe();
}, []);

const signOut = async () => {
try {
await firebaseSignOut(auth);
} catch (error) {
console.error("Error signing out:", error);
throw error;
}
};

return { user, loading, signOut };
};

export default useAuth;
19 changes: 16 additions & 3 deletions src/components/header/AppHeaderDropdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,23 @@ import {
cilUser,
} from '@coreui/icons'
import CIcon from '@coreui/icons-react'

import { useNavigate } from 'react-router-dom';
import useAuth from '../../Firebase/useAuth'
import avatar8 from './../../assets/images/avatars/8.jpg'

const AppHeaderDropdown = () => {
const { signOut } = useAuth();
const navigate = useNavigate();

const handleLogout = async () => {
try {
await signOut();
navigate('/login');
} catch (error) {
console.error('Logout error:', error);
}
};

return (
<CDropdown variant="nav-item">
<CDropdownToggle placement="bottom-end" className="py-0 pe-0" caret={false}>
Expand Down Expand Up @@ -84,9 +97,9 @@ const AppHeaderDropdown = () => {
</CBadge>
</CDropdownItem>
<CDropdownDivider />
<CDropdownItem href="#">
<CDropdownItem onClick={handleLogout}>
<CIcon icon={cilLockLocked} className="me-2" />
Lock Account
Log Out
</CDropdownItem>
</CDropdownMenu>
</CDropdown>
Expand Down
Loading