Add a Statistics page for storefront visits and instruction 1:1/3:2 crops.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Cursor
parent
d9bdfbbb12
commit
6be867ea7a
@@ -29,6 +29,13 @@ import { flattenCategories } from '../utils/categories'
|
||||
import pageStyles from '../components/PageContent.module.css'
|
||||
import styles from './AddNewProductPage.module.css'
|
||||
|
||||
type CoverImageAspectId = '1:1' | '3:2'
|
||||
|
||||
const COVER_IMAGE_ASPECTS: { id: CoverImageAspectId; aspect: number }[] = [
|
||||
{ id: '1:1', aspect: 1 },
|
||||
{ id: '3:2', aspect: 3 / 2 },
|
||||
]
|
||||
|
||||
export function AddNewInstructionPage() {
|
||||
const { id } = useParams()
|
||||
const navigate = useNavigate()
|
||||
@@ -45,6 +52,7 @@ export function AddNewInstructionPage() {
|
||||
const [videoProvider, setInstructionProvider] = useState<VideoProvider>('youtube')
|
||||
const [embedCode, setEmbedCode] = useState('')
|
||||
const [coverImage, setCoverImage] = useState<string | null>(null)
|
||||
const [coverImageAspect, setCoverImageAspect] = useState<CoverImageAspectId>('3:2')
|
||||
const [tags, setTags] = useState<string[]>([])
|
||||
const [featuredMediaId, setFeaturedMediaId] = useState<string | null>(null)
|
||||
const [loaded, setLoaded] = useState(!isEdit)
|
||||
@@ -52,6 +60,8 @@ export function AddNewInstructionPage() {
|
||||
const [error, setError] = useState('')
|
||||
|
||||
const categoryOptions = flattenCategories(categories)
|
||||
const selectedAspect =
|
||||
COVER_IMAGE_ASPECTS.find((option) => option.id === coverImageAspect)?.aspect ?? 3 / 2
|
||||
|
||||
useEffect(() => {
|
||||
const controller = new AbortController()
|
||||
@@ -197,16 +207,44 @@ export function AddNewInstructionPage() {
|
||||
|
||||
<form className={styles.form} onSubmit={handleSubmit}>
|
||||
<div className={styles.formGrid}>
|
||||
<div className={`${styles.field} ${styles.col3} ${styles.rowSpan4}`}>
|
||||
<div className={`${styles.field} ${styles.col3} ${styles.rowSpan4} ${styles.thumbnailField}`}>
|
||||
<label>{t('instruction.form.coverImage')}</label>
|
||||
<ImageCropper
|
||||
value={coverImage}
|
||||
onChange={setCoverImage}
|
||||
aspect={3 / 2}
|
||||
aspect={selectedAspect}
|
||||
uploadLabel={t('instruction.form.uploadCoverImage')}
|
||||
hint={t('instruction.form.cropHint')}
|
||||
hint={t('instruction.form.cropHint', { ratio: coverImageAspect })}
|
||||
changeLabel={t('instruction.form.changeCoverImage')}
|
||||
/>
|
||||
<div
|
||||
className={styles.aspectSwitch}
|
||||
role="radiogroup"
|
||||
aria-label={t('instruction.form.aspectAria')}
|
||||
>
|
||||
{COVER_IMAGE_ASPECTS.map((option) => (
|
||||
<button
|
||||
key={option.id}
|
||||
type="button"
|
||||
role="radio"
|
||||
aria-checked={coverImageAspect === option.id}
|
||||
className={`${styles.aspectSwitchBtn} ${
|
||||
coverImageAspect === option.id ? styles.aspectSwitchBtnSelected : ''
|
||||
}`}
|
||||
onClick={() => {
|
||||
if (option.id === coverImageAspect) return
|
||||
setCoverImageAspect(option.id)
|
||||
if (coverImage) {
|
||||
setCoverImage(null)
|
||||
setFeaturedMediaId(null)
|
||||
}
|
||||
}}
|
||||
disabled={isSubmitting}
|
||||
>
|
||||
{option.id}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={styles.formColumn}>
|
||||
|
||||
Reference in New Issue
Block a user