// ==========================================
// CLOUDPRIME FRONTEND COMPONENT SYSTEM
// ==========================================
/**
* Core Application Class
*/
class CloudPrimeApp {
constructor() {
this.config = {
apiBaseUrl: '/api/v1',
wsUrl: 'wss://yourserver.com/ws',
theme: localStorage.getItem('cp_theme') || 'light'
};
this.state = {
user: null,
isAuthenticated: false,
currentView: 'public',
notifications: []
};
this.components = {};
this.init();
}
async init() {
await this.loadConfig();
this.initializeTheme();
this.registerComponents();
this.setupEventListeners();
this.checkAuthentication();
}
async loadConfig() {
try {
const response = await fetch(`${this.config.apiBaseUrl}/config`);
const config = await response.json();
this.config = { ...this.config, ...config };
} catch (error) {
console.error('Failed to load config:', error);
}
}
registerComponents() {
this.components = {
navbar: new NavbarComponent(this),
hero: new HeroComponent(this),
services: new ServicesComponent(this),
pricing: new PricingComponent(this),
connectivity: new ConnectivityComponent(this),
footer: new FooterComponent(this),
chatbot: new ChatbotComponent(this),
admin: new AdminDashboard(this)
};
}
initializeTheme() {
document.body.setAttribute('data-bs-theme', this.config.theme);
this.updateThemeIcon();
}
toggleTheme() {
const newTheme = this.config.theme === 'light' ? 'dark' : 'light';
this.config.theme = newTheme;
localStorage.setItem('cp_theme', newTheme);
document.body.setAttribute('data-bs-theme', newTheme);
this.updateThemeIcon();
}
updateThemeIcon() {
const icons = document.querySelectorAll('#theme-icon');
icons.forEach(icon => {
icon.className = this.config.theme === 'dark'
? 'bi bi-sun-fill'
: 'bi bi-moon-stars-fill';
});
}
switchView(view) {
this.state.currentView = view;
const publicEl = document.getElementById('public_site');
const adminEl = document.getElementById('admin_dashboard');
if (view === 'admin') {
if (!this.state.isAuthenticated) {
this.showLoginModal();
return;
}
publicEl.classList.add('d-none');
adminEl.classList.remove('d-none');
this.components.admin.init();
} else {
publicEl.classList.remove('d-none');
adminEl.classList.add('d-none');
}
}
async checkAuthentication() {
try {
const token = localStorage.getItem('cp_auth_token');
if (!token) return;
const response = await fetch(`${this.config.apiBaseUrl}/auth/verify`, {
headers: { 'Authorization': `Bearer ${token}` }
});
if (response.ok) {
this.state.user = await response.json();
this.state.isAuthenticated = true;
}
} catch (error) {
console.error('Auth check failed:', error);
}
}
showLoginModal() {
const modal = new LoginModal(this);
modal.show();
}
setupEventListeners() {
// Global event delegation
document.addEventListener('click', (e) => {
if (e.target.matches('[data-action]')) {
const action = e.target.dataset.action;
this.handleAction(action, e.target);
}
});
// Theme toggle
document.addEventListener('click', (e) => {
if (e.target.closest('.theme-toggle')) {
this.toggleTheme();
}
});
}
handleAction(action, element) {
const actions = {
'switch-to-admin': () => this.switchView('admin'),
'switch-to-public': () => this.switchView('public'),
'logout': () => this.logout(),
'open-chatbot': () => this.components.chatbot.toggle()
};
if (actions[action]) {
actions[action]();
}
}
async logout() {
localStorage.removeItem('cp_auth_token');
this.state.isAuthenticated = false;
this.state.user = null;
this.switchView('public');
this.showToast('Logged out successfully', 'success');
}
showToast(message, type = 'info') {
const toast = document.createElement('div');
toast.className = `toast align-items-center text-white bg-${type} border-0`;
toast.innerHTML = `
`;
const container = document.getElementById('toast-container') || this.createToastContainer();
container.appendChild(toast);
const bsToast = new bootstrap.Toast(toast);
bsToast.show();
toast.addEventListener('hidden.bs.toast', () => toast.remove());
}
createToastContainer() {
const container = document.createElement('div');
container.id = 'toast-container';
container.className = 'position-fixed bottom-0 end-0 p-3';
container.style.zIndex = '11000';
document.body.appendChild(container);
return container;
}
}
/**
* Base Component Class
*/
class BaseComponent {
constructor(app) {
this.app = app;
this.element = null;
}
render() {
throw new Error('render() must be implemented');
}
update() {
if (this.element) {
this.render();
}
}
destroy() {
if (this.element) {
this.element.remove();
this.element = null;
}
}
}
/**
* Hero Component with Typing Effect
*/
class HeroComponent extends BaseComponent {
constructor(app) {
super(app);
this.typingTexts = [
'Intelligent Tech',
'Smart Solutions',
'AI-Powered Tools',
'Cloud Innovation'
];
this.currentIndex = 0;
this.isDeleting = false;
this.charIndex = 0;
this.initTypingEffect();
}
initTypingEffect() {
const element = document.getElementById('typing-text');
if (!element) return;
this.element = element;
this.typeEffect();
}
typeEffect() {
const currentText = this.typingTexts[this.currentIndex];
const displayText = this.isDeleting
? currentText.substring(0, this.charIndex--)
: currentText.substring(0, this.charIndex++);
if (this.element) {
this.element.textContent = displayText;
if (!this.isDeleting && this.charIndex === currentText.length + 1) {
this.isDeleting = true;
setTimeout(() => this.typeEffect(), 2000);
} else if (this.isDeleting && this.charIndex === 0) {
this.isDeleting = false;
this.currentIndex = (this.currentIndex + 1) % this.typingTexts.length;
setTimeout(() => this.typeEffect(), 500);
} else {
setTimeout(() => this.typeEffect(), this.isDeleting ? 50 : 100);
}
}
}
}
/**
* Connectivity Checker Component
*/
class ConnectivityComponent extends BaseComponent {
constructor(app) {
super(app);
this.setupChecker();
}
setupChecker() {
const form = document.querySelector('#connectivity form');
if (!form) return;
form.addEventListener('submit', (e) => {
e.preventDefault();
this.checkAvailability(new FormData(e.target));
});
}
async checkAvailability(formData) {
const address = formData.get('address') ||
document.querySelector('#connectivity input[type="text"]')?.value;
if (!address) {
this.app.showToast('Please enter an address', 'warning');
return;
}
this.app.showToast('Checking coverage...', 'info');
try {
const response = await fetch(`${this.app.config.apiBaseUrl}/connectivity/check`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ address })
});
const data = await response.json();
if (data.success) {
this.showResults(data.results);
} else {
this.app.showToast('No coverage found at this location', 'warning');
}
} catch (error) {
this.app.showToast('Failed to check coverage. Please try again.', 'danger');
}
}
showResults(results) {
const message = `
Coverage Available!
Fibre: ${results.fibre ? '✓ Available' : '✗ Not available'}
LTE: ${results.lte ? '✓ Available' : '✗ Not available'}
5G: ${results.fiveG ? '✓ Available' : '✗ Not available'}
`;
this.app.showToast(message, 'success');
}
}
/**
* Login Modal Component
*/
class LoginModal {
constructor(app) {
this.app = app;
this.modal = null;
this.create();
}
create() {
const modalHtml = `
`;
const container = document.createElement('div');
container.innerHTML = modalHtml;
document.body.appendChild(container.firstElementChild);
this.modal = new bootstrap.Modal(document.getElementById('loginModal'));
this.setupForm();
}
setupForm() {
const form = document.getElementById('loginForm');
form.addEventListener('submit', async (e) => {
e.preventDefault();
await this.handleLogin(new FormData(e.target));
});
}
async handleLogin(formData) {
const errorEl = document.getElementById('loginError');
errorEl.classList.add('d-none');
try {
const response = await fetch(`${this.app.config.apiBaseUrl}/auth/login`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
username: formData.get('username'),
password: formData.get('password')
})
});
const data = await response.json();
if (response.ok) {
localStorage.setItem('cp_auth_token', data.token);
this.app.state.user = data.user;
this.app.state.isAuthenticated = true;
this.modal.hide();
this.app.switchView('admin');
this.app.showToast('Login successful!', 'success');
} else {
errorEl.textContent = data.message || 'Invalid credentials';
errorEl.classList.remove('d-none');
}
} catch (error) {
errorEl.textContent = 'Connection error. Please try again.';
errorEl.classList.remove('d-none');
}
}
show() {
this.modal.show();
}
}
/**
* API Service Layer
*/
class APIService {
constructor(baseUrl) {
this.baseUrl = baseUrl;
}
async request(endpoint, options = {}) {
const token = localStorage.getItem('cp_auth_token');
const headers = {
'Content-Type': 'application/json',
...(token && { 'Authorization': `Bearer ${token}` }),
...options.headers
};
try {
const response = await fetch(`${this.baseUrl}${endpoint}`, {
...options,
headers
});
if (response.status === 401) {
localStorage.removeItem('cp_auth_token');
window.location.reload();
return;
}
return await response.json();
} catch (error) {
console.error('API Request failed:', error);
throw error;
}
}
get(endpoint) {
return this.request(endpoint);
}
post(endpoint, data) {
return this.request(endpoint, {
method: 'POST',
body: JSON.stringify(data)
});
}
put(endpoint, data) {
return this.request(endpoint, {
method: 'PUT',
body: JSON.stringify(data)
});
}
delete(endpoint) {
return this.request(endpoint, {
method: 'DELETE'
});
}
}
// Initialize App on DOM Ready
let app;
document.addEventListener('DOMContentLoaded', () => {
app = new CloudPrimeApp();
window.CloudPrime = app; // Expose globally for debugging
});
// Export for module usage
if (typeof module !== 'undefined' && module.exports) {
module.exports = { CloudPrimeApp, APIService };
}