add custom email field

This commit is contained in:
chark1es 2025-03-08 23:23:30 -08:00
parent 8da2ffb4f1
commit 44e3f6e7ff
3 changed files with 174 additions and 0 deletions

View file

@ -5,6 +5,7 @@ import AccountSecuritySettings from "./SettingsSection/AccountSecuritySettings";
import NotificationSettings from "./SettingsSection/NotificationSettings";
import DisplaySettings from "./SettingsSection/DisplaySettings";
import ResumeSettings from "./SettingsSection/ResumeSettings";
import EmailRequestSettings from "./SettingsSection/EmailRequestSettings";
// Import environment variables
const logtoAppId = import.meta.env.LOGTO_APP_ID;
@ -119,6 +120,25 @@ const safeLogtoApiEndpoint = logtoApiEndpoint || "";
</div>
</div>
<!-- IEEE Email Request Card -->
<div
class="card bg-base-100 shadow-xl border border-base-200 hover:border-primary transition-all duration-300 hover:-translate-y-1 transform mb-6"
>
<div class="card-body">
<h3 class="card-title flex items-center gap-3">
<div class="badge badge-primary p-3">
<Icon name="heroicons:envelope" class="h-5 w-5" />
</div>
IEEE Email Address
</h3>
<p class="text-sm opacity-70 mb-4">
Request an official IEEE UCSD email address (officers only)
</p>
<div class="divider"></div>
<EmailRequestSettings client:load />
</div>
</div>
<!-- Account Security Settings Card -->
<div
class="card bg-base-100 shadow-xl border border-base-200 hover:border-primary transition-all duration-300 hover:-translate-y-1 transform mb-6"

View file

@ -0,0 +1,153 @@
import { useState, useEffect } from 'react';
import { Authentication } from '../../../scripts/pocketbase/Authentication';
import { Update } from '../../../scripts/pocketbase/Update';
import { Collections, type User } from '../../../schemas/pocketbase/schema';
import { toast } from 'react-hot-toast';
export default function EmailRequestSettings() {
const auth = Authentication.getInstance();
const update = Update.getInstance();
const [user, setUser] = useState<User | null>(null);
const [loading, setLoading] = useState(true);
const [requesting, setRequesting] = useState(false);
const [isOfficer, setIsOfficer] = useState(false);
useEffect(() => {
const loadUserData = async () => {
try {
setLoading(true);
const currentUser = auth.getCurrentUser();
if (!currentUser) {
toast.error('You must be logged in to access this page');
return;
}
setUser(currentUser);
// Check if user is an officer
const pb = auth.getPocketBase();
try {
const officerRecord = await pb.collection('officers').getFirstListItem(`user="${currentUser.id}"`);
if (officerRecord) {
setIsOfficer(true);
}
} catch (error) {
// Not an officer, which is fine
console.log('User is not an officer');
}
} catch (error) {
console.error('Error loading user data:', error);
toast.error('Failed to load user data. Please try again later.');
} finally {
setLoading(false);
}
};
loadUserData();
}, []);
const handleRequestEmail = async () => {
if (!user) return;
try {
setRequesting(true);
// Update the user record to mark email as requested
const pb = auth.getPocketBase();
await pb.collection(Collections.USERS).update(user.id, {
requested_email: true
});
// Refresh user data
const updatedUser = auth.getCurrentUser();
setUser(updatedUser);
toast.success('Email request submitted successfully! Our team will process your request soon.');
} catch (error) {
console.error('Error requesting email:', error);
toast.error('Failed to submit email request. Please try again later.');
} finally {
setRequesting(false);
}
};
if (loading) {
return (
<div className="flex justify-center items-center p-8">
<span className="loading loading-spinner loading-lg text-primary"></span>
</div>
);
}
if (!isOfficer) {
return (
<div className="alert alert-info">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" className="stroke-current shrink-0 w-6 h-6"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg>
<span>IEEE email addresses are only available to officers. If you are an officer and don't see the option to request an email, please contact the webmaster.</span>
</div>
);
}
if (user?.requested_email) {
return (
<div className="space-y-4">
<div className="alert alert-success">
<svg xmlns="http://www.w3.org/2000/svg" className="stroke-current shrink-0 h-6 w-6" fill="none" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>
<span>You have requested an IEEE email address. Our team is processing your request.</span>
</div>
<div className="card bg-base-200 p-4">
<h3 className="font-bold text-lg mb-2">What happens next?</h3>
<ol className="list-decimal list-inside space-y-2">
<li>Our webmaster will create your email address (typically firstname.lastname@ieeeucsd.org)</li>
<li>You'll receive an email with your credentials and setup instructions</li>
<li>You can use this email for IEEE-related communications</li>
</ol>
</div>
<div className="alert alert-info">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" className="stroke-current shrink-0 w-6 h-6"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg>
<span>If you have any questions or need help with your IEEE email, please contact <a href="mailto:webmaster@ieeeucsd.org" className="underline">webmaster@ieeeucsd.org</a></span>
</div>
</div>
);
}
return (
<div className="space-y-4">
<p className="text-sm">
As an IEEE officer, you're eligible for an official IEEE UCSD email address. This email can be used for all IEEE-related communications and provides a professional identity when representing the organization.
</p>
<div className="card bg-base-200 p-4">
<h3 className="font-bold text-lg mb-2">Benefits of an IEEE email:</h3>
<ul className="list-disc list-inside space-y-1">
<li>Professional communication with sponsors and partners</li>
<li>Consistent branding for IEEE UCSD</li>
<li>Separation between personal and IEEE communications</li>
<li>Access to IEEE UCSD shared resources</li>
</ul>
</div>
<button
className="btn btn-primary w-full"
onClick={handleRequestEmail}
disabled={requesting}
>
{requesting ? (
<>
<span className="loading loading-spinner loading-sm"></span>
Processing...
</>
) : (
'Request IEEE Email Address'
)}
</button>
<div className="text-xs opacity-70">
<p>By requesting an email, you agree to use it responsibly and in accordance with IEEE UCSD policies.</p>
<p>Email addresses are typically in the format firstname.lastname@ieeeucsd.org</p>
</div>
</div>
);
}

View file

@ -37,6 +37,7 @@ export interface User extends BaseRecord {
display_preferences?: string; // JSON string of display settings (theme, font size, etc.)
accessibility_settings?: string; // JSON string of accessibility settings (color blind mode, reduced motion)
resume?: string;
requested_email?: boolean; // Whether the user has requested an IEEE email address
}
/**