refactor: Clean up and standardize JSX structure in MergePreviewForm component

This commit is contained in:
Nils-Johan Gynther
2026-04-12 09:08:24 +02:00
parent a76fc5ecc5
commit 4d3873c9e4
+201 -199
View File
@@ -129,214 +129,216 @@ export default function MergePreviewForm({ products }: Props) {
{isExpanded && ( {isExpanded && (
<div style={{ padding: '1rem', background: '#f9fafb', display: 'grid', gap: '1rem' }}> <div style={{ padding: '1rem', background: '#f9fafb', display: 'grid', gap: '1rem' }}>
<div style={{ display: 'grid', gap: '0.75rem', gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))' }}> <div style={{ display: 'grid', gap: '0.75rem', gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))' }}>
<label style={{ display: 'grid', gap: '0.3rem' }}> <label style={{ display: 'grid', gap: '0.3rem' }}>
<span style={{ fontWeight: 500, fontSize: '0.9rem' }}>Source product (ska bort)</span> <span style={{ fontWeight: 500, fontSize: '0.9rem' }}>Source product (ska bort)</span>
<select <select
value={sourceProductId} value={sourceProductId}
onChange={(e) => setSourceProductId(e.target.value)} onChange={(e) => setSourceProductId(e.target.value)}
style={{ style={{
width: '100%', width: '100%',
padding: '0.75rem', padding: '0.75rem',
border: '1px solid #ddd', border: '1px solid #ddd',
borderRadius: '4px', borderRadius: '4px',
fontSize: '1rem', fontSize: '1rem',
boxSizing: 'border-box', boxSizing: 'border-box',
minHeight: '44px', minHeight: '44px',
}} }}
> >
<option value="">Välj source</option> <option value="">Välj source</option>
{products.map((product) => ( {products.map((product) => (
<option key={product.id} value={product.id}> <option key={product.id} value={product.id}>
{product.canonicalName || product.name} (ID {product.id}) {product.canonicalName || product.name} (ID {product.id})
</option> </option>
))} ))}
</select> </select>
</label> </label>
<label style={{ display: 'grid', gap: '0.3rem' }}> <label style={{ display: 'grid', gap: '0.3rem' }}>
<span style={{ fontWeight: 500, fontSize: '0.9rem' }}>Target product (ska behållas)</span> <span style={{ fontWeight: 500, fontSize: '0.9rem' }}>Target product (ska behållas)</span>
<select <select
value={targetProductId} value={targetProductId}
onChange={(e) => setTargetProductId(e.target.value)} onChange={(e) => setTargetProductId(e.target.value)}
style={{ style={{
width: '100%', width: '100%',
padding: '0.75rem', padding: '0.75rem',
border: '1px solid #ddd', border: '1px solid #ddd',
borderRadius: '4px', borderRadius: '4px',
fontSize: '1rem', fontSize: '1rem',
boxSizing: 'border-box', boxSizing: 'border-box',
minHeight: '44px', minHeight: '44px',
}} }}
> >
<option value="">Välj target</option> <option value="">Välj target</option>
{products.map((product) => ( {products.map((product) => (
<option key={product.id} value={product.id}> <option key={product.id} value={product.id}>
{product.canonicalName || product.name} (ID {product.id}) {product.canonicalName || product.name} (ID {product.id})
</option> </option>
))} ))}
</select> </select>
</label> </label>
</div>
<div style={{ display: 'flex', gap: '0.75rem', flexWrap: 'wrap' }}>
<button
type="button"
onClick={fetchPreview}
disabled={isPending}
style={{
padding: '0.75rem 1.5rem',
background: '#0070f3',
color: 'white',
border: 'none',
borderRadius: '4px',
cursor: 'pointer',
fontSize: '1rem',
minHeight: '44px',
fontWeight: 600,
}}
>
{isPending ? 'Hämtar preview...' : 'Förhandsgranska merge'}
</button>
{preview ? (
<button
type="button"
onClick={() => setIsConfirming((prev) => !prev)}
disabled={isPending}
style={{
padding: '0.75rem 1.5rem',
background: '#f0f0f0',
color: '#333',
border: '1px solid #ccc',
borderRadius: '4px',
cursor: 'pointer',
fontSize: '1rem',
minHeight: '44px',
fontWeight: 600,
}}
>
{isConfirming ? 'Avbryt bekräftelse' : 'Gå vidare till bekräftelse'}
</button>
) : null}
</div>
{error ? <p style={{ color: 'crimson', margin: 0 }}>{error}</p> : null}
{successMessage ? <p style={{ color: 'green', margin: 0 }}>{successMessage}</p> : null}
{preview ? (
<div style={{ display: 'grid', gap: '1rem' }}>
<div
style={{
display: 'grid',
gap: '1rem',
gridTemplateColumns: '1fr 1fr',
}}
>
<article style={{ border: '1px solid #ddd', borderRadius: '8px', padding: '1rem' }}>
<h3 style={{ marginTop: 0 }}>Source</h3>
<div><strong>ID:</strong> {preview.source.id}</div>
<div><strong>Namn:</strong> {preview.source.name}</div>
<div><strong>Canonical:</strong> {preview.source.canonicalName || 'Saknas'}</div>
<div><strong>Normalized:</strong> {preview.source.normalizedName}</div>
<div><strong>Aktiv:</strong> {preview.source.isActive ? 'Ja' : 'Nej'}</div>
<div><strong>Inventory count:</strong> {preview.source.inventoryCount}</div>
</article>
<article style={{ border: '1px solid #ddd', borderRadius: '8px', padding: '1rem' }}>
<h3 style={{ marginTop: 0 }}>Target</h3>
<div><strong>ID:</strong> {preview.target.id}</div>
<div><strong>Namn:</strong> {preview.target.name}</div>
<div><strong>Canonical:</strong> {preview.target.canonicalName || 'Saknas'}</div>
<div><strong>Normalized:</strong> {preview.target.normalizedName}</div>
<div><strong>Aktiv:</strong> {preview.target.isActive ? 'Ja' : 'Nej'}</div>
<div><strong>Inventory count:</strong> {preview.target.inventoryCount}</div>
</article>
</div> </div>
<article <div style={{ display: 'flex', gap: '0.75rem', flexWrap: 'wrap' }}>
style={{ <button
border: '1px solid #ddd', type="button"
borderRadius: '8px', onClick={fetchPreview}
padding: '1rem', disabled={isPending}
background: '#fafafa',
}}
>
<h3 style={{ marginTop: 0 }}>Det här kommer att hända</h3>
<div>
<strong>Inventory som flyttas:</strong> {preview.outcome.inventoryItemsToMove}
</div>
<div>
<strong>Source soft-deletas:</strong>{' '}
{preview.outcome.sourceWillBeSoftDeleted ? 'Ja' : 'Nej'}
</div>
<div>
<strong>Target förblir aktiv:</strong>{' '}
{preview.outcome.targetWillRemainActive ? 'Ja' : 'Nej'}
</div>
</article>
{isConfirming ? (
<article
style={{ style={{
border: '1px solid #e0b4b4', padding: '0.75rem 1.5rem',
borderRadius: '8px', background: '#0070f3',
padding: '1rem', color: 'white',
background: '#fff6f6', border: 'none',
display: 'grid', borderRadius: '4px',
gap: '0.75rem', cursor: 'pointer',
fontSize: '1rem',
minHeight: '44px',
fontWeight: 600,
}} }}
> >
<h3 style={{ marginTop: 0 }}>Bekräfta merge</h3> {isPending ? 'Hämtar preview...' : 'Förhandsgranska merge'}
<p style={{ margin: 0 }}> </button>
Du är väg att slå ihop{' '}
<strong>{preview.source.canonicalName || preview.source.name}</strong> in i{' '}
<strong>{preview.target.canonicalName || preview.target.name}</strong>.
</p>
<p style={{ margin: 0 }}>
Source-produkten kommer att soft-deletas och kan återställas senare, men
inventory flyttas till target.
</p>
<div style={{ display: 'flex', gap: '0.75rem', flexWrap: 'wrap' }}> {preview ? (
<button <button
type="button" type="button"
onClick={confirmMerge} onClick={() => setIsConfirming((prev) => !prev)}
disabled={isPending} disabled={isPending}
style={{ style={{
padding: '0.75rem 1.5rem', padding: '0.75rem 1.5rem',
background: '#c0392b', background: '#f0f0f0',
color: 'white', color: '#333',
border: 'none', border: '1px solid #ccc',
borderRadius: '4px', borderRadius: '4px',
cursor: 'pointer', cursor: 'pointer',
fontSize: '1rem', fontSize: '1rem',
minHeight: '44px', minHeight: '44px',
fontWeight: 600, fontWeight: 600,
}} }}
> >
{isPending ? 'Slår ihop...' : 'Bekräfta merge'} {isConfirming ? 'Avbryt bekräftelse' : 'Gå vidare till bekräftelse'}
</button> </button>
) : null}
</div>
<button {error ? <p style={{ color: 'crimson', margin: 0 }}>{error}</p> : null}
type="button" {successMessage ? <p style={{ color: 'green', margin: 0 }}>{successMessage}</p> : null}
onClick={() => setIsConfirming(false)}
disabled={isPending} {preview ? (
style={{ <div style={{ display: 'grid', gap: '1rem' }}>
padding: '0.75rem 1.5rem', <div
background: '#f0f0f0', style={{
color: '#333', display: 'grid',
border: '1px solid #ccc', gap: '1rem',
borderRadius: '4px', gridTemplateColumns: '1fr 1fr',
cursor: 'pointer', }}
fontSize: '1rem', >
minHeight: '44px', <article style={{ border: '1px solid #ddd', borderRadius: '8px', padding: '1rem' }}>
fontWeight: 600, <h3 style={{ marginTop: 0 }}>Source</h3>
}} <div><strong>ID:</strong> {preview.source.id}</div>
> <div><strong>Namn:</strong> {preview.source.name}</div>
Avbryt <div><strong>Canonical:</strong> {preview.source.canonicalName || 'Saknas'}</div>
</button> <div><strong>Normalized:</strong> {preview.source.normalizedName}</div>
<div><strong>Aktiv:</strong> {preview.source.isActive ? 'Ja' : 'Nej'}</div>
<div><strong>Inventory count:</strong> {preview.source.inventoryCount}</div>
</article>
<article style={{ border: '1px solid #ddd', borderRadius: '8px', padding: '1rem' }}>
<h3 style={{ marginTop: 0 }}>Target</h3>
<div><strong>ID:</strong> {preview.target.id}</div>
<div><strong>Namn:</strong> {preview.target.name}</div>
<div><strong>Canonical:</strong> {preview.target.canonicalName || 'Saknas'}</div>
<div><strong>Normalized:</strong> {preview.target.normalizedName}</div>
<div><strong>Aktiv:</strong> {preview.target.isActive ? 'Ja' : 'Nej'}</div>
<div><strong>Inventory count:</strong> {preview.target.inventoryCount}</div>
</article>
</div> </div>
</article>
<article
style={{
border: '1px solid #ddd',
borderRadius: '8px',
padding: '1rem',
background: '#fafafa',
}}
>
<h3 style={{ marginTop: 0 }}>Det här kommer att hända</h3>
<div>
<strong>Inventory som flyttas:</strong> {preview.outcome.inventoryItemsToMove}
</div>
<div>
<strong>Source soft-deletas:</strong>{' '}
{preview.outcome.sourceWillBeSoftDeleted ? 'Ja' : 'Nej'}
</div>
<div>
<strong>Target förblir aktiv:</strong>{' '}
{preview.outcome.targetWillRemainActive ? 'Ja' : 'Nej'}
</div>
</article>
{isConfirming ? (
<article
style={{
border: '1px solid #e0b4b4',
borderRadius: '8px',
padding: '1rem',
background: '#fff6f6',
display: 'grid',
gap: '0.75rem',
}}
>
<h3 style={{ marginTop: 0 }}>Bekräfta merge</h3>
<p style={{ margin: 0 }}>
Du är väg att slå ihop{' '}
<strong>{preview.source.canonicalName || preview.source.name}</strong> in i{' '}
<strong>{preview.target.canonicalName || preview.target.name}</strong>.
</p>
<p style={{ margin: 0 }}>
Source-produkten kommer att soft-deletas och kan återställas senare, men
inventory flyttas till target.
</p>
<div style={{ display: 'flex', gap: '0.75rem', flexWrap: 'wrap' }}>
<button
type="button"
onClick={confirmMerge}
disabled={isPending}
style={{
padding: '0.75rem 1.5rem',
background: '#c0392b',
color: 'white',
border: 'none',
borderRadius: '4px',
cursor: 'pointer',
fontSize: '1rem',
minHeight: '44px',
fontWeight: 600,
}}
>
{isPending ? 'Slår ihop...' : 'Bekräfta merge'}
</button>
<button
type="button"
onClick={() => setIsConfirming(false)}
disabled={isPending}
style={{
padding: '0.75rem 1.5rem',
background: '#f0f0f0',
color: '#333',
border: '1px solid #ccc',
borderRadius: '4px',
cursor: 'pointer',
fontSize: '1rem',
minHeight: '44px',
fontWeight: 600,
}}
>
Avbryt
</button>
</div>
</article>
) : null}
</div>
) : null} ) : null}
</div> </div>
)} )}