feat: Initialize License Tracker Pro v1.2 project
Adds initial project structure, dependencies, and basic configuration for the License Tracker Pro v1.2 application. This includes setting up Vite for the build process, defining core types, and incorporating essential UI components like icons and a timeline. The project is now ready for development.
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
import { License, User, AuditLog, Contact, NotificationGroup, AppSettings, AIInsight } from './types';
|
||||
import { GoogleGenAI, Type } from "@google/genai";
|
||||
|
||||
const API_URL = 'api.php';
|
||||
|
||||
export const DEFAULT_SETTINGS: AppSettings = {
|
||||
fiscal_start_month: 4, alert_days: 45, smtp_host: '', smtp_port: '465',
|
||||
smtp_user: '', smtp_pass: '', smtp_from: '', azure_enabled: false,
|
||||
azure_tenant_id: '', azure_client_id: '', azure_client_secret: '',
|
||||
ldap_enabled: false, ldap_host: '', ldap_port: '389', ldap_base_dn: '',
|
||||
ldap_bind_dn: '', ldap_bind_pass: '', ldap_user_filter: '', allow_local_login: true
|
||||
};
|
||||
|
||||
async function handleResponse(response: Response) {
|
||||
const text = await response.text();
|
||||
let json;
|
||||
try {
|
||||
json = text ? JSON.parse(text) : null;
|
||||
} catch(e) {
|
||||
console.error("Failed to parse JSON response. Status:", response.status, "Text:", text.substring(0, 100));
|
||||
json = null;
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
const errorMsg = json?.error || `Server Error (${response.status}): ${text.substring(0, 50)}`;
|
||||
throw new Error(errorMsg);
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
export const checkSession = async () => handleResponse(await fetch(`${API_URL}?action=check_session`));
|
||||
export const login = async (username: string, password: string, authSource: string = 'local') =>
|
||||
handleResponse(await fetch(`${API_URL}?action=login`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ username, password, authSource })
|
||||
}));
|
||||
|
||||
export const logout = async () => handleResponse(await fetch(`${API_URL}?action=logout`));
|
||||
export const fetchLicenses = async () => handleResponse(await fetch(`${API_URL}?action=list`));
|
||||
export const fetchSettings = async () => handleResponse(await fetch(`${API_URL}?action=settings_get`));
|
||||
|
||||
export const saveLicense = async (license: any) => {
|
||||
return handleResponse(await fetch(`${API_URL}?action=save`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(license)
|
||||
}));
|
||||
};
|
||||
|
||||
export const deleteLicense = async (id: string) => handleResponse(await fetch(`${API_URL}?action=delete&id=${id}`, { method: 'POST' }));
|
||||
export const saveSettings = async (settings: AppSettings) => handleResponse(await fetch(`${API_URL}?action=settings_save`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(settings) }));
|
||||
|
||||
export const fetchUsers = async () => handleResponse(await fetch(`${API_URL}?action=users_list`));
|
||||
export const createUser = async (u: any) => handleResponse(await fetch(`${API_URL}?action=users_create`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(u) }));
|
||||
export const updateUser = async (id: number, u: any) => handleResponse(await fetch(`${API_URL}?action=users_update&id=${id}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(u) }));
|
||||
export const deleteUser = async (id: number) => handleResponse(await fetch(`${API_URL}?action=users_delete&id=${id}`, { method: 'POST' }));
|
||||
|
||||
export const fetchGroups = async () => handleResponse(await fetch(`${API_URL}?action=groups_list`));
|
||||
export const saveGroup = async (g: any) => handleResponse(await fetch(`${API_URL}?action=groups_save`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(g) }));
|
||||
export const deleteGroup = async (id: number) => handleResponse(await fetch(`${API_URL}?action=groups_delete&id=${id}`, { method: 'POST' }));
|
||||
|
||||
export const fetchContacts = async () => handleResponse(await fetch(`${API_URL}?action=contacts_list`));
|
||||
export const saveContact = async (c: any) => handleResponse(await fetch(`${API_URL}?action=contacts_save`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(c) }));
|
||||
export const deleteContact = async (id: number) => handleResponse(await fetch(`${API_URL}?action=contacts_delete&id=${id}`, { method: 'POST' }));
|
||||
|
||||
export const fetchLogs = async () => handleResponse(await fetch(`${API_URL}?action=logs_list`));
|
||||
|
||||
export async function getAIInsights(license: License): Promise<AIInsight> {
|
||||
try {
|
||||
const ai = new GoogleGenAI({ apiKey: process.env.API_KEY });
|
||||
const res = await ai.models.generateContent({
|
||||
model: 'gemini-3-pro-preview',
|
||||
contents: `Analyze this license for procurement risks: ${license.licenseName}, Vendor: ${license.vendorName}. Return JSON with status (saving/warning/neutral), advice, and suggested_alternatives.`,
|
||||
config: {
|
||||
responseMimeType: 'application/json',
|
||||
responseSchema: {
|
||||
type: Type.OBJECT,
|
||||
properties: {
|
||||
status: { type: Type.STRING },
|
||||
advice: { type: Type.STRING },
|
||||
suggested_alternatives: { type: Type.ARRAY, items: { type: Type.STRING } }
|
||||
},
|
||||
required: ["status", "advice", "suggested_alternatives"]
|
||||
}
|
||||
}
|
||||
});
|
||||
return JSON.parse(res.text || '{}');
|
||||
} catch (e) {
|
||||
return { status: 'neutral', advice: "Advice unavailable.", suggested_alternatives: [] };
|
||||
}
|
||||
}
|
||||
export const deleteFile = async (id: number) => handleResponse(await fetch(`${API_URL}?action=file_delete&id=${id}`, { method: 'POST' }));
|
||||
export const exportDatabase = async () => handleResponse(await fetch(`${API_URL}?action=export`));
|
||||
export const importDatabase = async (json: string) => handleResponse(await fetch(`${API_URL}?action=import`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: json }));
|
||||
export const sendTestEmail = async (email: string) => handleResponse(await fetch(`${API_URL}?action=test_email`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email }) }));
|
||||
export const runNotifications = async () => handleResponse(await fetch(`${API_URL}?action=run_notifications`));
|
||||
export const getAzureLoginUrl = async () => ({ url: '#' });
|
||||
export const resetPassword = async (token: string, password: string) => handleResponse(await fetch(`${API_URL}?action=reset_password`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ token, password }) }));
|
||||
Reference in New Issue
Block a user