profile view

This commit is contained in:
2026-04-03 13:40:06 +05:30
parent aa04b105d0
commit 399b2656b8
7 changed files with 95 additions and 5 deletions

View File

@@ -64,6 +64,8 @@ function Dashboard() {
);
}
import ProfileView from "./components/ProfileView";
function AdminApp() {
const { currentUser, login, logout, loading, error } = useAuth();
const config = React.useContext(ConfigContext);
@@ -93,6 +95,7 @@ function AdminApp() {
>
<Routes>
<Route path="/" element={<Dashboard />} />
<Route path="/profile" element={<ProfileView />} />
<Route path="/:resourceName" element={<ResourceRouteWrapper />} />
<Route path="/:resourceName/:id" element={<ResourceRouteWrapper />} />
<Route path="/:resourceName/create" element={<ResourceRouteWrapper />} />

View File

@@ -12,6 +12,7 @@ import {
ListItemIcon,
ListItemText,
CssBaseline,
Button,
IconButton,
Tooltip,
useMediaQuery,
@@ -176,9 +177,15 @@ export default function AdminLayout({
<Typography variant="h6" noWrap component="div" sx={{ flexGrow: 1, fontWeight: 'bold' }}>
Admin Panel
</Typography>
<Typography variant="body1" sx={{ mr: 2, fontWeight: 500, display: { xs: 'none', sm: 'block' } }}>
{username}
</Typography>
<Box sx={{ display: { xs: 'none', sm: 'flex' }, alignItems: 'center', mr: 2 }}>
<Button
color="inherit"
onClick={() => navigate('/profile')}
sx={{ textTransform: 'none', fontWeight: 500 }}
>
{username}
</Button>
</Box>
<Tooltip title="Logout">
<IconButton color="inherit" onClick={onLogout}>
<LogoutIcon />

View File

@@ -0,0 +1,58 @@
import * as React from 'react';
import { Box, Typography, Paper, CircularProgress, Alert } from '@mui/material';
import { useResource } from '../hooks/useResource';
import GenericForm from './GenericForm';
import { ConfigContext } from '../App';
export default function ProfileView() {
const appConfig = React.useContext(ConfigContext);
const profileConfig = appConfig?.profile;
const resourceConfig = appConfig?.resources.find(r => r.name === profileConfig?.resource);
if (!profileConfig || !resourceConfig) {
debugger;
return <Alert severity="error">Profile configuration not found.</Alert>;
}
const { useMe, useUpdate } = useResource(resourceConfig);
const { data: profile, isLoading, error } = useMe();
const updateMutation = useUpdate();
const handleSave = async (formData: any) => {
try {
const id = profile[resourceConfig.primaryKey];
await updateMutation.mutateAsync({ id, data: formData });
} catch (err) {
console.error('Profile update failed:', err);
}
};
if (isLoading) {
return (
<Box sx={{ display: 'flex', justifyContent: 'center', p: 4 }}>
<CircularProgress />
</Box>
);
}
if (error) {
return <Alert severity="error">Failed to load profile data.</Alert>;
}
return (
<Box sx={{ maxWidth: 800, mx: 'auto', mt: 4 }}>
<Typography variant="h4" gutterBottom>
My Profile
</Typography>
<Paper sx={{ p: 4, mt: 2 }}>
<GenericForm
config={resourceConfig}
initialData={profile}
onSave={handleSave}
onCancel={() => window.history.back()}
loading={updateMutation.isPending}
/>
</Paper>
</Box>
);
}

View File

@@ -40,3 +40,8 @@ export const configuration: Record<string, ResourceOverride> = {
},
},
};
export const profileConfiguration = {
"extraFields": ['name'],
"resource": "payors"
};

View File

@@ -81,9 +81,21 @@ export function useResource<T = any>(config: ResourceConfig) {
},
});
// --- READ ME ---
const useMe = () =>
useQuery({
queryKey: [name, "me"],
queryFn: async () => {
// @ts-ignore
const res = await api.get<T>(`${endpoint}/me`);
return res.data;
},
});
return {
useList,
useRead,
useMe,
useCreate,
useUpdate,
useDelete,

View File

@@ -35,4 +35,8 @@ export interface AppConfig {
baseUrl: string;
authBaseUrl: string;
resources: ResourceConfig[];
profile?: {
resource: string;
extraFields?: Record<string, any>;
};
}

View File

@@ -1,6 +1,6 @@
import SwaggerParser from "@apidevtools/swagger-parser";
import { AppConfig, ResourceConfig, ResourceField, FieldType } from "../types/config";
import { configuration } from "../configuration";
import { configuration, profileConfiguration } from "../configuration";
/**
* Maps OpenAPI property types to our internal FieldType
@@ -115,7 +115,7 @@ export async function loadConfigFromOpenApi(baseUrl: string): Promise<AppConfig>
resourcePaths[base].methods.push(...methods);
// Identify the list endpoint for this resource
if (!path.includes("{") && paths[path]?.get?.responses?.["200"]) {
if (!resourcePaths[base].listPath && !path.includes("{") && paths[path]?.get?.responses?.["200"]) {
resourcePaths[base].listPath = path;
}
}
@@ -170,5 +170,6 @@ export async function loadConfigFromOpenApi(baseUrl: string): Promise<AppConfig>
baseUrl: serverBaseUrl,
authBaseUrl: authBaseUrl,
resources,
profile: profileConfiguration,
};
}