chore: batch supporting UI, settings schema, templates, and docs updates

This commit is contained in:
Dwindi Ramadhana
2026-06-01 00:58:43 +07:00
parent 30f2fc2ea6
commit f3c4ee7124
20 changed files with 1149 additions and 54 deletions

View File

@@ -7,7 +7,7 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@
import { Checkbox } from '@/components/ui/checkbox';
export interface FieldSchema {
type: 'text' | 'textarea' | 'email' | 'url' | 'number' | 'toggle' | 'checkbox' | 'select';
type: 'text' | 'textarea' | 'email' | 'url' | 'number' | 'toggle' | 'checkbox' | 'select' | 'multiselect';
label: string;
description?: string;
placeholder?: string;
@@ -47,8 +47,8 @@ export function SchemaField({ name, schema, value, onChange, error }: SchemaFiel
return (
<Input
type="number"
value={value || ''}
onChange={(e) => onChange(parseFloat(e.target.value))}
value={value ?? ''}
onChange={(e) => onChange(e.target.value === '' ? 0 : parseFloat(e.target.value))}
placeholder={schema.placeholder}
required={schema.required}
min={schema.min}
@@ -110,6 +110,35 @@ export function SchemaField({ name, schema, value, onChange, error }: SchemaFiel
</Select>
);
case 'multiselect':
const selectedValues = Array.isArray(value) ? value : [];
return (
<div className="flex flex-wrap gap-2">
{schema.options && Object.entries(schema.options).map(([key, label]) => (
<label
key={key}
className={`flex items-center gap-2 px-3 py-2 rounded-lg border cursor-pointer transition-colors ${
selectedValues.includes(key)
? 'bg-primary/10 border-primary text-primary'
: 'bg-background border-input hover:bg-muted'
}`}
>
<Checkbox
checked={selectedValues.includes(key)}
onCheckedChange={(checked) => {
if (checked) {
onChange([...selectedValues, key]);
} else {
onChange(selectedValues.filter((v: string) => v !== key));
}
}}
/>
<span className="text-sm">{label}</span>
</label>
))}
</div>
);
default:
return (
<Input

View File

@@ -164,9 +164,10 @@
display: none !important;
}
/* Hide WooNooW app shell - all nav, header, submenu elements */
/* Hide WooNooW app shell - all nav, sidebar, header, submenu elements */
#woonoow-admin-app header,
#woonoow-admin-app nav,
#woonoow-admin-app aside,
#woonoow-admin-app [data-submenubar],
#woonoow-admin-app [data-bottomnav],
.woonoow-app-header,
@@ -372,4 +373,4 @@ html #wpadminbar {
.media-modal .attachments,
.media-modal .attachment {
pointer-events: auto !important;
}
}

View File

@@ -74,8 +74,8 @@ export default function CampaignsList() {
const { data, isLoading } = useQuery({
queryKey: ['campaigns'],
queryFn: async () => {
const response = await api.get('/campaigns');
return response.data as Campaign[];
const response: any = await api.get('/campaigns');
return Array.isArray(response) ? (response as Campaign[]) : ((response?.data || []) as Campaign[]);
},
});

View File

@@ -73,8 +73,8 @@ export default function Campaigns() {
const { data, isLoading } = useQuery({
queryKey: ['campaigns'],
queryFn: async () => {
const response = await api.get('/campaigns');
return response.data as Campaign[];
const response: any = await api.get('/newsletter/campaigns');
return Array.isArray(response) ? (response as Campaign[]) : ((response?.data || []) as Campaign[]);
},
});

View File

@@ -35,14 +35,16 @@ import {
export default function Subscribers() {
const [searchQuery, setSearchQuery] = useState('');
const [showDeleteDialog, setShowDeleteDialog] = useState(false);
const [deleteTargetEmail, setDeleteTargetEmail] = useState<string | null>(null);
const queryClient = useQueryClient();
const navigate = useNavigate();
const { data: subscribersData, isLoading } = useQuery({
queryKey: ['newsletter-subscribers'],
queryFn: async () => {
const response = await api.get('/newsletter/subscribers');
return response.data;
const response: any = await api.get('/admin/newsletter/subscribers');
return Array.isArray(response) ? response : (response?.data || []);
},
});

View File

@@ -13,9 +13,7 @@
"strict": true,
"allowJs": false,
"types": [],
"baseUrl": ".",
"paths": { "@/*": ["./src/*"] },
"ignoreDeprecations": "6.0"
"paths": { "@/*": ["./src/*"] }
},
"include": ["src"]
}
}