Align external preview UX and unlock leads preview flow

This commit is contained in:
Tracewebstudio Dev 2026-04-15 00:15:22 +02:00
parent df5326db73
commit 3265b1a16a

View file

@ -560,8 +560,6 @@ function portfolioMediaConfig(roleKey: string): {
|| normalized === 'GRAPHIC_DESIGNER'
|| normalized === 'SOCIAL_MEDIA_MANAGER'
|| normalized === 'CATERING_SERVICES'
|| normalized === 'DEVELOPER'
|| normalized === 'FITNESS_TRAINER'
) {
return {
mode: 'visual',
@ -1622,6 +1620,7 @@ export default function DashboardDesignPreview(props: {
const serviceTabKey = normalizeTabKey(spec.serviceTabLabel);
const galleryTabKey = normalizeTabKey(spec.galleryTabLabel);
const experienceTabKey = normalizeTabKey(spec.experienceTabLabel);
const requiresVisualAssets = mediaConfig.mode === 'visual';
const testimonialsTabKey = normalizeTabKey('testimonials');
const faqsTabKey = normalizeTabKey('faqs');
const portfolioJobsCompleted = portfolioJobsCompletedPreview;
@ -1708,7 +1707,7 @@ export default function DashboardDesignPreview(props: {
});
if (stepKey === serviceTabKey && portfolioServices().length < 1) {
setPortfolioValidationNotice('Add at least one service with pricing.');
} else if (stepKey === galleryTabKey && (portfolioPhotos().length < 1 || portfolioPhotos().length > 6)) {
} else if (stepKey === galleryTabKey && requiresVisualAssets && (portfolioPhotos().length < 1 || portfolioPhotos().length > 6)) {
setPortfolioValidationNotice('Add 1 to 6 portfolio photos.');
} else if (stepKey === experienceTabKey && portfolioExperiences().length < 1) {
setPortfolioValidationNotice('Add at least one experience entry.');
@ -1720,7 +1719,7 @@ export default function DashboardDesignPreview(props: {
setPortfolioFormErrors((prev) => ({ ...prev, ...nextErrors }));
return Object.keys(nextErrors).length === 0
&& !(stepKey === serviceTabKey && portfolioServices().length < 1)
&& !(stepKey === galleryTabKey && (portfolioPhotos().length < 1 || portfolioPhotos().length > 6))
&& !(stepKey === galleryTabKey && requiresVisualAssets && (portfolioPhotos().length < 1 || portfolioPhotos().length > 6))
&& !(stepKey === experienceTabKey && portfolioExperiences().length < 1);
};
const addServiceDraft = () => {
@ -1901,18 +1900,36 @@ export default function DashboardDesignPreview(props: {
<Show when={selectedPortfolioTabKey === galleryTabKey}>
<div style="display:grid;gap:10px;margin-top:10px">
<div style="display:flex;align-items:center;justify-content:space-between;gap:8px">
<p style="margin:0;font-size:12px;color:#374151">Portfolio photos ({portfolioPhotos().length}/6)</p>
<button type="button" onClick={addPhotoItem} disabled={portfolioPhotos().length >= 6} style={`height:32px;border-radius:8px;border:1px solid #E5E7EB;background:white;padding:0 12px;font-size:12px;font-weight:700;color:#374151;cursor:${portfolioPhotos().length >= 6 ? 'not-allowed' : 'pointer'};opacity:${portfolioPhotos().length >= 6 ? 0.6 : 1}`}>Add Photo</button>
</div>
<div style="display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px">
<For each={portfolioPhotos()}>{(photo, idx) => (
<div style="border:1px solid #E5E7EB;border-radius:10px;background:#FAFBFD;padding:10px;display:flex;align-items:center;justify-content:space-between;gap:8px">
<span style="font-size:12px;font-weight:600;color:#374151">{photo}</span>
<button type="button" onClick={() => removePhotoItem(idx())} style="height:26px;border-radius:8px;border:1px solid #E5E7EB;background:white;padding:0 8px;font-size:11px;font-weight:700;color:#374151;cursor:pointer">Remove</button>
<Show
when={requiresVisualAssets}
fallback={
<div style="border:1px solid #E5E7EB;border-radius:10px;background:#F9FAFB;padding:10px;display:grid;gap:8px">
<p style="margin:0;font-size:12px;color:#374151;font-weight:600">Structured work proof (photos optional)</p>
<For each={mediaConfig.items}>{(item, idx) => (
<div style="border:1px solid #E5E7EB;border-radius:8px;background:white;padding:8px 10px;display:flex;align-items:flex-start;gap:8px">
<FileText size={14} style="color:#9CA3AF;flex-shrink:0;margin-top:2px" />
<div>
<p style="margin:0;font-size:12px;font-weight:700;color:#111827">{item}</p>
<p style="margin:4px 0 0;font-size:11px;color:#6B7280">Entry #{idx() + 1} for outcome-focused portfolio evidence.</p>
</div>
</div>
)}</For>
</div>
)}</For>
</div>
}
>
<div style="display:flex;align-items:center;justify-content:space-between;gap:8px">
<p style="margin:0;font-size:12px;color:#374151">Portfolio photos ({portfolioPhotos().length}/6)</p>
<button type="button" onClick={addPhotoItem} disabled={portfolioPhotos().length >= 6} style={`height:32px;border-radius:8px;border:1px solid #E5E7EB;background:white;padding:0 12px;font-size:12px;font-weight:700;color:#374151;cursor:${portfolioPhotos().length >= 6 ? 'not-allowed' : 'pointer'};opacity:${portfolioPhotos().length >= 6 ? 0.6 : 1}`}>Add Photo</button>
</div>
<div style="display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px">
<For each={portfolioPhotos()}>{(photo, idx) => (
<div style="border:1px solid #E5E7EB;border-radius:10px;background:#FAFBFD;padding:10px;display:flex;align-items:center;justify-content:space-between;gap:8px">
<span style="font-size:12px;font-weight:600;color:#374151">{photo}</span>
<button type="button" onClick={() => removePhotoItem(idx())} style="height:26px;border-radius:8px;border:1px solid #E5E7EB;background:white;padding:0 8px;font-size:11px;font-weight:700;color:#374151;cursor:pointer">Remove</button>
</div>
)}</For>
</div>
</Show>
</div>
</Show>
@ -2853,7 +2870,8 @@ export default function DashboardDesignPreview(props: {
}
if (customerKey() === 'leads') {
if (!bothApprovalsApproved()) {
const lockLeadsPreview = false;
if (lockLeadsPreview && !bothApprovalsApproved()) {
return (
<div style="display:grid;gap:12px">
<div style="border:1px solid #E5E7EB;background:white;border-radius:14px;padding:14px">