39948-vm/frontend/src/components/ElementSettings/CarouselSettingsSection.tsx
2026-03-31 10:26:13 +04:00

184 lines
5.8 KiB
TypeScript

/**
* CarouselSettingsSection
*
* Settings for carousel element type.
* Manages carousel slides with images and captions.
*/
import React from 'react';
import { mdiPlus, mdiTrashCan } from '@mdi/js';
import BaseButton from '../BaseButton';
import CardBox from '../CardBox';
import FormField from '../FormField';
import type { CarouselSettingsSectionProps } from './types';
import { FONT_OPTIONS } from '../../lib/fonts';
const CarouselSettingsSection: React.FC<CarouselSettingsSectionProps> = ({
carouselPrevIconUrl,
carouselNextIconUrl,
carouselCaptionFontFamily,
carouselSlides,
onAddSlide,
onRemoveSlide,
onUpdateSlide,
onChange,
context,
iconAssetOptions = [],
imageAssetOptions = [],
}) => {
const isConstructor = context === 'constructor';
return (
<CardBox className='border border-gray-200 dark:border-dark-700'>
<h3 className='mb-3 text-sm font-semibold'>Carousel settings</h3>
<div className='grid gap-3 md:grid-cols-2'>
{isConstructor ? (
<>
<FormField label='Previous icon'>
<select
value={carouselPrevIconUrl}
onChange={(event) =>
onChange('carouselPrevIconUrl', event.target.value)
}
>
<option value=''>Not selected</option>
{iconAssetOptions.map((option) => (
<option key={option.value} value={option.value}>
{option.label}
</option>
))}
</select>
</FormField>
<FormField label='Next icon'>
<select
value={carouselNextIconUrl}
onChange={(event) =>
onChange('carouselNextIconUrl', event.target.value)
}
>
<option value=''>Not selected</option>
{iconAssetOptions.map((option) => (
<option key={option.value} value={option.value}>
{option.label}
</option>
))}
</select>
</FormField>
</>
) : (
<>
<FormField label='Previous icon URL'>
<input
value={carouselPrevIconUrl}
onChange={(event) =>
onChange('carouselPrevIconUrl', event.target.value)
}
/>
</FormField>
<FormField label='Next icon URL'>
<input
value={carouselNextIconUrl}
onChange={(event) =>
onChange('carouselNextIconUrl', event.target.value)
}
/>
</FormField>
</>
)}
</div>
<div className='mt-4'>
<FormField label='Caption font family'>
<select
value={carouselCaptionFontFamily}
onChange={(event) =>
onChange('carouselCaptionFontFamily', event.target.value)
}
>
<option value=''>Not set</option>
{FONT_OPTIONS.map((font) => (
<option key={font.key} value={font.key}>
{font.label}
</option>
))}
</select>
</FormField>
</div>
<div className='mb-3 mt-4 flex items-center justify-between'>
<h3 className='text-sm font-semibold'>Carousel slides</h3>
<BaseButton
color='info'
icon={mdiPlus}
small
label='Add slide'
onClick={onAddSlide}
/>
</div>
<div className='space-y-4'>
{carouselSlides.length === 0 ? (
<p className='text-sm text-gray-500'>No slides yet.</p>
) : (
carouselSlides.map((slide, index) => (
<CardBox
key={slide.id}
className='border border-gray-200 dark:border-dark-700'
>
<div className='mb-3 flex items-center justify-between'>
<h4 className='text-sm font-semibold'>Slide {index + 1}</h4>
<BaseButton
color='danger'
icon={mdiTrashCan}
small
outline
onClick={() => onRemoveSlide(slide.id)}
/>
</div>
<div className='grid gap-3 md:grid-cols-2'>
{isConstructor ? (
<FormField label='Image'>
<select
value={slide.imageUrl}
onChange={(event) =>
onUpdateSlide(slide.id, 'imageUrl', event.target.value)
}
>
<option value=''>Not selected</option>
{imageAssetOptions.map((option) => (
<option key={option.value} value={option.value}>
{option.label}
</option>
))}
</select>
</FormField>
) : (
<FormField label='Image URL'>
<input
value={slide.imageUrl}
onChange={(event) =>
onUpdateSlide(slide.id, 'imageUrl', event.target.value)
}
/>
</FormField>
)}
<FormField label='Caption'>
<input
value={slide.caption}
onChange={(event) =>
onUpdateSlide(slide.id, 'caption', event.target.value)
}
/>
</FormField>
</div>
</CardBox>
))
)}
</div>
</CardBox>
);
};
export default CarouselSettingsSection;