feat: Add SMTP settings and collapsible email configuration UI

- Add SMTP fields to TicketEmailSettings model (host, port, TLS/SSL, credentials, from email/name)
- Update serializers with SMTP fields and is_smtp_configured flag
- Add TicketEmailTestSmtpView for testing SMTP connections
- Update frontend API types and hooks for SMTP settings
- Add collapsible IMAP and SMTP configuration sections with "Configured" badges
- Fix TypeScript errors in mockData.ts (missing required fields, type mismatches)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
poduck
2025-11-29 18:28:29 -05:00
parent 0c7d76e264
commit cfc1b36ada
94 changed files with 13419 additions and 1121 deletions

View File

@@ -0,0 +1,106 @@
/**
* React Query hooks for ticket email settings
*/
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import {
getTicketEmailSettings,
updateTicketEmailSettings,
testImapConnection,
testSmtpConnection,
fetchEmailsNow,
getIncomingEmails,
reprocessIncomingEmail,
TicketEmailSettings,
TicketEmailSettingsUpdate,
IncomingTicketEmail,
} from '../api/ticketEmailSettings';
const QUERY_KEY = 'ticketEmailSettings';
const INCOMING_EMAILS_KEY = 'incomingTicketEmails';
/**
* Hook to fetch ticket email settings
*/
export const useTicketEmailSettings = () => {
return useQuery<TicketEmailSettings>({
queryKey: [QUERY_KEY],
queryFn: getTicketEmailSettings,
});
};
/**
* Hook to update ticket email settings
*/
export const useUpdateTicketEmailSettings = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (data: TicketEmailSettingsUpdate) => updateTicketEmailSettings(data),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: [QUERY_KEY] });
},
});
};
/**
* Hook to test IMAP connection
*/
export const useTestImapConnection = () => {
return useMutation({
mutationFn: testImapConnection,
});
};
/**
* Hook to test SMTP connection
*/
export const useTestSmtpConnection = () => {
return useMutation({
mutationFn: testSmtpConnection,
});
};
// Legacy alias
export const useTestEmailConnection = useTestImapConnection;
/**
* Hook to manually fetch emails
*/
export const useFetchEmailsNow = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: fetchEmailsNow,
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: [QUERY_KEY] });
queryClient.invalidateQueries({ queryKey: [INCOMING_EMAILS_KEY] });
},
});
};
/**
* Hook to fetch incoming email audit log
*/
export const useIncomingEmails = (params?: { status?: string; ticket?: number }) => {
return useQuery<IncomingTicketEmail[]>({
queryKey: [INCOMING_EMAILS_KEY, params],
queryFn: () => getIncomingEmails(params),
});
};
/**
* Hook to reprocess a failed incoming email
*/
export const useReprocessIncomingEmail = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (id: number) => reprocessIncomingEmail(id),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: [INCOMING_EMAILS_KEY] });
},
});
};
export type { TicketEmailSettings, TicketEmailSettingsUpdate, IncomingTicketEmail };

View File

@@ -46,6 +46,29 @@ export const useStaffForAssignment = () => {
});
};
/**
* Hook to fetch platform staff members for ticket assignment.
* Returns platform admins (superuser, platform_manager, platform_support) formatted for dropdown use.
*/
export const usePlatformStaffForAssignment = () => {
return useQuery<{ id: string; name: string; email: string; role: string }[]>({
queryKey: ['platformStaffForAssignment'],
queryFn: async () => {
const response = await apiClient.get('/api/platform/users/');
// Filter to only platform-level roles and format for dropdown
const platformRoles = ['superuser', 'platform_manager', 'platform_support'];
return response.data
.filter((user: { role: string }) => platformRoles.includes(user.role))
.map((user: { id: number; name?: string; email: string; role: string }) => ({
id: String(user.id),
name: user.name || user.email,
email: user.email,
role: user.role,
}));
},
});
};
/**
* Hook to update a staff member's permissions
*/