Initial commit: Meshkee dashboards monorepo.

Includes business, customer, and super-admin apps with shared packages and production deploy scripts.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Alireza Hassani
2026-07-22 13:48:53 +03:30
co-authored by Cursor
commit f566387c61
509 changed files with 62690 additions and 0 deletions
@@ -0,0 +1,248 @@
import { useEffect, useRef, useState } from 'react'
import { Plus, X } from 'lucide-react'
import type { Variation, VariationType } from '../types/variation'
import { COLOR_OPTIONS, SIZE_OPTIONS } from '../types/variation'
import styles from './VariationsModal.module.css'
interface AddVariationModalProps {
open: boolean
onClose: () => void
onSubmit: (variation: Omit<Variation, 'id'>) => void
}
const ANIMATION_MS = 220
export function AddVariationModal({ open, onClose, onSubmit }: AddVariationModalProps) {
const [mounted, setMounted] = useState(open)
const [closing, setClosing] = useState(false)
const [type, setType] = useState<VariationType>('color')
const [customName, setCustomName] = useState('')
const [selectedColors, setSelectedColors] = useState<string[]>([])
const [selectedSizes, setSelectedSizes] = useState<string[]>([])
const [customValues, setCustomValues] = useState<string[]>([''])
const valueInputRefs = useRef<(HTMLInputElement | null)[]>([])
const pendingFocusIndex = useRef<number | null>(null)
useEffect(() => {
if (pendingFocusIndex.current === null) return
valueInputRefs.current[pendingFocusIndex.current]?.focus()
pendingFocusIndex.current = null
}, [customValues.length])
useEffect(() => {
if (open) {
setMounted(true)
setClosing(false)
setType('color')
setCustomName('')
setSelectedColors([])
setSelectedSizes([])
setCustomValues([''])
} else if (mounted) {
setClosing(true)
const timer = setTimeout(() => {
setMounted(false)
setClosing(false)
}, ANIMATION_MS)
return () => clearTimeout(timer)
}
}, [open, mounted])
useEffect(() => {
if (!mounted || closing) return
const onKey = (e: KeyboardEvent) => {
if (e.key === 'Escape') onClose()
}
document.addEventListener('keydown', onKey)
return () => document.removeEventListener('keydown', onKey)
}, [mounted, closing, onClose])
if (!mounted) return null
function toggleOption(value: string, selected: string[], setSelected: (v: string[]) => void) {
setSelected(
selected.includes(value)
? selected.filter((v) => v !== value)
: [...selected, value],
)
}
function updateCustomValue(index: number, value: string) {
setCustomValues((prev) => prev.map((v, i) => (i === index ? value : v)))
}
function addCustomRow() {
setCustomValues((prev) => [...prev, ''])
}
function removeCustomRow(index: number) {
setCustomValues((prev) => prev.filter((_, i) => i !== index))
}
function handleValueKeyDown(index: number, e: React.KeyboardEvent<HTMLInputElement>) {
if (e.key !== 'Enter') return
e.preventDefault()
const nextIndex = index + 1
if (nextIndex < customValues.length) {
valueInputRefs.current[nextIndex]?.focus()
return
}
pendingFocusIndex.current = nextIndex
setCustomValues((prev) => [...prev, ''])
}
function handleSubmit(e: React.FormEvent) {
e.preventDefault()
if (type === 'color') {
onSubmit({ name: 'Color', type: 'color', values: selectedColors })
} else if (type === 'size') {
onSubmit({ name: 'Size', type: 'size', values: selectedSizes })
} else {
const name = customName.trim() || 'Custom'
const values = customValues.map((v) => v.trim()).filter(Boolean)
onSubmit({ name, type: 'custom', values })
}
}
const canSubmit =
type === 'color'
? selectedColors.length > 0
: type === 'size'
? selectedSizes.length > 0
: customValues.some((v) => v.trim())
return (
<div
className={`${styles.overlay} ${styles.overlayNested} ${closing ? styles.overlayOut : styles.overlayIn}`}
onClick={onClose}
>
<div
className={`${styles.modal} ${closing ? styles.modalOut : styles.modalIn}`}
onClick={(e) => e.stopPropagation()}
role="dialog"
aria-modal="true"
aria-labelledby="add-variation-title"
>
<div className={styles.header}>
<h3 id="add-variation-title" className={styles.title}>
Add Variation
</h3>
<button className={styles.closeBtn} onClick={onClose} aria-label="Close">
<X size={20} />
</button>
</div>
<form className={styles.body} onSubmit={handleSubmit}>
<div className={styles.field}>
<label htmlFor="variationType">Type</label>
<select
id="variationType"
value={type}
onChange={(e) => setType(e.target.value as VariationType)}
>
<option value="color">Color</option>
<option value="size">Size</option>
<option value="custom">Your own</option>
</select>
</div>
{type === 'color' && (
<div className={styles.field}>
<label>Select colors</label>
<div className={styles.chipGrid}>
{COLOR_OPTIONS.map((color) => (
<button
key={color}
type="button"
className={`${styles.chip} ${selectedColors.includes(color) ? styles.chipSelected : ''}`}
onClick={() => toggleOption(color, selectedColors, setSelectedColors)}
>
{color}
</button>
))}
</div>
</div>
)}
{type === 'size' && (
<div className={styles.field}>
<label>Select sizes</label>
<div className={styles.chipGrid}>
{SIZE_OPTIONS.map((size) => (
<button
key={size}
type="button"
className={`${styles.chip} ${selectedSizes.includes(size) ? styles.chipSelected : ''}`}
onClick={() => toggleOption(size, selectedSizes, setSelectedSizes)}
>
{size}
</button>
))}
</div>
</div>
)}
{type === 'custom' && (
<>
<div className={styles.field}>
<label htmlFor="customName">Variation name</label>
<input
id="customName"
type="text"
placeholder="e.g. Guarantee, Material..."
value={customName}
onChange={(e) => setCustomName(e.target.value)}
/>
</div>
<div className={styles.field}>
<label>Values</label>
<div className={styles.customValues}>
{customValues.map((value, index) => (
<div key={index} className={styles.customRow}>
<input
ref={(el) => {
valueInputRefs.current[index] = el
}}
type="text"
placeholder={`Value ${index + 1}`}
value={value}
onChange={(e) => updateCustomValue(index, e.target.value)}
onKeyDown={(e) => handleValueKeyDown(index, e)}
/>
{customValues.length > 1 && (
<button
type="button"
className={styles.removeValueBtn}
onClick={() => removeCustomRow(index)}
aria-label="Remove value"
>
<X size={16} />
</button>
)}
</div>
))}
<button type="button" className={styles.addValueBtn} onClick={addCustomRow}>
<Plus size={14} />
Add value
</button>
</div>
</div>
</>
)}
<div className={styles.actions}>
<button type="button" className={styles.cancelBtn} onClick={onClose}>
Cancel
</button>
<button type="submit" className={styles.submitBtn} disabled={!canSubmit}>
Add
</button>
</div>
</form>
</div>
</div>
)
}