Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 32 additions & 19 deletions src/pages/groups/groups-view/group-actions/EditGroups.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ import { Button } from '@/components/ui/button'
import { Label } from '@/components/ui/label'
import { Input } from '@/components/ui/input'

import { GroupsApi, type GetGroupsGroupIdResponse } from '@/fineract-api'
import { GroupsApi, type PutGroupsGroupIdRequest } from '@/fineract-api'
import type { ExtendedGroupResponse } from '@/pages/groups/types'
import { getConfiguration } from '@/lib/fineract-openapi'
import { dateArrayToInputValue, inputToFineractDate } from '@/lib/date-utils'
import { useTranslation } from 'react-i18next'
Expand All @@ -28,7 +29,7 @@ const EditGroups = () => {
const { t: tc } = useTranslation('common')

// Local state for group + form fields
const [group, setGroup] = useState<GetGroupsGroupIdResponse>()
const [group, setGroup] = useState<ExtendedGroupResponse>()
const [name, setName] = useState('')
const [staffId, setStaffId] = useState<string>('')
const [submittedOn, setSubmittedOn] = useState<string>('')
Expand All @@ -42,19 +43,21 @@ const EditGroups = () => {
if (!id) return
try {
const res = await groupsApi.retrieveOne15(Number(id))
setGroup(res.data)
const groupData = res.data as ExtendedGroupResponse
setGroup(groupData)

setName(res.data?.name ?? '')
if ((res.data as any)?.staffId) {
setStaffId(String((res.data as any).staffId))
setName(groupData?.name ?? '')
if (groupData?.staffId) {
setStaffId(String(groupData.staffId))
}
setSubmittedOn(
dateArrayToInputValue((res.data as any)?.timeline?.submittedOnDate)
dateArrayToInputValue(
groupData?.timeline?.submittedOnDate as number[] | null
)
)
setActivationOn(
dateArrayToInputValue(
(res.data as any)?.timeline?.activationDate ??
(res.data as any)?.timeline?.activatedOnDate
groupData?.timeline?.activatedOnDate as number[] | null
)
)
// externalId left blank on purpose, user must fill if needed
Expand All @@ -65,18 +68,22 @@ const EditGroups = () => {
}, [id])

// Build staff dropdown options from API response
const staffOptions =
((group as any)?.staffOptions ?? []).map((s: any) => ({
id: s.id,
name: s.displayName ?? s.name ?? t('edit.staffFallback', { id: s.id }),
})) || []
const staffOptions = (group?.staffOptions ?? []).map(s => ({
id: s.id ?? 0,
name: s.displayName ?? s.name ?? t('edit.staffFallback', { id: s.id }),
}))
Comment on lines +71 to +74
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fallback id: 0 may cause issues if selected.

If a staff option has no id and the user selects it, submitting staffId: 0 to the API could cause unexpected behavior or validation errors. Consider filtering out staff options without valid IDs instead.

Proposed fix to filter invalid staff options
-  const staffOptions = (group?.staffOptions ?? []).map(s => ({
-    id: s.id ?? 0,
-    name: s.displayName ?? s.name ?? t('edit.staffFallback', { id: s.id }),
-  }))
+  const staffOptions = (group?.staffOptions ?? [])
+    .filter(s => s.id != null)
+    .map(s => ({
+      id: s.id!,
+      name: s.displayName ?? s.name ?? t('edit.staffFallback', { id: s.id }),
+    }))
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const staffOptions = (group?.staffOptions ?? []).map(s => ({
id: s.id ?? 0,
name: s.displayName ?? s.name ?? t('edit.staffFallback', { id: s.id }),
}))
const staffOptions = (group?.staffOptions ?? [])
.filter(s => s.id != null)
.map(s => ({
id: s.id!,
name: s.displayName ?? s.name ?? t('edit.staffFallback', { id: s.id }),
}))
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/pages/groups/groups-view/group-actions/EditGroups.tsx` around lines 71 -
74, The current staffOptions mapping in EditGroups.tsx uses id: s.id ?? 0 which
injects a 0 ID for missing IDs; instead filter out entries without a valid
numeric id before mapping to avoid submitting staffId: 0 to the API. Update the
logic that builds staffOptions (the group?.staffOptions mapping) to first filter
by a defined/non-null id (e.g., s.id !== undefined && s.id !== null) and then
map to { id: s.id, name: ... } so only valid staff IDs are included; keep the
existing name fallback (s.displayName ?? s.name ?? t('edit.staffFallback', { id:
s.id })) but ensure you only call that when s.id exists.


// Handle submit
const onSubmit = async () => {
if (!id) return
const groupId = Number(id)
if (!Number.isFinite(groupId)) {
console.error('Invalid group id:', id)
return
}
setSaving(true)
try {
const payload: any = {
const payload: PutGroupsGroupIdRequest & Record<string, unknown> = {
name: name.trim(),
locale: 'en',
dateFormat: 'dd MMMM yyyy',
Expand All @@ -89,6 +96,7 @@ const EditGroups = () => {
if (act) payload.activationDate = act
if (externalId.trim()) payload.externalId = externalId.trim()

await groupsApi.update13(groupId, payload)
navigate(`/groups/${id}/general`)
} catch (err) {
console.error('Failed to update group', err)
Expand All @@ -104,7 +112,10 @@ const EditGroups = () => {
items={[
{ label: tc('nav.home'), href: '/home' },
{ label: t('title'), href: '/groups' },
{ label: group?.name ?? t('view.groupName'), href: `/groups/${id}/general` },
{
label: group?.name ?? t('view.groupName'),
href: `/groups/${id}/general`,
},
{ label: t('edit.breadcrumb'), current: true },
]}
/>
Expand Down Expand Up @@ -141,8 +152,8 @@ const EditGroups = () => {
<Label>{t('edit.labelStaff')}</Label>
<Input
value={
(group as any)?.staffName ??
(group as any)?.staff?.displayName ??
group?.staffName ??
group?.staff?.displayName ??
t('edit.placeholderUnassigned')
}
readOnly
Expand All @@ -165,7 +176,9 @@ const EditGroups = () => {

{/* Activation Date */}
<div className="w-full space-y-2">
<Label htmlFor="activation-on">{t('edit.labelActivationDate')}</Label>
<Label htmlFor="activation-on">
{t('edit.labelActivationDate')}
</Label>
<Input
id="activation-on"
type="date"
Expand Down