Fix image handling in forms
This commit is contained in:
parent
5edc7eb33b
commit
b3c9529e3f
11 changed files with 293 additions and 81 deletions
|
|
@ -18,12 +18,12 @@
|
||||||
{/if}
|
{/if}
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
|
{@render children?.()}
|
||||||
|
|
||||||
{#if helpText}
|
{#if helpText}
|
||||||
<p class="help-text">{helpText}</p>
|
<p class="help-text">{helpText}</p>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{@render children?.()}
|
|
||||||
|
|
||||||
{#if error}
|
{#if error}
|
||||||
<p class="error-text">{error}</p>
|
<p class="error-text">{error}</p>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
@ -39,7 +39,8 @@
|
||||||
|
|
||||||
&.has-error {
|
&.has-error {
|
||||||
:global(input),
|
:global(input),
|
||||||
:global(textarea) {
|
:global(textarea),
|
||||||
|
:global(select) {
|
||||||
border-color: #c33;
|
border-color: #c33;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
label: string
|
label: string
|
||||||
value?: Media | null
|
value?: Media | null
|
||||||
onUpload: (media: Media) => void
|
onUpload: (media: Media) => void
|
||||||
|
onRemove?: () => void
|
||||||
aspectRatio?: string // e.g., "16:9", "1:1"
|
aspectRatio?: string // e.g., "16:9", "1:1"
|
||||||
required?: boolean
|
required?: boolean
|
||||||
error?: string
|
error?: string
|
||||||
|
|
@ -26,6 +27,7 @@
|
||||||
label,
|
label,
|
||||||
value = $bindable(),
|
value = $bindable(),
|
||||||
onUpload,
|
onUpload,
|
||||||
|
onRemove,
|
||||||
aspectRatio,
|
aspectRatio,
|
||||||
required = false,
|
required = false,
|
||||||
error,
|
error,
|
||||||
|
|
@ -182,6 +184,7 @@
|
||||||
altTextValue = ''
|
altTextValue = ''
|
||||||
descriptionValue = ''
|
descriptionValue = ''
|
||||||
uploadError = null
|
uploadError = null
|
||||||
|
onRemove?.()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update alt text on server
|
// Update alt text on server
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,26 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Input from './Input.svelte'
|
import Input from './Input.svelte'
|
||||||
import ImageUploader from './ImageUploader.svelte'
|
import ImageUploader from './ImageUploader.svelte'
|
||||||
|
import Button from './Button.svelte'
|
||||||
import type { ProjectFormData } from '$lib/types/project'
|
import type { ProjectFormData } from '$lib/types/project'
|
||||||
import type { Media } from '@prisma/client'
|
import type { Media } from '@prisma/client'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
formData: ProjectFormData
|
formData: ProjectFormData
|
||||||
|
onSave?: () => Promise<void>
|
||||||
}
|
}
|
||||||
|
|
||||||
let { formData = $bindable() }: Props = $props()
|
let { formData = $bindable(), onSave }: Props = $props()
|
||||||
|
|
||||||
|
// State for collapsible logo section
|
||||||
|
let showLogoSection = $state(!!formData.logoUrl && formData.logoUrl.trim() !== '')
|
||||||
|
|
||||||
// Convert logoUrl string to Media object for ImageUploader
|
// Convert logoUrl string to Media object for ImageUploader
|
||||||
let logoMedia = $state<Media | null>(null)
|
let logoMedia = $state<Media | null>(null)
|
||||||
|
|
||||||
// Update logoMedia when logoUrl changes
|
// Update logoMedia when logoUrl changes
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
if (formData.logoUrl && !logoMedia) {
|
if (formData.logoUrl && formData.logoUrl.trim() !== '' && !logoMedia) {
|
||||||
// Create a minimal Media object from the URL for display
|
// Create a minimal Media object from the URL for display
|
||||||
logoMedia = {
|
logoMedia = {
|
||||||
id: -1, // Temporary ID for existing URLs
|
id: -1, // Temporary ID for existing URLs
|
||||||
|
|
@ -33,8 +38,13 @@
|
||||||
createdAt: new Date(),
|
createdAt: new Date(),
|
||||||
updatedAt: new Date()
|
updatedAt: new Date()
|
||||||
}
|
}
|
||||||
} else if (!formData.logoUrl) {
|
}
|
||||||
logoMedia = null
|
})
|
||||||
|
|
||||||
|
// Sync logoMedia changes back to formData
|
||||||
|
$effect(() => {
|
||||||
|
if (!logoMedia && formData.logoUrl) {
|
||||||
|
formData.logoUrl = ''
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -43,19 +53,53 @@
|
||||||
logoMedia = media
|
logoMedia = media
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleLogoRemove() {
|
async function handleLogoRemove() {
|
||||||
formData.logoUrl = ''
|
formData.logoUrl = ''
|
||||||
logoMedia = null
|
logoMedia = null
|
||||||
|
showLogoSection = false
|
||||||
|
|
||||||
|
// Auto-save the removal
|
||||||
|
if (onSave) {
|
||||||
|
await onSave()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="form-section">
|
<div class="form-section">
|
||||||
<h2>Branding</h2>
|
<h2>Branding</h2>
|
||||||
|
|
||||||
|
{#if !showLogoSection && (!formData.logoUrl || formData.logoUrl.trim() === '')}
|
||||||
|
<Button
|
||||||
|
variant="secondary"
|
||||||
|
buttonSize="medium"
|
||||||
|
onclick={() => showLogoSection = true}
|
||||||
|
iconPosition="left"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
slot="icon"
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
>
|
||||||
|
<rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect>
|
||||||
|
<line x1="12" y1="3" x2="12" y2="21"></line>
|
||||||
|
<line x1="3" y1="12" x2="21" y2="12"></line>
|
||||||
|
</svg>
|
||||||
|
Add Project Logo
|
||||||
|
</Button>
|
||||||
|
{:else}
|
||||||
|
<div class="collapsible-section">
|
||||||
|
<div class="section-header">
|
||||||
|
<h3>Project Logo</h3>
|
||||||
|
</div>
|
||||||
<ImageUploader
|
<ImageUploader
|
||||||
label="Project Logo"
|
label=""
|
||||||
value={logoMedia}
|
bind:value={logoMedia}
|
||||||
onUpload={handleLogoUpload}
|
onUpload={handleLogoUpload}
|
||||||
|
onRemove={handleLogoRemove}
|
||||||
aspectRatio="1:1"
|
aspectRatio="1:1"
|
||||||
allowAltText={true}
|
allowAltText={true}
|
||||||
maxFileSize={0.5}
|
maxFileSize={0.5}
|
||||||
|
|
@ -65,6 +109,8 @@
|
||||||
compact={true}
|
compact={true}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.form-section {
|
.form-section {
|
||||||
|
|
@ -81,4 +127,23 @@
|
||||||
color: $grey-10;
|
color: $grey-10;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.collapsible-section {
|
||||||
|
// No border or background needed
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: $unit-2x;
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
font-weight: 600;
|
||||||
|
margin: 0;
|
||||||
|
color: $grey-20;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@
|
||||||
import Editor from './Editor.svelte'
|
import Editor from './Editor.svelte'
|
||||||
import ProjectMetadataForm from './ProjectMetadataForm.svelte'
|
import ProjectMetadataForm from './ProjectMetadataForm.svelte'
|
||||||
import ProjectBrandingForm from './ProjectBrandingForm.svelte'
|
import ProjectBrandingForm from './ProjectBrandingForm.svelte'
|
||||||
import ProjectGalleryForm from './ProjectGalleryForm.svelte'
|
|
||||||
import ProjectStylingForm from './ProjectStylingForm.svelte'
|
import ProjectStylingForm from './ProjectStylingForm.svelte'
|
||||||
import Button from './Button.svelte'
|
import Button from './Button.svelte'
|
||||||
import StatusDropdown from './StatusDropdown.svelte'
|
import StatusDropdown from './StatusDropdown.svelte'
|
||||||
|
|
@ -60,11 +59,10 @@
|
||||||
role: data.role || '',
|
role: data.role || '',
|
||||||
projectType: data.projectType || 'work',
|
projectType: data.projectType || 'work',
|
||||||
externalUrl: data.externalUrl || '',
|
externalUrl: data.externalUrl || '',
|
||||||
featuredImage: data.featuredImage || null,
|
featuredImage: data.featuredImage && data.featuredImage.trim() !== '' ? data.featuredImage : null,
|
||||||
backgroundColor: data.backgroundColor || '',
|
backgroundColor: data.backgroundColor || '',
|
||||||
highlightColor: data.highlightColor || '',
|
highlightColor: data.highlightColor || '',
|
||||||
logoUrl: data.logoUrl || '',
|
logoUrl: data.logoUrl && data.logoUrl.trim() !== '' ? data.logoUrl : '',
|
||||||
gallery: data.gallery || null,
|
|
||||||
status: data.status || 'draft',
|
status: data.status || 'draft',
|
||||||
password: data.password || '',
|
password: data.password || '',
|
||||||
caseStudyContent: data.caseStudyContent || {
|
caseStudyContent: data.caseStudyContent || {
|
||||||
|
|
@ -142,9 +140,8 @@
|
||||||
role: formData.role,
|
role: formData.role,
|
||||||
projectType: formData.projectType,
|
projectType: formData.projectType,
|
||||||
externalUrl: formData.externalUrl,
|
externalUrl: formData.externalUrl,
|
||||||
featuredImage: formData.featuredImage,
|
featuredImage: formData.featuredImage && formData.featuredImage !== '' ? formData.featuredImage : null,
|
||||||
logoUrl: formData.logoUrl,
|
logoUrl: formData.logoUrl && formData.logoUrl !== '' ? formData.logoUrl : null,
|
||||||
gallery: formData.gallery && formData.gallery.length > 0 ? formData.gallery : null,
|
|
||||||
backgroundColor: formData.backgroundColor,
|
backgroundColor: formData.backgroundColor,
|
||||||
highlightColor: formData.highlightColor,
|
highlightColor: formData.highlightColor,
|
||||||
status: formData.status,
|
status: formData.status,
|
||||||
|
|
@ -266,9 +263,8 @@
|
||||||
handleSave()
|
handleSave()
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ProjectMetadataForm bind:formData {validationErrors} />
|
<ProjectMetadataForm bind:formData {validationErrors} onSave={handleSave} />
|
||||||
<ProjectBrandingForm bind:formData />
|
<ProjectBrandingForm bind:formData onSave={handleSave} />
|
||||||
<ProjectGalleryForm bind:formData />
|
|
||||||
<ProjectStylingForm bind:formData {validationErrors} />
|
<ProjectStylingForm bind:formData {validationErrors} />
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,71 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Input from './Input.svelte'
|
import Input from './Input.svelte'
|
||||||
import Select from './Select.svelte'
|
import SelectField from './SelectField.svelte'
|
||||||
import ImageUploader from './ImageUploader.svelte'
|
import ImageUploader from './ImageUploader.svelte'
|
||||||
|
import Button from './Button.svelte'
|
||||||
import type { ProjectFormData } from '$lib/types/project'
|
import type { ProjectFormData } from '$lib/types/project'
|
||||||
|
import type { Media } from '@prisma/client'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
formData: ProjectFormData
|
formData: ProjectFormData
|
||||||
validationErrors: Record<string, string>
|
validationErrors: Record<string, string>
|
||||||
|
onSave?: () => Promise<void>
|
||||||
}
|
}
|
||||||
|
|
||||||
let { formData = $bindable(), validationErrors }: Props = $props()
|
let { formData = $bindable(), validationErrors, onSave }: Props = $props()
|
||||||
|
|
||||||
|
// State for collapsible featured image section
|
||||||
|
let showFeaturedImage = $state(!!formData.featuredImage && formData.featuredImage !== '' && formData.featuredImage !== null)
|
||||||
|
|
||||||
|
// Convert featuredImage string to Media object for ImageUploader
|
||||||
|
let featuredImageMedia = $state<Media | null>(null)
|
||||||
|
|
||||||
|
// Initialize media object from existing featuredImage URL
|
||||||
|
$effect(() => {
|
||||||
|
if (formData.featuredImage && formData.featuredImage !== '' && formData.featuredImage !== null && !featuredImageMedia) {
|
||||||
|
// Only create a minimal Media object if we don't already have one
|
||||||
|
featuredImageMedia = {
|
||||||
|
id: -1, // Temporary ID for existing URLs
|
||||||
|
filename: 'featured-image',
|
||||||
|
originalName: 'featured-image',
|
||||||
|
mimeType: 'image/jpeg',
|
||||||
|
size: 0,
|
||||||
|
url: formData.featuredImage,
|
||||||
|
thumbnailUrl: formData.featuredImage,
|
||||||
|
width: null,
|
||||||
|
height: null,
|
||||||
|
altText: null,
|
||||||
|
description: null,
|
||||||
|
usedIn: [],
|
||||||
|
createdAt: new Date(),
|
||||||
|
updatedAt: new Date()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Sync featuredImageMedia changes back to formData
|
||||||
|
$effect(() => {
|
||||||
|
if (!featuredImageMedia && formData.featuredImage) {
|
||||||
|
formData.featuredImage = ''
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
function handleFeaturedImageUpload(media: Media) {
|
function handleFeaturedImageUpload(media: Media) {
|
||||||
formData.featuredImage = media.url
|
formData.featuredImage = media.url
|
||||||
|
featuredImageMedia = media
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function handleFeaturedImageRemove() {
|
||||||
|
formData.featuredImage = ''
|
||||||
|
featuredImageMedia = null
|
||||||
|
showFeaturedImage = false
|
||||||
|
|
||||||
|
// Auto-save the removal
|
||||||
|
if (onSave) {
|
||||||
|
await onSave()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="form-section">
|
<div class="form-section">
|
||||||
|
|
@ -34,7 +86,7 @@
|
||||||
placeholder="Short description for project cards"
|
placeholder="Short description for project cards"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Select
|
<SelectField
|
||||||
label="Project Type"
|
label="Project Type"
|
||||||
bind:value={formData.projectType}
|
bind:value={formData.projectType}
|
||||||
error={validationErrors.projectType}
|
error={validationErrors.projectType}
|
||||||
|
|
@ -72,26 +124,43 @@
|
||||||
placeholder="https://example.com"
|
placeholder="https://example.com"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{#if !showFeaturedImage}
|
||||||
|
<Button
|
||||||
|
variant="secondary"
|
||||||
|
buttonSize="medium"
|
||||||
|
onclick={() => showFeaturedImage = true}
|
||||||
|
iconPosition="left"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
slot="icon"
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
>
|
||||||
|
<rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect>
|
||||||
|
<circle cx="8.5" cy="8.5" r="1.5"></circle>
|
||||||
|
<polyline points="21 15 16 10 5 21"></polyline>
|
||||||
|
</svg>
|
||||||
|
Add Featured Image
|
||||||
|
</Button>
|
||||||
|
{:else if showFeaturedImage}
|
||||||
|
<div class="collapsible-section">
|
||||||
|
<div class="section-header">
|
||||||
|
<h3>Featured Image</h3>
|
||||||
|
</div>
|
||||||
<ImageUploader
|
<ImageUploader
|
||||||
label="Featured Image"
|
label=""
|
||||||
value={null}
|
bind:value={featuredImageMedia}
|
||||||
onUpload={handleFeaturedImageUpload}
|
onUpload={handleFeaturedImageUpload}
|
||||||
|
onRemove={handleFeaturedImageRemove}
|
||||||
placeholder="Upload a featured image for this project"
|
placeholder="Upload a featured image for this project"
|
||||||
showBrowseLibrary={true}
|
showBrowseLibrary={true}
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
<Select
|
{/if}
|
||||||
label="Project Status"
|
|
||||||
bind:value={formData.status}
|
|
||||||
error={validationErrors.status}
|
|
||||||
options={[
|
|
||||||
{ value: 'draft', label: 'Draft (Hidden)' },
|
|
||||||
{ value: 'published', label: 'Published' },
|
|
||||||
{ value: 'list-only', label: 'List Only (No Access)' },
|
|
||||||
{ value: 'password-protected', label: 'Password Protected' }
|
|
||||||
]}
|
|
||||||
helpText="Control how this project appears on the public site"
|
|
||||||
/>
|
|
||||||
|
|
||||||
{#if formData.status === 'password-protected'}
|
{#if formData.status === 'password-protected'}
|
||||||
<Input
|
<Input
|
||||||
|
|
@ -127,4 +196,23 @@
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.collapsible-section {
|
||||||
|
// No border or background needed
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: $unit-2x;
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
font-weight: 600;
|
||||||
|
margin: 0;
|
||||||
|
color: $grey-20;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@
|
||||||
.select-wrapper {
|
.select-wrapper {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.select {
|
.select {
|
||||||
|
|
@ -59,6 +60,7 @@
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
appearance: none;
|
appearance: none;
|
||||||
padding-right: 36px;
|
padding-right: 36px;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
&:focus {
|
&:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
|
|
|
||||||
60
src/lib/components/admin/SelectField.svelte
Normal file
60
src/lib/components/admin/SelectField.svelte
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import Select from './Select.svelte'
|
||||||
|
import FormFieldWrapper from './FormFieldWrapper.svelte'
|
||||||
|
import type { HTMLSelectAttributes } from 'svelte/elements'
|
||||||
|
|
||||||
|
interface Option {
|
||||||
|
value: string
|
||||||
|
label: string
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Props extends Omit<HTMLSelectAttributes, 'size'> {
|
||||||
|
label: string
|
||||||
|
options: Option[]
|
||||||
|
value?: string
|
||||||
|
size?: 'small' | 'medium' | 'large'
|
||||||
|
variant?: 'default' | 'minimal'
|
||||||
|
fullWidth?: boolean
|
||||||
|
pill?: boolean
|
||||||
|
required?: boolean
|
||||||
|
helpText?: string
|
||||||
|
error?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
let {
|
||||||
|
label,
|
||||||
|
options,
|
||||||
|
value = $bindable(),
|
||||||
|
size = 'medium',
|
||||||
|
variant = 'default',
|
||||||
|
fullWidth = true,
|
||||||
|
pill = true,
|
||||||
|
required = false,
|
||||||
|
helpText,
|
||||||
|
error,
|
||||||
|
...restProps
|
||||||
|
}: Props = $props()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<FormFieldWrapper {label} {required} {helpText} {error}>
|
||||||
|
{#snippet children()}
|
||||||
|
<Select
|
||||||
|
bind:value
|
||||||
|
{options}
|
||||||
|
{size}
|
||||||
|
{variant}
|
||||||
|
{fullWidth}
|
||||||
|
{pill}
|
||||||
|
{...restProps}
|
||||||
|
/>
|
||||||
|
{/snippet}
|
||||||
|
</FormFieldWrapper>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
// Ensure proper spacing for select fields
|
||||||
|
:global(.form-field) {
|
||||||
|
:global(.select-wrapper) {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -12,7 +12,6 @@ export interface Project {
|
||||||
role: string | null
|
role: string | null
|
||||||
featuredImage: string | null
|
featuredImage: string | null
|
||||||
logoUrl: string | null
|
logoUrl: string | null
|
||||||
gallery: any[] | null
|
|
||||||
externalUrl: string | null
|
externalUrl: string | null
|
||||||
caseStudyContent: any | null
|
caseStudyContent: any | null
|
||||||
backgroundColor: string | null
|
backgroundColor: string | null
|
||||||
|
|
@ -39,7 +38,6 @@ export interface ProjectFormData {
|
||||||
backgroundColor: string
|
backgroundColor: string
|
||||||
highlightColor: string
|
highlightColor: string
|
||||||
logoUrl: string
|
logoUrl: string
|
||||||
gallery: any[] | null
|
|
||||||
status: ProjectStatus
|
status: ProjectStatus
|
||||||
password: string
|
password: string
|
||||||
caseStudyContent: any
|
caseStudyContent: any
|
||||||
|
|
@ -58,7 +56,6 @@ export const defaultProjectFormData: ProjectFormData = {
|
||||||
backgroundColor: '',
|
backgroundColor: '',
|
||||||
highlightColor: '',
|
highlightColor: '',
|
||||||
logoUrl: '',
|
logoUrl: '',
|
||||||
gallery: null,
|
|
||||||
status: 'draft',
|
status: 'draft',
|
||||||
password: '',
|
password: '',
|
||||||
caseStudyContent: {
|
caseStudyContent: {
|
||||||
|
|
|
||||||
|
|
@ -134,15 +134,15 @@ export const PUT: RequestHandler = async (event) => {
|
||||||
const album = await prisma.album.update({
|
const album = await prisma.album.update({
|
||||||
where: { id },
|
where: { id },
|
||||||
data: {
|
data: {
|
||||||
slug: body.slug ?? existing.slug,
|
slug: body.slug !== undefined ? body.slug : existing.slug,
|
||||||
title: body.title ?? existing.title,
|
title: body.title !== undefined ? body.title : existing.title,
|
||||||
description: body.description !== undefined ? body.description : existing.description,
|
description: body.description !== undefined ? body.description : existing.description,
|
||||||
date: body.date !== undefined ? (body.date ? new Date(body.date) : null) : existing.date,
|
date: body.date !== undefined ? (body.date ? new Date(body.date) : null) : existing.date,
|
||||||
location: body.location !== undefined ? body.location : existing.location,
|
location: body.location !== undefined ? body.location : existing.location,
|
||||||
coverPhotoId: body.coverPhotoId !== undefined ? body.coverPhotoId : existing.coverPhotoId,
|
coverPhotoId: body.coverPhotoId !== undefined ? body.coverPhotoId : existing.coverPhotoId,
|
||||||
isPhotography: body.isPhotography ?? existing.isPhotography,
|
isPhotography: body.isPhotography !== undefined ? body.isPhotography : existing.isPhotography,
|
||||||
status: body.status ?? existing.status,
|
status: body.status !== undefined ? body.status : existing.status,
|
||||||
showInUniverse: body.showInUniverse ?? existing.showInUniverse
|
showInUniverse: body.showInUniverse !== undefined ? body.showInUniverse : existing.showInUniverse
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -68,9 +68,9 @@ export const PUT: RequestHandler = async (event) => {
|
||||||
const media = await prisma.media.update({
|
const media = await prisma.media.update({
|
||||||
where: { id },
|
where: { id },
|
||||||
data: {
|
data: {
|
||||||
altText: body.altText ?? existing.altText,
|
altText: body.altText !== undefined ? body.altText : existing.altText,
|
||||||
description: body.description ?? existing.description,
|
description: body.description !== undefined ? body.description : existing.description,
|
||||||
isPhotography: body.isPhotography ?? existing.isPhotography
|
isPhotography: body.isPhotography !== undefined ? body.isPhotography : existing.isPhotography
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -76,23 +76,23 @@ export const PUT: RequestHandler = async (event) => {
|
||||||
where: { id },
|
where: { id },
|
||||||
data: {
|
data: {
|
||||||
slug,
|
slug,
|
||||||
title: body.title ?? existing.title,
|
title: body.title !== undefined ? body.title : existing.title,
|
||||||
subtitle: body.subtitle ?? existing.subtitle,
|
subtitle: body.subtitle !== undefined ? body.subtitle : existing.subtitle,
|
||||||
description: body.description ?? existing.description,
|
description: body.description !== undefined ? body.description : existing.description,
|
||||||
year: body.year ?? existing.year,
|
year: body.year !== undefined ? body.year : existing.year,
|
||||||
client: body.client ?? existing.client,
|
client: body.client !== undefined ? body.client : existing.client,
|
||||||
role: body.role ?? existing.role,
|
role: body.role !== undefined ? body.role : existing.role,
|
||||||
featuredImage: body.featuredImage ?? existing.featuredImage,
|
featuredImage: body.featuredImage !== undefined ? body.featuredImage : existing.featuredImage,
|
||||||
logoUrl: body.logoUrl ?? existing.logoUrl,
|
logoUrl: body.logoUrl !== undefined ? body.logoUrl : existing.logoUrl,
|
||||||
gallery: body.gallery ?? existing.gallery,
|
gallery: body.gallery !== undefined ? body.gallery : existing.gallery,
|
||||||
externalUrl: body.externalUrl ?? existing.externalUrl,
|
externalUrl: body.externalUrl !== undefined ? body.externalUrl : existing.externalUrl,
|
||||||
caseStudyContent: body.caseStudyContent ?? existing.caseStudyContent,
|
caseStudyContent: body.caseStudyContent !== undefined ? body.caseStudyContent : existing.caseStudyContent,
|
||||||
backgroundColor: body.backgroundColor ?? existing.backgroundColor,
|
backgroundColor: body.backgroundColor !== undefined ? body.backgroundColor : existing.backgroundColor,
|
||||||
highlightColor: body.highlightColor ?? existing.highlightColor,
|
highlightColor: body.highlightColor !== undefined ? body.highlightColor : existing.highlightColor,
|
||||||
projectType: body.projectType ?? existing.projectType,
|
projectType: body.projectType !== undefined ? body.projectType : existing.projectType,
|
||||||
displayOrder: body.displayOrder ?? existing.displayOrder,
|
displayOrder: body.displayOrder !== undefined ? body.displayOrder : existing.displayOrder,
|
||||||
status: body.status ?? existing.status,
|
status: body.status !== undefined ? body.status : existing.status,
|
||||||
password: body.password ?? existing.password,
|
password: body.password !== undefined ? body.password : existing.password,
|
||||||
publishedAt:
|
publishedAt:
|
||||||
body.status === 'published' && !existing.publishedAt ? new Date() : existing.publishedAt
|
body.status === 'published' && !existing.publishedAt ? new Date() : existing.publishedAt
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue