[ResourceApp][Frontend][REFACTOR] Resource Feature Extraction#73
[ResourceApp][Frontend][REFACTOR] Resource Feature Extraction#73MohamadNazik wants to merge 3 commits intoLSFLK:mainfrom
Conversation
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request implements a significant refactoring of the frontend application by extracting all resource-related logic into a self-contained feature module. This change enhances modularity, improves separation of concerns, and streamlines the global application context, making the codebase more maintainable and scalable. The primary impact is a cleaner architecture where resource management is isolated and independently manageable. Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request does a great job of refactoring the resource management logic into its own dedicated feature module, following DDD principles. The code is well-structured, and the separation of concerns between the AppContext and the new ResourceContext is clear. I've identified a few areas for improvement regarding type safety, key generation, and code maintainability. My detailed comments are below.
resource-app/frontend/features/resource/hooks/useResourceForm.ts
Outdated
Show resolved
Hide resolved
resource-app/frontend/features/resource/hooks/useResourceForm.ts
Outdated
Show resolved
Hide resolved
resource-app/frontend/features/resource/views/CreateResourceView.tsx
Outdated
Show resolved
Hide resolved
- Default new resources to isActive true on creation - Replace Date.now() with a stable ref counter for form field IDs - Replace color ternary chains with lookup maps in catalog and creation views
resource-app/frontend/features/resource/views/CreateResourceView.tsx
Outdated
Show resolved
Hide resolved
- Align submit button disabled state with form validation logic - Surface resource loading and error states in the global app shell - Add safe fallback for specs to prevent crash on missing data - Make reschedule inputs controlled and reset state on modal close - Clear reschedule time state when opening the propose time modal
|
|
||
| const handleAddField = () => { | ||
| setFormFields(prevFields => [...prevFields, { | ||
| id: `field_${fieldIdCounter.current++}`, |
There was a problem hiding this comment.
why not use more robust id generation method like crypto.randomUUID() ?
issue here is if a user edits an existing resource that already has fields named field_0, field_1, etc., adding a new field will restart the counter at 0 and result in duplicate React keys and duplicate ids in the payload
| setResources(prev => [...prev, res.data!]); | ||
| return true; | ||
| } | ||
| return false; |
There was a problem hiding this comment.
currently addResource and updateResource return false if error. then handleSubmit in useResourceForm.ts sees success = false and sets isSubmitting to false, but never triggers an error message or UI feedback. The user is left clicking a button that appears to do nothing
Better to include error in result here
interface MutationResult {
success: boolean;
error?: string;
}
interface ResourceContextType {
// ... keep existing properties
addResource: (data: Omit<Resource, 'id'>) => Promise<MutationResult>;
updateResource: (data: Resource) => Promise<MutationResult>;
// ...
}
There was a problem hiding this comment.
this way ResourceProvider can be updated as such:
const addResource = useCallback(async (data: Omit<Resource, 'id'>) => {
const res = await resourceApi.addResource(data);
if (res.success && res.data) {
setResources(prev => [...prev, res.data!]);
return { success: true };
}
return { success: false, error: res.error || 'Failed to add resource' };
}, []);
const updateResource = useCallback(async (data: Resource) => {
const res = await resourceApi.updateResource(data);
if (res.success && res.data) {
setResources(prev => prev.map(r => r.id === data.id ? res.data! : r));
return { success: true };
}
return { success: false, error: res.error || 'Failed to update resource' };
}, []);| } | ||
|
|
||
| setIsSubmitting(false); | ||
| if (success) onClose(); |
There was a problem hiding this comment.
If you made the updates to addResource and updateResource above, then above handleSubmit function, you should add: const [submitError, setSubmitError] = useState<string | null>(null);
And within handleSubmit, change this last part to
if (result.success) {
onClose();
} else {
setSubmitError(result.error || 'An unexpected error occurred.');
}
There was a problem hiding this comment.
Finally, in features/resource/views/CreateResourceView.tsx
you can get submitError from the hook
const {
isSubmitting,
submitError, // <-- Extract the error
basicInfo, setBasicInfo,
// ...
} = useResourceForm(onClose, initialData);And display it in the UI above the submit button, for example:
{submitError && (
<div className="p-3 bg-red-50 text-red-600 text-sm rounded-lg border border-red-100 flex items-center gap-2">
<span className="font-semibold">Error:</span> {submitError}
</div>
)}
<Button .... />
Context
Part of the incremental DDD refactoring of the resource-app frontend.
What changed
Why
The resource entity is the core of this application. Giving it a dedicated feature module with owned views and business logic keeps all resource concerns co-located and removes them from the bloated global context.
Acceptance Criteria
features/resource/exists with all subfoldersuseResourceContext()returns{ resources, stats, addResource, ... }useResourceFormimports from resource domain onlyViews use
useResourceContext()instead ofuseApp()AppContext.tsxno longer manages resource statenpm run buildpasses with 0 TypeScript errorsCloses [ResourceApp][Frontend][REFACTOR] Introduce Resource domain with context, API layer, and owned views #59