feat: Add isSystem property to profile sections and isSearchableOnly to profile fields, including UI updates for display and management.
This commit is contained in:
@@ -55,6 +55,7 @@ export default function SectionDetailPage() {
|
||||
sortOrder: 0,
|
||||
isActive: true,
|
||||
isRequired: false,
|
||||
isSearchableOnly: false,
|
||||
options: [],
|
||||
rangeConfig: undefined,
|
||||
});
|
||||
@@ -110,6 +111,7 @@ export default function SectionDetailPage() {
|
||||
sortOrder: fields.length,
|
||||
isActive: true,
|
||||
isRequired: false,
|
||||
isSearchableOnly: false,
|
||||
options: [],
|
||||
rangeConfig: undefined,
|
||||
});
|
||||
@@ -130,6 +132,7 @@ export default function SectionDetailPage() {
|
||||
sortOrder: field.sortOrder,
|
||||
isActive: field.isActive,
|
||||
isRequired: field.isRequired,
|
||||
isSearchableOnly: field.isSearchableOnly,
|
||||
options: field.options || [],
|
||||
rangeConfig: field.rangeConfig || undefined,
|
||||
});
|
||||
@@ -322,6 +325,11 @@ export default function SectionDetailPage() {
|
||||
<div className="flex items-center">
|
||||
{section.icon && <span className="text-2xl mr-2">{section.icon}</span>}
|
||||
<h1 className="text-2xl font-bold text-gray-900">{section.name}</h1>
|
||||
{section.isSystem && (
|
||||
<span className="ml-3 px-2 py-1 text-xs font-semibold rounded-full bg-amber-100 text-amber-800">
|
||||
System
|
||||
</span>
|
||||
)}
|
||||
{section.isGlobal && (
|
||||
<span className="ml-3 px-2 py-1 text-xs font-semibold rounded-full bg-purple-100 text-purple-800">
|
||||
Global
|
||||
@@ -382,11 +390,16 @@ export default function SectionDetailPage() {
|
||||
<div key={field.id} className="px-6 py-4 hover:bg-gray-50">
|
||||
<div className="flex justify-between items-start">
|
||||
<div className="flex-1">
|
||||
<div className="flex items-center">
|
||||
<span className="text-gray-400 mr-3 text-sm">#{index + 1}</span>
|
||||
<div className="flex items-center flex-wrap gap-2">
|
||||
<span className="text-gray-400 mr-1 text-sm">#{index + 1}</span>
|
||||
<span className="font-medium text-gray-900">{field.name}</span>
|
||||
{field.isRequired && (
|
||||
<span className="ml-2 text-red-500 text-xs">*required</span>
|
||||
<span className="text-red-500 text-xs">*required</span>
|
||||
)}
|
||||
{field.isSearchableOnly && (
|
||||
<span className="px-2 py-0.5 text-xs font-medium rounded-full bg-amber-100 text-amber-800">
|
||||
Search Only
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<div className="mt-1 flex items-center space-x-3 text-sm">
|
||||
@@ -647,6 +660,28 @@ export default function SectionDetailPage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Search Only Toggle */}
|
||||
<div className="border border-amber-200 rounded-lg p-4 bg-amber-50">
|
||||
<div className="flex items-start justify-between">
|
||||
<div className="flex-1">
|
||||
<label htmlFor="fieldIsSearchableOnly" className="text-sm font-medium text-gray-700">
|
||||
Search Only (Hidden from Public Profile)
|
||||
</label>
|
||||
<p className="text-xs text-gray-500 mt-1">
|
||||
This field will be shown in the agent edit form and used for search filtering,
|
||||
but will NOT be visible on the public agent profile page.
|
||||
</p>
|
||||
</div>
|
||||
<input
|
||||
type="checkbox"
|
||||
id="fieldIsSearchableOnly"
|
||||
checked={fieldForm.isSearchableOnly}
|
||||
onChange={(e) => setFieldForm({ ...fieldForm, isSearchableOnly: e.target.checked })}
|
||||
className="mt-1 rounded border-gray-300 text-amber-600 focus:ring-amber-500"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Options Editor for SELECT, RADIO, MULTI_SELECT, CHECKBOX_GROUP */}
|
||||
{REQUIRES_OPTIONS.includes(fieldForm.fieldType) && (
|
||||
<div className="border border-gray-200 rounded-lg p-4">
|
||||
|
||||
@@ -284,15 +284,22 @@ export default function ProfileSectionsPage() {
|
||||
</div>
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap">
|
||||
<span
|
||||
className={`inline-flex px-2 py-1 text-xs font-semibold rounded-full ${
|
||||
section.isGlobal
|
||||
? 'bg-purple-100 text-purple-800'
|
||||
: 'bg-gray-100 text-gray-600'
|
||||
}`}
|
||||
>
|
||||
{section.isGlobal ? 'Global' : 'Specific'}
|
||||
</span>
|
||||
<div className="flex items-center space-x-2">
|
||||
{section.isSystem && (
|
||||
<span className="inline-flex px-2 py-1 text-xs font-semibold rounded-full bg-amber-100 text-amber-800">
|
||||
System
|
||||
</span>
|
||||
)}
|
||||
<span
|
||||
className={`inline-flex px-2 py-1 text-xs font-semibold rounded-full ${
|
||||
section.isGlobal
|
||||
? 'bg-purple-100 text-purple-800'
|
||||
: 'bg-gray-100 text-gray-600'
|
||||
}`}
|
||||
>
|
||||
{section.isGlobal ? 'Global' : 'Specific'}
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap">
|
||||
<button
|
||||
@@ -319,12 +326,21 @@ export default function ProfileSectionsPage() {
|
||||
>
|
||||
Edit
|
||||
</button>
|
||||
<button
|
||||
onClick={() => openDeleteModal(section)}
|
||||
className="text-red-600 hover:text-red-900"
|
||||
>
|
||||
Delete
|
||||
</button>
|
||||
{section.isSystem ? (
|
||||
<span
|
||||
className="text-gray-400 cursor-not-allowed"
|
||||
title="System sections cannot be deleted"
|
||||
>
|
||||
Delete
|
||||
</span>
|
||||
) : (
|
||||
<button
|
||||
onClick={() => openDeleteModal(section)}
|
||||
className="text-red-600 hover:text-red-900"
|
||||
>
|
||||
Delete
|
||||
</button>
|
||||
)}
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
|
||||
@@ -67,6 +67,7 @@ export interface ProfileField {
|
||||
sortOrder: number;
|
||||
isActive: boolean;
|
||||
isRequired: boolean;
|
||||
isSearchableOnly: boolean;
|
||||
validation: FieldValidation | null;
|
||||
options: FieldOption[] | null;
|
||||
rangeConfig: RangeConfig | null;
|
||||
@@ -90,6 +91,7 @@ export interface CreateFieldDto {
|
||||
sortOrder?: number;
|
||||
isActive?: boolean;
|
||||
isRequired?: boolean;
|
||||
isSearchableOnly?: boolean;
|
||||
validation?: FieldValidation;
|
||||
options?: FieldOption[];
|
||||
rangeConfig?: RangeConfig;
|
||||
@@ -105,6 +107,7 @@ export interface UpdateFieldDto {
|
||||
sortOrder?: number;
|
||||
isActive?: boolean;
|
||||
isRequired?: boolean;
|
||||
isSearchableOnly?: boolean;
|
||||
validation?: FieldValidation;
|
||||
options?: FieldOption[];
|
||||
rangeConfig?: RangeConfig;
|
||||
|
||||
@@ -11,6 +11,7 @@ export interface ProfileSection {
|
||||
sortOrder: number;
|
||||
isActive: boolean;
|
||||
isGlobal: boolean;
|
||||
isSystem: boolean;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
fields?: ProfileField[];
|
||||
|
||||
Reference in New Issue
Block a user