Refactor admin components to use atomic component library and add utilities

Co-authored-by: johndoe6345789 <224850594+johndoe6345789@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-01-08 15:20:10 +00:00
parent d7d5bbfb2b
commit ef1a912833
7 changed files with 283 additions and 28 deletions

View File

@@ -1,23 +1,21 @@
'use client';
import AddIcon from '@mui/icons-material/Add';
import DeleteIcon from '@mui/icons-material/Delete';
import { useState } from 'react';
import {
Box,
Button,
Checkbox,
Dialog,
DialogActions,
DialogContent,
DialogTitle,
FormControlLabel,
IconButton,
Checkbox,
MenuItem,
Select,
TextField,
Typography,
} from '@mui/material';
import { useState } from 'react';
} from '../atoms';
import Button from '../atoms/Button';
import TextField from '../atoms/TextField';
import Typography from '../atoms/Typography';
import IconButton from '../atoms/IconButton';
type Column = {
name: string;
@@ -141,21 +139,15 @@ export default function CreateTableDialog({
sx={{ mr: 1 }}
/>
{columns.length > 1 && (
<IconButton onClick={() => removeColumn(index)} color="error" size="small">
<DeleteIcon />
</IconButton>
<IconButton onClick={() => removeColumn(index)} color="error" size="small" icon="Delete" />
)}
</Box>
))}
<Button startIcon={<AddIcon />} onClick={addColumn} variant="outlined">
Add Column
</Button>
<Button startIcon="Add" onClick={addColumn} variant="outlined" text="Add Column" />
</DialogContent>
<DialogActions>
<Button onClick={handleClose}>Cancel</Button>
<Button onClick={handleCreate} variant="contained" disabled={loading || !tableName.trim()}>
Create Table
</Button>
<Button onClick={handleClose} text="Cancel" />
<Button onClick={handleCreate} variant="contained" disabled={loading || !tableName.trim()} text="Create Table" />
</DialogActions>
</Dialog>
);

View File

@@ -9,7 +9,7 @@ import {
TableHead,
TableRow,
Tooltip,
} from '@mui/material';
} from '../atoms';
import IconButton from '../atoms/IconButton';
type DataGridProps = {

View File

@@ -1,16 +1,16 @@
'use client';
import { useState } from 'react';
import {
Button,
Dialog,
DialogActions,
DialogContent,
DialogTitle,
MenuItem,
Select,
Typography,
} from '@mui/material';
import { useState } from 'react';
} from '../atoms';
import Button from '../atoms/Button';
import Typography from '../atoms/Typography';
type DropTableDialogProps = {
open: boolean;
@@ -70,15 +70,14 @@ export default function DropTableDialog({
</Select>
</DialogContent>
<DialogActions>
<Button onClick={handleClose}>Cancel</Button>
<Button onClick={handleClose} text="Cancel" />
<Button
onClick={handleDrop}
color="error"
variant="contained"
disabled={loading || !selectedTable}
>
Drop Table
</Button>
text="Drop Table"
/>
</DialogActions>
</Dialog>
);

View File

@@ -0,0 +1,52 @@
import type { Meta, StoryObj } from '@storybook/react';
import Button from './Button';
import { generateMeta, generateStories } from '@/utils/storybook/storyGenerator';
/**
* Example of using story generator with features.json configuration
* This demonstrates how to leverage the storybookStories section from features.json
*/
// Generate meta from features.json
const meta = generateMeta(Button, 'Button', {
title: 'Atoms/Button',
}) satisfies Meta<typeof Button>;
export default meta;
type Story = StoryObj<typeof meta>;
// Generate stories from features.json
const generatedStories = generateStories<typeof Button>('Button');
// Export individual stories
export const Primary: Story = generatedStories.primary || {
args: {
variant: 'contained',
color: 'primary',
text: 'Primary Button',
},
};
export const Secondary: Story = generatedStories.secondary || {
args: {
variant: 'outlined',
color: 'secondary',
text: 'Secondary Button',
},
};
export const WithIcon: Story = generatedStories.withIcon || {
args: {
variant: 'contained',
startIcon: 'Add',
text: 'Add Item',
},
};
export const Loading: Story = generatedStories.loading || {
args: {
variant: 'contained',
disabled: true,
text: 'Loading...',
},
};

View File

@@ -44,4 +44,5 @@ export {
AccordionSummary,
AccordionDetails,
Chip,
Tooltip,
} from '@mui/material';

View File

@@ -0,0 +1,76 @@
import type { Meta, StoryObj } from '@storybook/react';
import { getAllStorybookStories, getStorybookStoriesForComponent, StorybookStory } from '@/utils/featureConfig';
/**
* Generate Storybook meta configuration from features.json
*/
export function generateMeta<T>(
component: T,
componentName: string,
customMeta?: Partial<Meta<T>>
): Meta<T> {
const stories = getStorybookStoriesForComponent(componentName);
const defaultStory = stories.default;
return {
title: `Components/${componentName}`,
component: component as any,
parameters: {
layout: 'centered',
...defaultStory?.parameters,
},
tags: ['autodocs'],
...customMeta,
};
}
/**
* Generate a single story from features.json story definition
*/
export function generateStory<T>(
storyConfig: StorybookStory
): StoryObj<T> {
return {
name: storyConfig.name,
args: storyConfig.args || {},
parameters: storyConfig.parameters,
// Note: play functions would need to be converted from strings to actual functions
// This is a limitation of JSON - we can only store the play steps as strings
};
}
/**
* Generate all stories for a component from features.json
*/
export function generateStories<T>(componentName: string): Record<string, StoryObj<T>> {
const stories = getStorybookStoriesForComponent(componentName);
const result: Record<string, StoryObj<T>> = {};
for (const [key, storyConfig] of Object.entries(stories)) {
result[key] = generateStory<T>(storyConfig);
}
return result;
}
/**
* Get all available story configurations
*/
export function listStorybookComponents(): string[] {
return Object.keys(getAllStorybookStories());
}
/**
* Helper to create mock handlers for stories
*/
export function createMockHandlers(handlerNames: string[]): Record<string, () => void> {
const handlers: Record<string, () => void> = {};
for (const name of handlerNames) {
handlers[name] = () => {
console.log(`Mock handler called: ${name}`);
};
}
return handlers;
}