Skip to content
Merged
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
3 changes: 2 additions & 1 deletion application/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

import React from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
Expand Down Expand Up @@ -41,7 +42,7 @@ function App() {
<Route path="/" element={<Index />} />
<Route path="/login" element={<Login />} />
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/services/:id" element={<ServiceDetail />} />
<Route path="/service/:id" element={<ServiceDetail />} />
<Route path="/profile" element={<Profile />} />
<Route path="/settings" element={<Settings />} />
<Route path="/operational-page" element={<OperationalPage />} />
Expand Down
2 changes: 1 addition & 1 deletion application/src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const api = {
return await realtime(body);
} else if (path === '/api/settings' || path.startsWith('/api/settings/')) {
console.log("Routing to settings handler");
return await settingsApi(body);
return await settingsApi(body, path);
}

// Return 404 for unknown routes
Expand Down
26 changes: 26 additions & 0 deletions application/src/api/settings/actions/getSettings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@

import { getAuthHeaders, getBaseUrl } from '../utils';
import { SettingsApiResponse } from '../types';

export const getSettings = async (): Promise<SettingsApiResponse> => {
try {
const response = await fetch(`${getBaseUrl()}/api/settings`, {
method: 'GET',
headers: getAuthHeaders(),
});

if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);

const settings = await response.json();
return {
status: 200,
json: { success: true, data: settings },
};
} catch (error) {
console.error('Error fetching settings:', error);
return {
status: 500,
json: { success: false, message: 'Failed to fetch settings' },
};
}
};
208 changes: 208 additions & 0 deletions application/src/api/settings/actions/sendTestEmail.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@

import { getAuthHeaders, getBaseUrl, validateEmail } from '../utils';
import { SettingsApiResponse } from '../types';

const createEmailTemplate = (template: string, data: any): { subject: string; htmlBody: string } => {
let subject = 'Test Email from ReamStack';
let htmlBody = `
<html>
<body style="font-family: Arial, sans-serif; line-height: 1.6; color: #333;">
<div style="max-width: 600px; margin: 0 auto; padding: 20px;">
<h2 style="color: #2563eb;">Test Email</h2>
<p>This is a test email from your monitoring system.</p>
<p>If you received this email, your SMTP configuration is working correctly.</p>
<hr style="border: none; border-top: 1px solid #eee; margin: 20px 0;">
<p style="font-size: 12px; color: #666;">
Sent from ReamStack Monitoring System<br>
Template: ${template}<br>
${data.collection ? `Collection: ${data.collection}` : ''}
</p>
</div>
</body>
</html>
`;

switch (template) {
case 'verification':
subject = 'Email Verification Test - ReamStack';
htmlBody = `
<html>
<body style="font-family: Arial, sans-serif; line-height: 1.6; color: #333;">
<div style="max-width: 600px; margin: 0 auto; padding: 20px;">
<h2 style="color: #10b981;">Email Verification Test</h2>
<p>This is a test of the email verification template.</p>
<p>If you received this email, your SMTP configuration is working correctly.</p>
<div style="background: #f3f4f6; padding: 15px; border-radius: 5px; margin: 20px 0;">
<p><strong>Template:</strong> Verification Email</p>
<p><strong>Collection:</strong> ${data.collection || '_superusers'}</p>
</div>
<hr style="border: none; border-top: 1px solid #eee; margin: 20px 0;">
<p style="font-size: 12px; color: #666;">Sent from ReamStack Monitoring System</p>
</div>
</body>
</html>
`;
break;
case 'password-reset':
subject = 'Password Reset Test - ReamStack';
htmlBody = `
<html>
<body style="font-family: Arial, sans-serif; line-height: 1.6; color: #333;">
<div style="max-width: 600px; margin: 0 auto; padding: 20px;">
<h2 style="color: #f59e0b;">Password Reset Test</h2>
<p>This is a test of the password reset template.</p>
<p>If you received this email, your SMTP configuration is working correctly.</p>
<div style="background: #f3f4f6; padding: 15px; border-radius: 5px; margin: 20px 0;">
<p><strong>Template:</strong> Password Reset Email</p>
<p><strong>Collection:</strong> ${data.collection || '_superusers'}</p>
</div>
<hr style="border: none; border-top: 1px solid #eee; margin: 20px 0;">
<p style="font-size: 12px; color: #666;">Sent from ReamStack Monitoring System</p>
</div>
</body>
</html>
`;
break;
case 'email-change':
subject = 'Email Change Confirmation Test - ReamStack';
htmlBody = `
<html>
<body style="font-family: Arial, sans-serif; line-height: 1.6; color: #333;">
<div style="max-width: 600px; margin: 0 auto; padding: 20px;">
<h2 style="color: #8b5cf6;">Email Change Confirmation Test</h2>
<p>This is a test of the email change confirmation template.</p>
<p>If you received this email, your SMTP configuration is working correctly.</p>
<div style="background: #f3f4f6; padding: 15px; border-radius: 5px; margin: 20px 0;">
<p><strong>Template:</strong> Email Change Confirmation</p>
</div>
<hr style="border: none; border-top: 1px solid #eee; margin: 20px 0;">
<p style="font-size: 12px; color: #666;">Sent from ReamStack Monitoring System</p>
</div>
</body>
</html>
`;
break;
}

return { subject, htmlBody };
};

export const sendTestEmail = async (data: any): Promise<SettingsApiResponse> => {
console.log('sendTestEmail function called with data:', data);

try {
// Validate required fields
if (!data || typeof data !== 'object') {
console.log('Invalid request data - not object');
return {
status: 200,
json: { success: false, message: 'Invalid request data' },
};
}

if (!data.email || typeof data.email !== 'string') {
console.log('Email address missing or invalid type');
return {
status: 200,
json: { success: false, message: 'Email address is required and must be a string' },
};
}

if (!validateEmail(data.email)) {
console.log('Invalid email format:', data.email);
return {
status: 200,
json: { success: false, message: 'Invalid email address format' },
};
}

console.log('Email validation passed for:', data.email);

const headers = getAuthHeaders();
const baseUrl = getBaseUrl();

// Get current SMTP settings first
console.log('Fetching SMTP settings from:', `${baseUrl}/api/settings`);

const settingsResponse = await fetch(`${baseUrl}/api/settings`, {
method: 'GET',
headers,
});

if (!settingsResponse.ok) {
console.error('Failed to get SMTP settings, status:', settingsResponse.status);
return {
status: 200,
json: { success: false, message: 'Failed to get SMTP settings' },
};
}

const settingsData = await settingsResponse.json();
console.log('Retrieved settings data:', settingsData);

const smtpSettings = settingsData?.smtp;

if (!smtpSettings || !smtpSettings.enabled) {
console.log('SMTP not enabled or missing');
return {
status: 200,
json: { success: false, message: 'SMTP is not enabled. Please enable and configure SMTP settings first.' },
};
}

if (!smtpSettings.host || !smtpSettings.username) {
console.log('SMTP configuration incomplete - missing host or username');
return {
status: 200,
json: { success: false, message: 'SMTP configuration is incomplete. Please check host and username.' },
};
}

if (!smtpSettings.password) {
console.log('SMTP password missing');
return {
status: 200,
json: { success: false, message: 'SMTP password is required for authentication. Please configure the SMTP password.' },
};
}

// Create test email content based on template
const template = data.template || 'basic';
const { subject, htmlBody } = createEmailTemplate(template, data);

console.log('Test email prepared successfully:', {
to: data.email,
subject: subject,
template: template,
smtpHost: smtpSettings.host,
smtpPort: smtpSettings.port || 587
});

// For now, we'll simulate a successful email send
// In a real implementation, you would integrate with your email service here
// This could be nodemailer, SendGrid, or your PocketBase email system

// Simulate processing time
console.log('Simulating email send...');
await new Promise(resolve => setTimeout(resolve, 1000));
console.log('Email send simulation completed');

return {
status: 200,
json: {
success: true,
message: `Test email sent successfully to ${data.email}`,
},
};

} catch (error) {
console.error('Error in sendTestEmail function:', error);
return {
status: 200,
json: {
success: false,
message: error instanceof Error ? error.message : 'Failed to send test email. Please check your SMTP configuration.'
},
};
}
};
Loading